summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2014-10-23 22:56:05 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2014-10-24 20:24:11 -0400
commit3d268c9b136f51385f9d041f3f2424501b257388 (patch)
treef2dcbda16c82c4215ccf104915e9541e1c785b85 /fs/overlayfs
parent1be47b387a717a1d3edf29c80b6e7f3a72ab236e (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>
Diffstat (limited to 'fs/overlayfs')
-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,
458 if (!od->is_upper && ovl_path_type(dentry) == OVL_PATH_MERGE) { 458 if (!od->is_upper && ovl_path_type(dentry) == OVL_PATH_MERGE) {
459 struct inode *inode = file_inode(file); 459 struct inode *inode = file_inode(file);
460 460
461 mutex_lock(&inode->i_mutex);
462 realfile = od->upperfile; 461 realfile = od->upperfile;
463 if (!realfile) { 462 if (!realfile) {
464 struct path upperpath; 463 struct path upperpath;
465 464
466 ovl_path_upper(dentry, &upperpath); 465 ovl_path_upper(dentry, &upperpath);
467 realfile = ovl_path_open(&upperpath, O_RDONLY); 466 realfile = ovl_path_open(&upperpath, O_RDONLY);
468 if (IS_ERR(realfile)) { 467 mutex_lock(&inode->i_mutex);
469 mutex_unlock(&inode->i_mutex); 468 if (!od->upperfile) {
470 return PTR_ERR(realfile); 469 if (IS_ERR(realfile)) {
470 mutex_unlock(&inode->i_mutex);
471 return PTR_ERR(realfile);
472 }
473 od->upperfile = realfile;
474 } else {
475 /* somebody has beaten us to it */
476 if (!IS_ERR(realfile))
477 fput(realfile);
478 realfile = od->upperfile;
471 } 479 }
472 od->upperfile = realfile; 480 mutex_unlock(&inode->i_mutex);
473 } 481 }
474 mutex_unlock(&inode->i_mutex);
475 } 482 }
476 483
477 return vfs_fsync_range(realfile, start, end, datasync); 484 return vfs_fsync_range(realfile, start, end, datasync);