diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/fs/namei.c b/fs/namei.c index ea14bfb04785..53bba7c1a520 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -498,8 +498,15 @@ err_root: | |||
498 | /* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ | 498 | /* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ |
499 | static inline int nameidata_dentry_drop_rcu_maybe(struct nameidata *nd, struct dentry *dentry) | 499 | static inline int nameidata_dentry_drop_rcu_maybe(struct nameidata *nd, struct dentry *dentry) |
500 | { | 500 | { |
501 | if (nd->flags & LOOKUP_RCU) | 501 | if (nd->flags & LOOKUP_RCU) { |
502 | return nameidata_dentry_drop_rcu(nd, dentry); | 502 | if (unlikely(nameidata_dentry_drop_rcu(nd, dentry))) { |
503 | nd->flags &= ~LOOKUP_RCU; | ||
504 | nd->root.mnt = NULL; | ||
505 | rcu_read_unlock(); | ||
506 | br_read_unlock(vfsmount_lock); | ||
507 | return -ECHILD; | ||
508 | } | ||
509 | } | ||
503 | return 0; | 510 | return 0; |
504 | } | 511 | } |
505 | 512 | ||
@@ -1424,7 +1431,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1424 | if (inode && inode->i_op->follow_link) { | 1431 | if (inode && inode->i_op->follow_link) { |
1425 | err = do_follow_link(inode, &next, nd); | 1432 | err = do_follow_link(inode, &next, nd); |
1426 | if (err) | 1433 | if (err) |
1427 | goto return_err; | 1434 | return err; |
1428 | nd->inode = nd->path.dentry->d_inode; | 1435 | nd->inode = nd->path.dentry->d_inode; |
1429 | } else { | 1436 | } else { |
1430 | path_to_nameidata(&next, nd); | 1437 | path_to_nameidata(&next, nd); |
@@ -1455,7 +1462,7 @@ last_component: | |||
1455 | (lookup_flags & LOOKUP_FOLLOW)) { | 1462 | (lookup_flags & LOOKUP_FOLLOW)) { |
1456 | err = do_follow_link(inode, &next, nd); | 1463 | err = do_follow_link(inode, &next, nd); |
1457 | if (err) | 1464 | if (err) |
1458 | goto return_err; | 1465 | return err; |
1459 | nd->inode = nd->path.dentry->d_inode; | 1466 | nd->inode = nd->path.dentry->d_inode; |
1460 | } else { | 1467 | } else { |
1461 | path_to_nameidata(&next, nd); | 1468 | path_to_nameidata(&next, nd); |
@@ -1477,7 +1484,6 @@ lookup_parent: | |||
1477 | } | 1484 | } |
1478 | if (!(nd->flags & LOOKUP_RCU)) | 1485 | if (!(nd->flags & LOOKUP_RCU)) |
1479 | path_put(&nd->path); | 1486 | path_put(&nd->path); |
1480 | return_err: | ||
1481 | if (nd->flags & LOOKUP_RCU) { | 1487 | if (nd->flags & LOOKUP_RCU) { |
1482 | nd->flags &= ~LOOKUP_RCU; | 1488 | nd->flags &= ~LOOKUP_RCU; |
1483 | nd->root.mnt = NULL; | 1489 | nd->root.mnt = NULL; |