Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
forked fromtorvalds/linux

Commitfff377d

Browse files
author
Jon Ayers
committed
whiteout patch
1 parentf36b753 commitfff377d

File tree

6 files changed

+161
-10
lines changed

6 files changed

+161
-10
lines changed

‎fs/overlayfs/dir.c‎

Lines changed: 144 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ module_param_named(redirect_max, ovl_redirect_max, ushort, 0644);
2424
MODULE_PARM_DESC(ovl_redirect_max,
2525
"Maximum length of absolute redirect xattr value");
2626

27+
staticunsignedintovl_singleton_wt_link_max=255;
28+
module_param_named(singleton_whiteout_link_max,
29+
ovl_singleton_wt_link_max,uint,0644);
30+
MODULE_PARM_DESC(ovl_singleton_wt_link_max,
31+
"Maximum hardlinks of a whiteout singleton");
32+
2733
intovl_cleanup(structinode*wdir,structdentry*wdentry)
2834
{
2935
interr;
@@ -62,18 +68,149 @@ struct dentry *ovl_lookup_temp(struct dentry *workdir)
6268
returntemp;
6369
}
6470

71+
#defineOVL_SINGLETON_WHITEOUT_NAME "whiteout"
72+
73+
/* caller holds write lock (i_rwsem) of dir */
74+
staticintovl_make_singleton_whiteout_locked(structovl_fs*ofs,
75+
structdentry*dir,constchar*name)
76+
{
77+
interr=0;
78+
structinode*inode=d_inode(dir);
79+
structdentry*whiteout;
80+
81+
whiteout=lookup_one_len(name,dir,strlen(name));
82+
if (IS_ERR(whiteout))
83+
returnPTR_ERR(whiteout);
84+
85+
if (ovl_is_whiteout(whiteout)) {
86+
ofs->whiteout=whiteout;
87+
}elseif (!whiteout->d_inode) {
88+
err=ovl_do_whiteout(inode,whiteout);
89+
if (!err)
90+
ofs->whiteout=whiteout;
91+
else
92+
dput(whiteout);
93+
}else {
94+
/*
95+
* fallback to creating new whiteout file if
96+
* a non-whiteout file already exists
97+
*/
98+
dput(whiteout);
99+
}
100+
101+
returnerr;
102+
}
103+
104+
/*
105+
* create a new whiteout file under workdir if it doesn't exist.
106+
* If a non-whiteout file already exists, no error will be reported
107+
* and the needed whiteout file will be newly created instead of
108+
* being linked to a singleton whiteout.
109+
*/
110+
intovl_make_singleton_whiteout(structovl_fs*ofs)
111+
{
112+
interr;
113+
structinode*dir;
114+
115+
/* disable singleton whiteout */
116+
if (ovl_singleton_wt_link_max <=1)
117+
return0;
118+
119+
dir=d_inode(ofs->workdir);
120+
inode_lock_nested(dir,I_MUTEX_PARENT);
121+
122+
err=ovl_make_singleton_whiteout_locked(ofs,ofs->workdir,
123+
OVL_SINGLETON_WHITEOUT_NAME);
124+
125+
inode_unlock(dir);
126+
127+
returnerr;
128+
}
129+
130+
/*
131+
* caller holds i_mutex of workdir to ensure the operations
132+
* on the singletion whiteout are serialized.
133+
*/
134+
staticintovl_link_to_singleton_whiteout(structovl_fs*ofs,
135+
structdentry*whiteout,bool*create_instead)
136+
{
137+
interr;
138+
structinode*wdir=d_inode(ofs->workdir);
139+
structdentry*singleton;
140+
boolretried= false;
141+
142+
*create_instead= false;
143+
retry:
144+
singleton=ofs->whiteout;
145+
/* Create a new singletion whiteout when the limit is exceeded */
146+
if (1<ovl_singleton_wt_link_max&&
147+
singleton->d_inode->i_nlink >=ovl_singleton_wt_link_max)
148+
err=-EMLINK;
149+
else
150+
err=ovl_do_link(singleton,wdir,whiteout, false);
151+
152+
if (!err) {
153+
gotoout;
154+
}elseif (err==-EMLINK&& !retried) {
155+
/*
156+
* The singleton already has the maximum number of links to it,
157+
* so remove the old singleton and create a new one
158+
*/
159+
ofs->whiteout=NULL;
160+
err=ovl_do_unlink(wdir,singleton);
161+
if (err) {
162+
dput(singleton);
163+
gotoout;
164+
}
165+
166+
dput(singleton);
167+
err=ovl_make_singleton_whiteout_locked(ofs,ofs->workdir,
168+
OVL_SINGLETON_WHITEOUT_NAME);
169+
if (err)
170+
gotoout;
171+
172+
retried= true;
173+
if (ofs->whiteout)
174+
gotoretry;
175+
else
176+
gotoout_fallback;
177+
}elseif (err==-EXDEV) {
178+
/*
179+
* upper fs may have a project id different than singleton,
180+
* so fall back to create whiteout directly
181+
*/
182+
gotoout_fallback;
183+
}else {
184+
gotoout;
185+
}
186+
187+
out_fallback:
188+
*create_instead= true;
189+
out:
190+
returnerr;
191+
}
192+
65193
/* caller holds i_mutex on workdir */
66-
staticstructdentry*ovl_whiteout(structdentry*workdir)
194+
staticstructdentry*ovl_whiteout(structovl_fs*ofs,structdentry*workdir)
67195
{
68196
interr;
69197
structdentry*whiteout;
70198
structinode*wdir=workdir->d_inode;
199+
boolcreate_instead;
71200

72201
whiteout=ovl_lookup_temp(workdir);
73202
if (IS_ERR(whiteout))
74203
returnwhiteout;
75204

76-
err=ovl_do_whiteout(wdir,whiteout);
205+
if (workdir==ofs->workdir&&ofs->whiteout)
206+
err=ovl_link_to_singleton_whiteout(ofs,whiteout,
207+
&create_instead);
208+
else
209+
create_instead= true;
210+
211+
if (create_instead)
212+
err=ovl_do_whiteout(wdir,whiteout);
213+
77214
if (err) {
78215
dput(whiteout);
79216
whiteout=ERR_PTR(err);
@@ -83,15 +220,15 @@ static struct dentry *ovl_whiteout(struct dentry *workdir)
83220
}
84221

85222
/* Caller must hold i_mutex on both workdir and dir */
86-
intovl_cleanup_and_whiteout(structdentry*workdir,structinode*dir,
87-
structdentry*dentry)
223+
intovl_cleanup_and_whiteout(structovl_fs*ofs,structdentry*workdir,
224+
structinode*dir,structdentry*dentry)
88225
{
89226
structinode*wdir=workdir->d_inode;
90227
structdentry*whiteout;
91228
interr;
92229
intflags=0;
93230

94-
whiteout=ovl_whiteout(workdir);
231+
whiteout=ovl_whiteout(ofs,workdir);
95232
err=PTR_ERR(whiteout);
96233
if (IS_ERR(whiteout))
97234
returnerr;
@@ -621,6 +758,7 @@ static bool ovl_matches_upper(struct dentry *dentry, struct dentry *upper)
621758
staticintovl_remove_and_whiteout(structdentry*dentry,
622759
structlist_head*list)
623760
{
761+
structovl_fs*ofs=dentry->d_sb->s_fs_info;
624762
structdentry*workdir=ovl_workdir(dentry);
625763
structdentry*upperdir=ovl_dentry_upper(dentry->d_parent);
626764
structdentry*upper;
@@ -654,7 +792,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
654792
gotoout_dput_upper;
655793
}
656794

657-
err=ovl_cleanup_and_whiteout(workdir,d_inode(upperdir),upper);
795+
err=ovl_cleanup_and_whiteout(ofs,workdir,d_inode(upperdir),upper);
658796
if (err)
659797
gotoout_d_drop;
660798

‎fs/overlayfs/overlayfs.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,8 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
344344
/* dir.c */
345345
externconststructinode_operationsovl_dir_inode_operations;
346346
structdentry*ovl_lookup_temp(structdentry*workdir);
347-
intovl_cleanup_and_whiteout(structdentry*workdir,structinode*dir,
348-
structdentry*dentry);
347+
intovl_cleanup_and_whiteout(structovl_fs*ofs,structdentry*workdir,
348+
structinode*dir,structdentry*dentry);
349349
structcattr {
350350
dev_trdev;
351351
umode_tmode;
@@ -355,6 +355,7 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry,
355355
structcattr*attr,
356356
structdentry*hardlink,booldebug);
357357
intovl_cleanup(structinode*dir,structdentry*dentry);
358+
intovl_make_singleton_whiteout(structovl_fs*ofs);
358359

359360
/* copy_up.c */
360361
intovl_copy_up(structdentry*dentry);

‎fs/overlayfs/ovl_entry.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ struct ovl_fs {
4343
structdentry*workdir;
4444
/* index directory listing overlay inodes by origin file handle */
4545
structdentry*indexdir;
46+
/*
47+
* the singleton whiteout file under workdir: all newly created
48+
* whiteout files will be linked to it if possible
49+
*/
50+
structdentry*whiteout;
4651
longnamelen;
4752
/* pathnames of lower and upper dirs, for show_options */
4853
structovl_configconfig;

‎fs/overlayfs/readdir.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1084,7 +1084,7 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
10841084
* Whiteout orphan index to block future open by
10851085
* handle after overlay nlink dropped to zero.
10861086
*/
1087-
err=ovl_cleanup_and_whiteout(indexdir,dir,index);
1087+
err=ovl_cleanup_and_whiteout(ofs,indexdir,dir,index);
10881088
}else {
10891089
/* Cleanup orphan index entries */
10901090
err=ovl_cleanup(dir,index);

‎fs/overlayfs/super.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ static void ovl_free_fs(struct ovl_fs *ofs)
229229
unsignedi;
230230

231231
dput(ofs->indexdir);
232+
dput(ofs->whiteout);
232233
dput(ofs->workdir);
233234
if (ofs->workdir_locked)
234235
ovl_inuse_unlock(ofs->workbasedir);
@@ -961,6 +962,10 @@ static int ovl_make_workdir(struct ovl_fs *ofs, struct path *workpath)
961962
if (!ofs->workdir)
962963
gotoout;
963964

965+
err=ovl_make_singleton_whiteout(ofs);
966+
if (err<0)
967+
gotoout;
968+
964969
/*
965970
* Upper should support d_type, else whiteouts are visible. Given
966971
* workdir and upper are on same fs, we can do iterate_dir() on

‎fs/overlayfs/util.c‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,10 @@ static void ovl_cleanup_index(struct dentry *dentry)
533533
if (IS_ERR(index)) {
534534
index=NULL;
535535
}elseif (ovl_index_all(dentry->d_sb)) {
536+
structovl_fs*ofs=dentry->d_sb->s_fs_info;
537+
536538
/* Whiteout orphan index to block future open by handle */
537-
err=ovl_cleanup_and_whiteout(indexdir,dir,index);
539+
err=ovl_cleanup_and_whiteout(ofs,indexdir,dir,index);
538540
}else {
539541
/* Cleanup orphan index entries */
540542
err=ovl_cleanup(dir,index);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp