diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-04-12 00:37:59 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-05-02 19:47:22 -0400 |
commit | 48f35b7b7367c6c2594f9c209ee2e1362519a899 (patch) | |
tree | 762d2c58ee6f2bdcb99f27fcbc91a259e79a9a9c /fs/configfs | |
parent | 779b839133d7ab23229be7e601cabab7678ceab1 (diff) |
configfs_detach_prep(): make sure that wait_mutex won't go away
grab a reference to dentry we'd got the sucker from, and return
that dentry via *wait, rather than just returning the address of
->i_mutex.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/configfs')
-rw-r--r-- | fs/configfs/dir.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index ea59c891fc53..48929c408e04 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
@@ -494,7 +494,7 @@ out: | |||
494 | * If there is an error, the caller will reset the flags via | 494 | * If there is an error, the caller will reset the flags via |
495 | * configfs_detach_rollback(). | 495 | * configfs_detach_rollback(). |
496 | */ | 496 | */ |
497 | static int configfs_detach_prep(struct dentry *dentry, struct mutex **wait_mutex) | 497 | static int configfs_detach_prep(struct dentry *dentry, struct dentry **wait) |
498 | { | 498 | { |
499 | struct configfs_dirent *parent_sd = dentry->d_fsdata; | 499 | struct configfs_dirent *parent_sd = dentry->d_fsdata; |
500 | struct configfs_dirent *sd; | 500 | struct configfs_dirent *sd; |
@@ -515,8 +515,8 @@ static int configfs_detach_prep(struct dentry *dentry, struct mutex **wait_mutex | |||
515 | if (sd->s_type & CONFIGFS_USET_DEFAULT) { | 515 | if (sd->s_type & CONFIGFS_USET_DEFAULT) { |
516 | /* Abort if racing with mkdir() */ | 516 | /* Abort if racing with mkdir() */ |
517 | if (sd->s_type & CONFIGFS_USET_IN_MKDIR) { | 517 | if (sd->s_type & CONFIGFS_USET_IN_MKDIR) { |
518 | if (wait_mutex) | 518 | if (wait) |
519 | *wait_mutex = &d_inode(sd->s_dentry)->i_mutex; | 519 | *wait= dget(sd->s_dentry); |
520 | return -EAGAIN; | 520 | return -EAGAIN; |
521 | } | 521 | } |
522 | 522 | ||
@@ -524,7 +524,7 @@ static int configfs_detach_prep(struct dentry *dentry, struct mutex **wait_mutex | |||
524 | * Yup, recursive. If there's a problem, blame | 524 | * Yup, recursive. If there's a problem, blame |
525 | * deep nesting of default_groups | 525 | * deep nesting of default_groups |
526 | */ | 526 | */ |
527 | ret = configfs_detach_prep(sd->s_dentry, wait_mutex); | 527 | ret = configfs_detach_prep(sd->s_dentry, wait); |
528 | if (!ret) | 528 | if (!ret) |
529 | continue; | 529 | continue; |
530 | } else | 530 | } else |
@@ -1458,7 +1458,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1458 | * the new link is temporarily attached | 1458 | * the new link is temporarily attached |
1459 | */ | 1459 | */ |
1460 | do { | 1460 | do { |
1461 | struct mutex *wait_mutex; | 1461 | struct dentry *wait; |
1462 | 1462 | ||
1463 | mutex_lock(&configfs_symlink_mutex); | 1463 | mutex_lock(&configfs_symlink_mutex); |
1464 | spin_lock(&configfs_dirent_lock); | 1464 | spin_lock(&configfs_dirent_lock); |
@@ -1469,7 +1469,7 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1469 | */ | 1469 | */ |
1470 | ret = sd->s_dependent_count ? -EBUSY : 0; | 1470 | ret = sd->s_dependent_count ? -EBUSY : 0; |
1471 | if (!ret) { | 1471 | if (!ret) { |
1472 | ret = configfs_detach_prep(dentry, &wait_mutex); | 1472 | ret = configfs_detach_prep(dentry, &wait); |
1473 | if (ret) | 1473 | if (ret) |
1474 | configfs_detach_rollback(dentry); | 1474 | configfs_detach_rollback(dentry); |
1475 | } | 1475 | } |
@@ -1483,8 +1483,9 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | /* Wait until the racing operation terminates */ | 1485 | /* Wait until the racing operation terminates */ |
1486 | mutex_lock(wait_mutex); | 1486 | inode_lock(d_inode(wait)); |
1487 | mutex_unlock(wait_mutex); | 1487 | inode_unlock(d_inode(wait)); |
1488 | dput(wait); | ||
1488 | } | 1489 | } |
1489 | } while (ret == -EAGAIN); | 1490 | } while (ret == -EAGAIN); |
1490 | 1491 | ||