summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/ovl_entry.h5
-rw-r--r--fs/overlayfs/super.c3
-rw-r--r--fs/overlayfs/util.c23
3 files changed, 11 insertions, 20 deletions
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index 50dfa4826152..d8f514a474ca 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 7c7b946b063f..b0d539af1fad 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 2fc4c22707aa..a0baaa7e224c 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)