Skip to content

Commit

Permalink
Merge tag 'ovl-update-5.10' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/mszeredi/vfs

Pull overlayfs updates from Miklos Szeredi:

 - Improve performance for certain container setups by introducing a
   "volatile" mode

 - ioctl improvements

 - continue preparation for unprivileged overlay mounts

* tag 'ovl-update-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
  ovl: use generic vfs_ioc_setflags_prepare() helper
  ovl: support [S|G]ETFLAGS and FS[S|G]ETXATTR ioctls for directories
  ovl: rearrange ovl_can_list()
  ovl: enumerate private xattrs
  ovl: pass ovl_fs down to functions accessing private xattrs
  ovl: drop flags argument from ovl_do_setxattr()
  ovl: adhere to the vfs_ vs. ovl_do_ conventions for xattrs
  ovl: use ovl_do_getxattr() for private xattr
  ovl: fold ovl_getxattr() into ovl_get_redirect_xattr()
  ovl: clean up ovl_getxattr() in copy_up.c
  duplicate ovl_getxattr()
  ovl: provide a mount option "volatile"
  ovl: check for incompatible features in work dir
  • Loading branch information
Linus Torvalds committed Oct 16, 2020
2 parents fad7011 + be4df0c commit 071a057
Showing 12 changed files with 446 additions and 200 deletions.
19 changes: 19 additions & 0 deletions Documentation/filesystems/overlayfs.rst
Original file line number Diff line number Diff line change
@@ -564,6 +564,25 @@ Note: the mount options index=off,nfs_export=on are conflicting for a
read-write mount and will result in an error.


Volatile mount
--------------

This is enabled with the "volatile" mount option. Volatile mounts are not
guaranteed to survive a crash. It is strongly recommended that volatile
mounts are only used if data written to the overlay can be recreated
without significant effort.

The advantage of mounting with the "volatile" option is that all forms of
sync calls to the upper filesystem are omitted.

When overlay is mounted with "volatile" option, the directory
"$workdir/work/incompat/volatile" is created. During next mount, overlay
checks for this directory and refuses to mount if present. This is a strong
indicator that user should throw away upper and work directories and create
fresh one. In very limited cases where the user knows that the system has
not crashed and contents of upperdir are intact, The "volatile" directory
can be removed.

Testsuite
---------

59 changes: 44 additions & 15 deletions fs/overlayfs/copy_up.c
Original file line number Diff line number Diff line change
@@ -43,7 +43,8 @@ static bool ovl_must_copy_xattr(const char *name)
!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN);
}

int ovl_copy_xattr(struct dentry *old, struct dentry *new)
int ovl_copy_xattr(struct super_block *sb, struct dentry *old,
struct dentry *new)
{
ssize_t list_size, size, value_size = 0;
char *buf, *name, *value = NULL;
@@ -81,7 +82,7 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
}
list_size -= slen;

if (ovl_is_private_xattr(name))
if (ovl_is_private_xattr(sb, name))
continue;
retry:
size = vfs_getxattr(old, name, value, value_size);
@@ -128,7 +129,8 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new)
return error;
}

static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
static int ovl_copy_up_data(struct ovl_fs *ofs, struct path *old,
struct path *new, loff_t len)
{
struct file *old_file;
struct file *new_file;
@@ -218,7 +220,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)
len -= bytes;
}
out:
if (!error)
if (!error && ovl_should_sync(ofs))
error = vfs_fsync(new_file, 0);
fput(new_file);
out_fput:
@@ -354,7 +356,8 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
}

/* Store file handle of @upper dir in @index dir entry */
static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index)
static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
struct dentry *index)
{
const struct ovl_fh *fh;
int err;
@@ -363,7 +366,7 @@ static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index)
if (IS_ERR(fh))
return PTR_ERR(fh);

err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh->buf, fh->fb.len, 0);
err = ovl_do_setxattr(ofs, index, OVL_XATTR_UPPER, fh->buf, fh->fb.len);

kfree(fh);
return err;
@@ -408,7 +411,7 @@ static int ovl_create_index(struct dentry *dentry, struct dentry *origin,
if (IS_ERR(temp))
goto free_name;

err = ovl_set_upper_fh(upper, temp);
err = ovl_set_upper_fh(OVL_FS(dentry->d_sb), upper, temp);
if (err)
goto out;

@@ -484,6 +487,7 @@ static int ovl_link_up(struct ovl_copy_up_ctx *c)

static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
{
struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
int err;

/*
@@ -499,12 +503,13 @@ static int ovl_copy_up_inode(struct ovl_copy_up_ctx *c, struct dentry *temp)
upperpath.dentry = temp;

ovl_path_lowerdata(c->dentry, &datapath);
err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
err = ovl_copy_up_data(ofs, &datapath, &upperpath,
c->stat.size);
if (err)
return err;
}

err = ovl_copy_xattr(c->lowerpath.dentry, temp);
err = ovl_copy_xattr(c->dentry->d_sb, c->lowerpath.dentry, temp);
if (err)
return err;

@@ -781,9 +786,33 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode,
return true;
}

static ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value)
{
ssize_t res;
char *buf;

res = vfs_getxattr(dentry, name, NULL, 0);
if (res == -ENODATA || res == -EOPNOTSUPP)
res = 0;

if (res > 0) {
buf = kzalloc(res, GFP_KERNEL);
if (!buf)
return -ENOMEM;

res = vfs_getxattr(dentry, name, buf, res);
if (res < 0)
kfree(buf);
else
*value = buf;
}
return res;
}

/* Copy up data of an inode which was copied up metadata only in the past. */
static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
{
struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
struct path upperpath, datapath;
int err;
char *capability = NULL;
@@ -799,12 +828,12 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)

if (c->stat.size) {
err = cap_size = ovl_getxattr(upperpath.dentry, XATTR_NAME_CAPS,
&capability, 0);
if (err < 0 && err != -ENODATA)
&capability);
if (cap_size < 0)
goto out;
}

err = ovl_copy_up_data(&datapath, &upperpath, c->stat.size);
err = ovl_copy_up_data(ofs, &datapath, &upperpath, c->stat.size);
if (err)
goto out_free;

@@ -813,14 +842,14 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c)
* don't want that to happen for normal copy-up operation.
*/
if (capability) {
err = ovl_do_setxattr(upperpath.dentry, XATTR_NAME_CAPS,
capability, cap_size, 0);
err = vfs_setxattr(upperpath.dentry, XATTR_NAME_CAPS,
capability, cap_size, 0);
if (err)
goto out_free;
}


err = vfs_removexattr(upperpath.dentry, OVL_XATTR_METACOPY);
err = ovl_do_removexattr(ofs, upperpath.dentry, OVL_XATTR_METACOPY);
if (err)
goto out_free;

2 changes: 1 addition & 1 deletion fs/overlayfs/dir.c
Original file line number Diff line number Diff line change
@@ -394,7 +394,7 @@ static struct dentry *ovl_clear_empty(struct dentry *dentry,
if (IS_ERR(opaquedir))
goto out_unlock;

err = ovl_copy_xattr(upper, opaquedir);
err = ovl_copy_xattr(dentry->d_sb, upper, opaquedir);
if (err)
goto out_cleanup;

2 changes: 1 addition & 1 deletion fs/overlayfs/export.c
Original file line number Diff line number Diff line change
@@ -752,7 +752,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
goto out_err;
}
if (index) {
err = ovl_verify_origin(index, origin.dentry, false);
err = ovl_verify_origin(ofs, index, origin.dentry, false);
if (err)
goto out_err;
}
Loading

0 comments on commit 071a057

Please sign in to comment.