Skip to content

Commit be3c213

Browse files
committed
Merge tag 'ovl-update-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs
Pull overlayfs update from Amir Goldstein: - fix two NULL pointer deref bugs (Zhihao Cheng) - add support for "data-only" lower layers destined to be used by composefs - port overlayfs to the new mount api (Christian Brauner) * tag 'ovl-update-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs: (26 commits) ovl: add Amir as co-maintainer ovl: reserve ability to reconfigure mount options with new mount api ovl: modify layer parameter parsing ovl: port to new mount api ovl: factor out ovl_parse_options() helper ovl: store enum redirect_mode in config instead of a string ovl: pass ovl_fs to xino helpers ovl: clarify ovl_get_root() semantics ovl: negate the ofs->share_whiteout boolean ovl: check type and offset of struct vfsmount in ovl_entry ovl: implement lazy lookup of lowerdata in data-only layers ovl: prepare for lazy lookup of lowerdata inode ovl: prepare to store lowerdata redirect for lazy lowerdata lookup ovl: implement lookup in data-only layers ovl: introduce data-only lower layers ovl: remove unneeded goto instructions ovl: deduplicate lowerdata and lowerstack[] ovl: deduplicate lowerpath and lowerstack[] ovl: move ovl_entry into ovl_inode ovl: factor out ovl_free_entry() and ovl_stack_*() helpers ...
2 parents eee9c70 + 62149a7 commit be3c213

15 files changed

Lines changed: 1390 additions & 704 deletions

File tree

Documentation/filesystems/overlayfs.rst

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,11 @@ Mount options:
231231
Redirects are enabled.
232232
- "redirect_dir=follow":
233233
Redirects are not created, but followed.
234-
- "redirect_dir=off":
235-
Redirects are not created and only followed if "redirect_always_follow"
236-
feature is enabled in the kernel/module config.
237234
- "redirect_dir=nofollow":
238-
Redirects are not created and not followed (equivalent to "redirect_dir=off"
239-
if "redirect_always_follow" feature is not enabled).
235+
Redirects are not created and not followed.
236+
- "redirect_dir=off":
237+
If "redirect_always_follow" is enabled in the kernel/module config,
238+
this "off" traslates to "follow", otherwise it translates to "nofollow".
240239

241240
When the NFS export feature is enabled, every copied up directory is
242241
indexed by the file handle of the lower inode and a file handle of the
@@ -371,6 +370,41 @@ conflict with metacopy=on, and will result in an error.
371370
[*] redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
372371
given.
373372

373+
374+
Data-only lower layers
375+
----------------------
376+
377+
With "metacopy" feature enabled, an overlayfs regular file may be a composition
378+
of information from up to three different layers:
379+
380+
1) metadata from a file in the upper layer
381+
382+
2) st_ino and st_dev object identifier from a file in a lower layer
383+
384+
3) data from a file in another lower layer (further below)
385+
386+
The "lower data" file can be on any lower layer, except from the top most
387+
lower layer.
388+
389+
Below the top most lower layer, any number of lower most layers may be defined
390+
as "data-only" lower layers, using double colon ("::") separators.
391+
A normal lower layer is not allowed to be below a data-only layer, so single
392+
colon separators are not allowed to the right of double colon ("::") separators.
393+
394+
395+
For example:
396+
397+
mount -t overlay overlay -olowerdir=/l1:/l2:/l3::/do1::/do2 /merged
398+
399+
The paths of files in the "data-only" lower layers are not visible in the
400+
merged overlayfs directories and the metadata and st_ino/st_dev of files
401+
in the "data-only" lower layers are not visible in overlayfs inodes.
402+
403+
Only the data of the files in the "data-only" lower layers may be visible
404+
when a "metacopy" file in one of the lower layers above it, has a "redirect"
405+
to the absolute path of the "lower data" file in the "data-only" lower layer.
406+
407+
374408
Sharing and copying layers
375409
--------------------------
376410

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15937,6 +15937,7 @@ F: include/media/i2c/ov2659.h
1593715937

1593815938
OVERLAY FILESYSTEM
1593915939
M: Miklos Szeredi <miklos@szeredi.hu>
15940+
M: Amir Goldstein <amir73il@gmail.com>
1594015941
L: linux-unionfs@vger.kernel.org
1594115942
S: Supported
1594215943
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git

fs/overlayfs/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
obj-$(CONFIG_OVERLAY_FS) += overlay.o
77

88
overlay-objs := super.o namei.o util.o inode.o file.o dir.o readdir.o \
9-
copy_up.o export.o
9+
copy_up.o export.o params.o

