All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 2/2] overlay: add no wait share flock for lowers/upper/work dirs to help check mount
@ 2018-03-29  9:08 yangerkun
  2018-03-29 11:39 ` Amir Goldstein
  0 siblings, 1 reply; 2+ messages in thread
From: yangerkun @ 2018-03-29  9:08 UTC (permalink / raw)
  To: jlayton, miklos, amir73il; +Cc: linux-unionfs, yi.zhang, miaoxie, yangerkun

In order to help check any dirs has been used in overlay, add share
flock to lowerdirs/upperdir/workdir, so user space can use flock -x to
help check mount.

Signed-off-by: yangerkun <yangerkun@huawei.com>
---
 fs/overlayfs/ovl_entry.h |  3 ++
 fs/overlayfs/super.c     | 87 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 90 insertions(+)

diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index bfef6ed..69dd89c 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -35,10 +35,13 @@ struct ovl_path {
 /* private information held for overlayfs's superblock */
 struct ovl_fs {
 	struct vfsmount *upper_mnt;
+	struct file *upperfile;
 	unsigned numlower;
 	struct ovl_layer *lower_layers;
+	struct file **lowerfiles;
 	/* workbasedir is the path at workdir= mount option */
 	struct dentry *workbasedir;
+	struct file *workbasefile;
 	/* workdir is the 'work' directory under workbasedir */
 	struct dentry *workdir;
 	/* index directory listing overlay inodes by origin file handle */
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 9ee37c7..e311c66 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/statfs.h>
 #include <linux/seq_file.h>
+#include <linux/file.h>
 #include <linux/posix_acl_xattr.h>
 #include "overlayfs.h"
 
@@ -233,15 +234,31 @@ static void ovl_free_fs(struct ovl_fs *ofs)
 	if (ofs->workdir_locked)
 		ovl_inuse_unlock(ofs->workbasedir);
 	dput(ofs->workbasedir);
+
+	if (ofs->workbasefile)
+		fput(ofs->workbasefile);
+
 	if (ofs->upperdir_locked)
 		ovl_inuse_unlock(ofs->upper_mnt->mnt_root);
 	mntput(ofs->upper_mnt);
+
+	if (ofs->upperfile)
+		fput(ofs->upperfile);
+
 	for (i = 0; i < ofs->numlower; i++) {
 		mntput(ofs->lower_layers[i].mnt);
 		free_anon_bdev(ofs->lower_layers[i].pseudo_dev);
 	}
 	kfree(ofs->lower_layers);
 
+	if (ofs->lowerfiles) {
+		for (i = 0; i < ofs->numlower; i++) {
+			if (ofs->lowerfiles[i])
+				fput(ofs->lowerfiles[i]);
+		}
+		kfree(ofs->lowerfiles);
+	}
+
 	kfree(ofs->config.lowerdir);
 	kfree(ofs->config.upperdir);
 	kfree(ofs->config.workdir);
@@ -902,15 +919,49 @@ static int ovl_other_xattr_set(const struct xattr_handler *handler,
 	NULL
 };
 
+static int ovl_add_share_flock(struct file *filp)
+{
+	int err;
+	struct file_lock *fl = locks_alloc_lock();
+
+	if (!fl)
+		return -ENOMEM;
+	fl->fl_file = filp;
+	fl->fl_owner = filp;
+	fl->fl_pid = current->tgid;
+	fl->fl_flags = FL_FLOCK;
+	fl->fl_type = F_RDLCK;
+	fl->fl_end = OFFSET_MAX;
+
+	err = flock_setlk(filp, fl);
+	locks_free_lock(fl);
+	return err;
+}
+
 static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
 {
 	struct vfsmount *upper_mnt;
+	struct file *upperfile;
 	int err;
 
 	err = ovl_mount_dir(ofs->config.upperdir, upperpath);
 	if (err)
 		goto out;
 
+	upperfile = ovl_path_open(upperpath, O_DIRECTORY);
+	if (IS_ERR(upperfile)) {
+		pr_err("overlayfs: unable to open upperdir.\n");
+		err = PTR_ERR(upperfile);
+		goto out;
+	}
+
+	ofs->upperfile = upperfile;
+	err = ovl_add_share_flock(upperfile);
+	if (err) {
+		pr_err("overlayfs: unable to add share flock for upperdir.\n");
+		goto out;
+	}
+
 	/* Upper fs should not be r/o */
 	if (sb_rdonly(upperpath->mnt->mnt_sb)) {
 		pr_err("overlayfs: upper fs is r/o, try multi-lower layers mount\n");
@@ -1021,11 +1072,26 @@ static int ovl_get_workdir(struct ovl_fs *ofs, struct path *upperpath)
 {
 	int err;
 	struct path workpath = { };
+	struct file *workfile;
 
 	err = ovl_mount_dir(ofs->config.workdir, &workpath);
 	if (err)
 		goto out;
 
+	workfile = ovl_path_open(&workpath, O_DIRECTORY);
+	if (IS_ERR(workfile)) {
+		pr_err("overlayfs: unable to open workdir.\n");
+		err = PTR_ERR(workfile);
+		goto out;
+	}
+
+	ofs->workbasefile = workfile;
+	err = ovl_add_share_flock(workfile);
+	if (err) {
+		pr_err("overlayfs: unable to add share flock for workdir.\n");
+		goto out;
+	}
+
 	err = -EINVAL;
 	if (upperpath->mnt != workpath.mnt) {
 		pr_err("overlayfs: workdir and upperdir must reside under the same mount\n");
@@ -1167,6 +1233,7 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 	unsigned int stacklen, numlower = 0, i;
 	bool remote = false;
 	struct ovl_entry *oe;
+	struct file *lowerfile, **files = NULL;
 
 	err = -ENOMEM;
 	lowertmp = kstrdup(ofs->config.lowerdir, GFP_KERNEL);
@@ -1193,6 +1260,10 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 	if (!stack)
 		goto out_err;
 
+	files = kcalloc(stacklen, sizeof(struct file *), GFP_KERNEL);
+	if (!files)
+		goto out_err;
+
 	err = -EINVAL;
 	lower = lowertmp;
 	for (numlower = 0; numlower < stacklen; numlower++) {
@@ -1201,9 +1272,24 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 		if (err)
 			goto out_err;
 
+		lowerfile = ovl_path_open(&stack[numlower], O_DIRECTORY);
+		if (IS_ERR(lowerfile)) {
+			pr_err("overlayfs: unable to open lowerdir:%s.\n", lower);
+			goto out_err;
+		}
+
+		files[numlower] = lowerfile;
+		err = ovl_add_share_flock(lowerfile);
+		if (err) {
+			pr_err("overlayfs: unable to add share flock for lowerdir:%s.\n", lower);
+			goto out_err;
+		}
+
 		lower = strchr(lower, '\0') + 1;
 	}
 
+	ofs->lowerfiles = files;
+
 	err = -EINVAL;
 	sb->s_stack_depth++;
 	if (sb->s_stack_depth > FILESYSTEM_MAX_STACK_DEPTH) {
@@ -1239,6 +1325,7 @@ static struct ovl_entry *ovl_get_lowerstack(struct super_block *sb,
 	return oe;
 
 out_err:
+	kfree(files);
 	oe = ERR_PTR(err);
 	goto out;
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [RFC PATCH 2/2] overlay: add no wait share flock for lowers/upper/work dirs to help check mount
  2018-03-29  9:08 [RFC PATCH 2/2] overlay: add no wait share flock for lowers/upper/work dirs to help check mount yangerkun
@ 2018-03-29 11:39 ` Amir Goldstein
  0 siblings, 0 replies; 2+ messages in thread
