Commit 3d268c9b136f51385f9d041f3f2424501b257388

Authored by Al Viro
1 parent 1be47b387a

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);