fs/overlayfs/copy_up.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)
575575
/* Restore timestamps on parent (best effort) */
576576
ovl_set_timestamps(ofs, upperdir, &c->pstat);
577577
ovl_dentry_set_upper_alias(c->dentry);
578+
ovl_dentry_update_reval(c->dentry, upper);
578579
}
579580
}
580581
inode_unlock(udir);
@@ -894,6 +895,7 @@ static int ovl_do_copy_up(struct ovl_copy_up_ctx *c)
894895
inode_unlock(udir);
895896

896897
ovl_dentry_set_upper_alias(c->dentry);
898+
ovl_dentry_update_reval(c->dentry, ovl_dentry_upper(c->dentry));
897899
}
898900

899901
out:
@@ -1071,6 +1073,15 @@ static int ovl_copy_up_flags(struct dentry *dentry, int flags)
10711073
if (WARN_ON(disconnected && d_is_dir(dentry)))
10721074
return -EIO;
10731075

1076+
/*
1077+
* We may not need lowerdata if we are only doing metacopy up, but it is
1078+
* not very important to optimize this case, so do lazy lowerdata lookup
1079+
* before any copy up, so we can do it before taking ovl_inode_lock().
1080+
*/
1081+
err = ovl_maybe_lookup_lowerdata(dentry);
1082+
if (err)
1083+
return err;
1084+
10741085
old_cred = ovl_override_creds(dentry->d_sb);
10751086
while (!err) {
10761087
struct dentry *next;

fs/overlayfs/dir.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs)
8383
ofs->whiteout = whiteout;
8484
}
8585

86-
if (ofs->share_whiteout) {
86+
if (!ofs->no_shared_whiteout) {
8787
whiteout = ovl_lookup_temp(ofs, workdir);
8888
if (IS_ERR(whiteout))
8989
goto out;
@@ -95,7 +95,7 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs)
9595
if (err != -EMLINK) {
9696
pr_warn("Failed to link whiteout - disabling whiteout inode sharing(nlink=%u, err=%i)\n",
9797
ofs->whiteout->d_inode->i_nlink, err);
98-
ofs->share_whiteout = false;
98+
ofs->no_shared_whiteout = true;
9999
}
100100
dput(whiteout);
101101
}
@@ -269,8 +269,7 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
269269