From: Amir Goldstein @ 2018-03-29 11:39 UTC (permalink / raw)
  To: yangerkun; +Cc: Jeff Layton, Miklos Szeredi, overlayfs, zhangyi (F), Miao Xie

On Thu, Mar 29, 2018 at 12:08 PM, yangerkun <yangerkun@huawei.com> wrote:
> In order to help check any dirs has been used in overlay, add share
> flock to lowerdirs/upperdir/workdir, so user space can use flock -x to
> help check mount.

Rephrase: so fsck.overlay can use flock -x to get an exclusive access
to fix overlay layers.

Yangerkun,

Besides addressing fsck.overlay exclusive access requirement, this work
should also make ovl_inuse_lock() obsolete. It should be replaced by an
exclusive flock on upperdir/workdir.

Please write a new xfstest (you can clone overlay/036) that tests
the interaction of overlayfs mount with flock -x and flock -s from usersapce.

Thanks for working on this.
See more comments below.

>
> Signed-off-by: yangerkun <yangerkun@huawei.com>
> ---
>  fs/overlayfs/ovl_entry.h |  3 ++
>  fs/overlayfs/super.c     | 87 ++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 90 insertions(+)
>
> diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
> index bfef6ed..69dd89c 100644
> --- a/fs/overlayfs/ovl_entry.h
> +++ b/fs/overlayfs/ovl_entry.h
> @@ -35,10 +35,13 @@ struct ovl_path {
>  /* private information held for overlayfs's superblock */
>  struct ovl_fs {
>         struct vfsmount *upper_mnt;
> +       struct file *upperfile;
>         unsigned numlower;
>         struct ovl_layer *lower_layers;
> +       struct file **lowerfiles;

Instead of lowerfiles array add file to struct ovl_layer.

>         /* workbasedir is the path at workdir= mount option */
>         struct dentry *workbasedir;
> +       struct file *workbasefile;

workbasedir it almost only used for the old ovl_inuse_lock() and you can
get it from workbasefile. No reason to keep both around.

>         /* workdir is the 'work' directory under workbasedir */
>         struct dentry *workdir;
>         /* index directory listing overlay inodes by origin file handle */
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index 9ee37c7..e311c66 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -16,6 +16,7 @@
>  #include <linux/module.h>
>  #include <linux/statfs.h>
>  #include <linux/seq_file.h>
> +#include <linux/file.h>
>  #include <linux/posix_acl_xattr.h>
>  #include "overlayfs.h"
>
> @@ -233,15 +234,31 @@ static void ovl_free_fs(struct ovl_fs *ofs)
>         if (ofs->workdir_locked)
>                 ovl_inuse_unlock(ofs->workbasedir);
>         dput(ofs->workbasedir);
> +
> +       if (ofs->workbasefile)
> +               fput(ofs->workbasefile);
> +
>         if (ofs->upperdir_locked)
>                 ovl_inuse_unlock(ofs->upper_mnt->mnt_root);
>         mntput(ofs->upper_mnt);
> +
> +       if (ofs->upperfile)
> +               fput(ofs->upperfile);
> +
>         for (i = 0; i < ofs->numlower; i++) {
>                 mntput(ofs->lower_layers[i].mnt);
>                 free_anon_bdev(ofs->lower_layers[i].pseudo_dev);
>         }
>         kfree(ofs->lower_layers);
>
> +       if (ofs->lowerfiles) {
> +               for (i = 0; i < ofs->numlower; i++) {
> +                       if (ofs->lowerfiles[i])
> +                               fput(ofs->lowerfiles[i]);
> +               }
> +               kfree(ofs->lowerfiles);
> +       }
> +
>         kfree(ofs->config.lowerdir);
>         kfree(ofs->config.upperdir);
>         kfree(ofs->config.workdir);
> @@ -902,15 +919,49 @@ static int ovl_other_xattr_set(const struct xattr_handler *handler,
>         NULL
>  };
>
> +static int ovl_add_share_flock(struct file *filp)

This name is strange. ovl_flock() seems descriptive enough
and it should take a 'cmd' argument, so you can use it also for
exclusive flock.

> +{
> +       int err;
> +       struct file_lock *fl = locks_alloc_lock();
> +
> +       if (!fl)
> +               return -ENOMEM;
> +       fl->fl_file = filp;
> +       fl->fl_owner = filp;
> +       fl->fl_pid = current->tgid;
> +       fl->fl_flags = FL_FLOCK;
> +       fl->fl_type = F_RDLCK;
> +       fl->fl_end = OFFSET_MAX;

I would consider making non static and exporting flock_make_lock()

> +
> +       err = flock_setlk(filp, fl);
> +       locks_free_lock(fl);
> +       return err;
> +}
> +
>  static int ovl_get_upper(struct ovl_fs *ofs, struct path *upperpath)
>  {
>         struct vfsmount *upper_mnt;
> +       struct file *upperfile;
>         int err;
>
>         err = ovl_mount_dir(ofs->config.upperdir, upperpath);
>         if (err)
>                 goto out;
>
> +       upperfile = ovl_path_open(upperpath, O_DIRECTORY);
> +       if (IS_ERR(upperfile)) {
> +               pr_err("overlayfs: unable to open upperdir.\n");
> +               err = PTR_ERR(upperfile);
> +               goto out;
> +       }
> +
> +       ofs->upperfile = upperfile;
> +       err = ovl_add_share_flock(upperfile);

It should be an exclusive lock if index feature is enabled,
instead of ovll_inuse_lock().

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-03-29 11:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-29  9:08 [RFC PATCH 2/2] overlay: add no wait share flock for lowers/upper/work dirs to help check mount yangerkun
2018-03-29 11:39 ` Amir Goldstein

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.