diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 50dfa4826152e1ea8a7123c00380557f1d2649c5..d8f514a474ca081899e108383e3e992dde091d0c 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -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) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 7c7b946b063f91624f1a467fd099f921d3f6027b..b0d539af1fadc5a308e327fa3b805002b075e1f5 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -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) diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 2fc4c22707aad525bee7acb0d315d8ae596d2e5e..a0baaa7e224c22e1fa0c05de06085123056e0d1b 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -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)