Skip to content

Commit

Permalink
ovl: use ovl_inode mutex to synchronize concurrent copy up
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Amir Goldstein authored and Miklos Szeredi committed Jul 4, 2017
1 parent 13c7207 commit a015daf
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 20 deletions.
5 changes: 3 additions & 2 deletions fs/overlayfs/ovl_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand All @@ -41,7 +40,6 @@ struct ovl_entry {
struct {
u64 version;
bool opaque;
bool copying;
};
struct rcu_head rcu;
};
Expand All @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion fs/overlayfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
Expand Down
23 changes: 6 additions & 17 deletions fs/overlayfs/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit a015daf

Please sign in to comment.