Commit 3d268c9b136f51385f9d041f3f2424501b257388
1 parent
1be47b387a
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
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>
Showing 1 changed file with 13 additions and 6 deletions Side-by-side Diff
fs/overlayfs/readdir.c
... | ... | @@ -458,20 +458,27 @@ |
458 | 458 | if (!od->is_upper && ovl_path_type(dentry) == OVL_PATH_MERGE) { |
459 | 459 | struct inode *inode = file_inode(file); |
460 | 460 | |
461 | - mutex_lock(&inode->i_mutex); | |
462 | 461 | realfile = od->upperfile; |
463 | 462 | if (!realfile) { |
464 | 463 | struct path upperpath; |
465 | 464 | |
466 | 465 | ovl_path_upper(dentry, &upperpath); |
467 | 466 | realfile = ovl_path_open(&upperpath, O_RDONLY); |
468 | - if (IS_ERR(realfile)) { | |
469 | - mutex_unlock(&inode->i_mutex); | |
470 | - return PTR_ERR(realfile); | |
467 | + mutex_lock(&inode->i_mutex); | |
468 | + if (!od->upperfile) { | |
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 | 484 | return vfs_fsync_range(realfile, start, end, datasync); |