ovl: use ovl_inode mutex to synchronize concurrent copy up
authorAmir Goldstein <amir73il@gmail.com>
Wed, 21 Jun 2017 12:28:51 +0000 (15:28 +0300)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 4 Jul 2017 20:03:16 +0000 (22:03 +0200)
Use the new ovl_inode mutex to synchonize concurrent copy up
instead of the super block copy up workqueue.

Moving the synchronization object from the overlay dentry to
the overlay inode is needed for synchonizing concurrent copy up
of lower hardlinks to the same upper inode.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/overlayfs/util.c

index 50dfa4826152e1ea8a7123c00380557f1d2649c5..d8f514a474ca081899e108383e3e992dde091d0c 100644 (file)
@@ -29,7 +29,6 @@ struct ovl_fs {
        const struct cred *creator_cred;
        bool tmpfile;
        bool noxattr;
-       wait_queue_head_t copyup_wq;
        /* sb common to all layers */
        struct super_block *same_sb;
 };
@@ -41,7 +40,6 @@ struct ovl_entry {
                struct {
                        u64 version;
                        bool opaque;
-                       bool copying;
                };
                struct rcu_head rcu;
        };
@@ -57,6 +55,9 @@ struct ovl_inode {
        struct inode vfs_inode;
        struct dentry *__upperdentry;
        struct inode *lower;
+
+       /* synchronize copy up and more */
+       struct mutex lock;
 };
 
 static inline struct ovl_inode *OVL_I(struct inode *inode)
index 7c7b946b063f91624f1a467fd099f921d3f6027b..b0d539af1fadc5a308e327fa3b805002b075e1f5 100644 (file)
@@ -173,6 +173,7 @@ static struct inode *ovl_alloc_inode(struct super_block *sb)
        oi->flags = 0;
        oi->__upperdentry = NULL;
        oi->lower = NULL;
+       mutex_init(&oi->lock);
 
        return &oi->vfs_inode;
 }
@@ -190,6 +191,7 @@ static void ovl_destroy_inode(struct inode *inode)
 
        dput(oi->__upperdentry);
        kfree(oi->redirect);
+       mutex_destroy(&oi->lock);
 
        call_rcu(&inode->i_rcu, ovl_i_callback);
 }
@@ -782,7 +784,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
        if (!ufs)
                goto out;
 
-       init_waitqueue_head(&ufs->copyup_wq);
        ufs->config.redirect_dir = ovl_redirect_dir_def;
        err = ovl_parse_opt((char *) data, &ufs->config);
        if (err)
index 2fc4c22707aad525bee7acb0d315d8ae596d2e5e..a0baaa7e224c22e1fa0c05de06085123056e0d1b 100644 (file)
@@ -270,32 +270,21 @@ struct file *ovl_path_open(struct path *path, int flags)
 
 int ovl_copy_up_start(struct dentry *dentry)
 {
-       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
-       struct ovl_entry *oe = dentry->d_fsdata;
+       struct ovl_inode *oi = OVL_I(d_inode(dentry));
        int err;
 
-       spin_lock(&ofs->copyup_wq.lock);
-       err = wait_event_interruptible_locked(ofs->copyup_wq, !oe->copying);
-       if (!err) {
-               if (ovl_dentry_upper(dentry))
-                       err = 1; /* Already copied up */
-               else
-                       oe->copying = true;
+       err = mutex_lock_interruptible(&oi->lock);
+       if (!err && ovl_dentry_upper(dentry)) {
+               err = 1; /* Already copied up */
+               mutex_unlock(&oi->lock);
        }
-       spin_unlock(&ofs->copyup_wq.lock);
 
        return err;
 }
 
 void ovl_copy_up_end(struct dentry *dentry)
 {
-       struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
-       struct ovl_entry *oe = dentry->d_fsdata;
-
-       spin_lock(&ofs->copyup_wq.lock);
-       oe->copying = false;
-       wake_up_locked(&ofs->copyup_wq);
-       spin_unlock(&ofs->copyup_wq.lock);
+       mutex_unlock(&OVL_I(d_inode(dentry))->lock);
 }
 
 bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)