diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2014-10-23 22:56:05 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-10-24 20:24:11 -0400 |
| commit | 3d268c9b136f51385f9d041f3f2424501b257388 (patch) | |
| tree | f2dcbda16c82c4215ccf104915e9541e1c785b85 | |
| parent | 1be47b387a717a1d3edf29c80b6e7f3a72ab236e (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>
| -rw-r--r-- | fs/overlayfs/readdir.c | 19 |
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); |