270270
ovl_dir_modified(dentry->d_parent, false);
271271
ovl_dentry_set_upper_alias(dentry);
272-
ovl_dentry_update_reval(dentry, newdentry,
273-
DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
272+
ovl_dentry_init_reval(dentry, newdentry, NULL);
274273

275274
if (!hardlink) {
276275
/*
@@ -953,7 +952,7 @@ static bool ovl_type_merge_or_lower(struct dentry *dentry)
953952

954953
static bool ovl_can_move(struct dentry *dentry)
955954
{
956-
return ovl_redirect_dir(dentry->d_sb) ||
955+
return ovl_redirect_dir(OVL_FS(dentry->d_sb)) ||
957956
!d_is_dir(dentry) || !ovl_type_merge_or_lower(dentry);
958957
}
959958

fs/overlayfs/export.c

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static int ovl_connectable_layer(struct dentry *dentry)
8080

8181
/* We can get overlay root from root of any layer */
8282
if (dentry == dentry->d_sb->s_root)
83-
return oe->numlower;
83+
return ovl_numlower(oe);
8484

8585
/*
8686
* If it's an unindexed merge dir, then it's not connectable with any
@@ -91,7 +91,7 @@ static int ovl_connectable_layer(struct dentry *dentry)
9191
return 0;
9292

9393
/* We can get upper/overlay path from indexed/lower dentry */
94-
return oe->lowerstack[0].layer->idx;
94+
return ovl_lowerstack(oe)->layer->idx;
9595
}
9696

9797
/*
@@ -105,14 +105,15 @@ static int ovl_connectable_layer(struct dentry *dentry)
105105
static int ovl_connect_layer(struct dentry *dentry)
106106
{
107107
struct dentry *next, *parent = NULL;
108+
struct ovl_entry *oe = OVL_E(dentry);
108109
int origin_layer;
109110
int err = 0;
110111

111112
if (WARN_ON(dentry == dentry->d_sb->s_root) ||
112113
WARN_ON(!ovl_dentry_lower(dentry)))
113114
return -EIO;
114115

115-
origin_layer = OVL_E(dentry)->lowerstack[0].layer->idx;
116+
origin_layer = ovl_lowerstack(oe)->layer->idx;
116117
if (ovl_dentry_test_flag(OVL_E_CONNECTED, dentry))
117118
return origin_layer;
118119

@@ -285,21 +286,29 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
285286
struct dentry *lower = lowerpath ? lowerpath->dentry : NULL;
286287
struct dentry *upper = upper_alias ?: index;
287288
struct dentry *dentry;
288-
struct inode *inode;
289+
struct inode *inode = NULL;
289290
struct ovl_entry *oe;
290291
struct ovl_inode_params oip = {
291-
.lowerpath = lowerpath,
292292
.index = index,
293-
.numlower = !!lower
294293
};
295294

296295
/* We get overlay directory dentries with ovl_lookup_real() */
297296
if (d_is_dir(upper ?: lower))
298297
return ERR_PTR(-EIO);
299298

299+
oe = ovl_alloc_entry(!!lower);
300+
if (!oe)
301+
return ERR_PTR(-ENOMEM);
302+
300303
oip.upperdentry = dget(upper);
304+
if (lower) {
305+
ovl_lowerstack(oe)->dentry = dget(lower);
306+
ovl_lowerstack(oe)->layer = lowerpath->layer;
307+
}
308+
oip.oe = oe;
301309
inode = ovl_get_inode(sb, &oip);
302310
if (IS_ERR(inode)) {
311+
ovl_free_entry(oe);
303312
dput(upper);
304313
return ERR_CAST(inode);
305314
}
@@ -314,20 +323,11 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
314323
dentry = d_alloc_anon(inode->i_sb);
315324
if (unlikely(!dentry))
316325
goto nomem;
317-
oe = ovl_alloc_entry(lower ? 1 : 0);
318-
if (!oe)
319-
goto nomem;
320326

321-
if (lower) {
322-
oe->lowerstack->dentry = dget(lower);
323-
oe->lowerstack->layer = lowerpath->layer;
324-
}
325-
dentry->d_fsdata = oe;
326327
if (upper_alias)
327328
ovl_dentry_set_upper_alias(dentry);
328329

329-
ovl_dentry_update_reval(dentry, upper,
330-
DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE);
330+
ovl_dentry_init_reval(dentry, upper, OVL_I_E(inode));
331331

332332
return d_instantiate_anon(dentry, inode);
333333

@@ -342,15 +342,16 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
342342
/* Get the upper or lower dentry in stack whose on layer @idx */
343343
static struct dentry *ovl_dentry_real_at(struct dentry *dentry, int idx)
344344
{
345-
struct ovl_entry *oe = dentry->d_fsdata;
345+
struct ovl_entry *oe = OVL_E(dentry);
346+
struct ovl_path *lowerstack = ovl_lowerstack(oe);
346347
int i;
347348

348349
if (!idx)
349350
return ovl_dentry_upper(dentry);
350351

351-
for (i = 0; i < oe->numlower; i++) {
352-
if (oe->lowerstack[i].layer->idx == idx)
353-
return oe->lowerstack[i].dentry;
352+
for (i = 0; i < ovl_numlower(oe); i++) {
353+
if (lowerstack[i].layer->idx == idx)
354+
return lowerstack[i].dentry;
354355
}
355356

356357
return NULL;

fs/overlayfs/file.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,23 @@ static int ovl_real_fdget_meta(const struct file *file, struct fd *real,
107107
{
108108
struct dentry *dentry = file_dentry(file);
109109
struct path realpath;
110+
int err;
110111

111112
real->flags = 0;
112113
real->file = file->private_data;
113114

114-
if (allow_meta)
115+
if (allow_meta) {
115116
ovl_path_real(dentry, &realpath);
116-
else
117+
} else {
118+
/* lazy lookup of lowerdata */
119+
err = ovl_maybe_lookup_lowerdata(dentry);
120+
if (err)
121+
return err;
122+
117123
ovl_path_realdata(dentry, &realpath);
124+
}
125+
if (!realpath.dentry)
126+
return -EIO;
118127

119128
/* Has it been copied up since we'd opened it? */
120129
if (unlikely(file_inode(real->file) != d_inode(realpath.dentry))) {
@@ -150,6 +159,11 @@ static int ovl_open(struct inode *inode, struct file *file)
150159
struct path realpath;
151160
int err;
152161

162+
/* lazy lookup of lowerdata */
163+
err = ovl_maybe_lookup_lowerdata(dentry);
164+
if (err)
165+
return err;
166+
153167
err = ovl_maybe_copy_up(dentry, file->f_flags);
154168
if (err)
155169
return err;
@@ -158,6 +172,9 @@ static int ovl_open(struct inode *inode, struct file *file)
158172
file->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
159173

160174
ovl_path_realdata(dentry, &realpath);
175+
if (!realpath.dentry)
176+
return -EIO;
177+
161178
realfile = ovl_open_realfile(file, &realpath);
162179
if (IS_ERR(realfile))
163180
return PTR_ERR(realfile);

0 commit comments

Comments
 (0)