aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-10-23 22:56:05 -0400
committerAlex Shi <alex.shi@linaro.org>2015-04-17 15:51:03 +0800
commita5613f10c5230eb50a863caf596774c50ec8f3e9 (patch)
tree8f2278551db0c95ef9c998a535a03412beb6911e /fs
parent8f963c31b87794a5c16a6ea155f8001cdd1d93c7 (diff)
overlayfs: don't hold ->i_mutex over opening the real directory
just use it to serialize the assignment Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> (cherry picked from commit 3d268c9b136f51385f9d041f3f2424501b257388) Signed-off-by: Alex Shi <alex.shi@linaro.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/readdir.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index c6787f84ece9..b7d9fb098840 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -458,20 +458,27 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
if (!od->is_upper && ovl_path_type(dentry) == OVL_PATH_MERGE) {
struct inode *inode = file_inode(file);
- mutex_lock(&inode->i_mutex);
realfile = od->upperfile;
if (!realfile) {
struct path upperpath;
ovl_path_upper(dentry, &upperpath);
realfile = ovl_path_open(&upperpath, O_RDONLY);
- if (IS_ERR(realfile)) {
- mutex_unlock(&inode->i_mutex);
- return PTR_ERR(realfile);
+ mutex_lock(&inode->i_mutex);
+ if (!od->upperfile) {
+ if (IS_ERR(realfile)) {
+ mutex_unlock(&inode->i_mutex);
+ return PTR_ERR(realfile);
+ }
+ od->upperfile = realfile;
+ } else {
+ /* somebody has beaten us to it */
+ if (!IS_ERR(realfile))
+ fput(realfile);
+ realfile = od->upperfile;
}
- od->upperfile = realfile;
+ mutex_unlock(&inode->i_mutex);
}
- mutex_unlock(&inode->i_mutex);
}
return vfs_fsync_range(realfile, start, end, datasync);