diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-02-22 20:56:27 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2011-03-14 09:15:24 -0400 |
commit | 086e183a641109033420e0b26ddecb6f4abb4c89 (patch) | |
tree | c8b0c197c042c51140fc9b8bb8bfcf816fe29448 /fs | |
parent | 16c2cd7179881d5dd87779512ca5a0d657c64f62 (diff) |
pull dropping RCU on success of link_path_walk() into path_lookupat()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/namei.c | 30 |
1 files changed, 12 insertions, 18 deletions
diff --git a/fs/namei.c b/fs/namei.c index 450b686e9682..8f10a9ff9f6b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -539,14 +539,6 @@ err_unlock: | |||
539 | return -ECHILD; | 539 | return -ECHILD; |
540 | } | 540 | } |
541 | 541 | ||
542 | /* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing. */ | ||
543 | static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd) | ||
544 | { | ||
545 | if (likely(nd->flags & LOOKUP_RCU)) | ||
546 | return nameidata_drop_rcu_last(nd); | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | /** | 542 | /** |
551 | * release_open_intent - free up open intent resources | 543 | * release_open_intent - free up open intent resources |
552 | * @nd: pointer to nameidata | 544 | * @nd: pointer to nameidata |
@@ -1339,7 +1331,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
1339 | while (*name=='/') | 1331 | while (*name=='/') |
1340 | name++; | 1332 | name++; |
1341 | if (!*name) | 1333 | if (!*name) |
1342 | goto return_base; | 1334 | return 0; |
1343 | 1335 | ||
1344 | if (nd->depth) | 1336 | if (nd->depth) |
1345 | lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); | 1337 | lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE); |
@@ -1448,7 +1440,7 @@ last_component: | |||
1448 | } else | 1440 | } else |
1449 | follow_dotdot(nd); | 1441 | follow_dotdot(nd); |
1450 | } | 1442 | } |
1451 | goto return_base; | 1443 | return 0; |
1452 | } | 1444 | } |
1453 | err = do_lookup(nd, &this, &next, &inode); | 1445 | err = do_lookup(nd, &this, &next, &inode); |
1454 | if (err) | 1446 | if (err) |
@@ -1471,13 +1463,10 @@ last_component: | |||
1471 | if (!nd->inode->i_op->lookup) | 1463 | if (!nd->inode->i_op->lookup) |
1472 | break; | 1464 | break; |
1473 | } | 1465 | } |
1474 | goto return_base; | 1466 | return 0; |
1475 | lookup_parent: | 1467 | lookup_parent: |
1476 | nd->last = this; | 1468 | nd->last = this; |
1477 | nd->last_type = type; | 1469 | nd->last_type = type; |
1478 | return_base: | ||
1479 | if (nameidata_drop_rcu_last_maybe(nd)) | ||
1480 | return -ECHILD; | ||
1481 | return 0; | 1470 | return 0; |
1482 | out_dput: | 1471 | out_dput: |
1483 | if (!(nd->flags & LOOKUP_RCU)) | 1472 | if (!(nd->flags & LOOKUP_RCU)) |
@@ -1598,10 +1587,15 @@ static int path_lookupat(int dfd, const char *name, | |||
1598 | 1587 | ||
1599 | if (nd->flags & LOOKUP_RCU) { | 1588 | if (nd->flags & LOOKUP_RCU) { |
1600 | /* RCU dangling. Cancel it. */ | 1589 | /* RCU dangling. Cancel it. */ |
1601 | nd->flags &= ~LOOKUP_RCU; | 1590 | if (!retval) { |
1602 | nd->root.mnt = NULL; | 1591 | if (nameidata_drop_rcu_last(nd)) |
1603 | rcu_read_unlock(); | 1592 | retval = -ECHILD; |
1604 | br_read_unlock(vfsmount_lock); | 1593 | } else { |
1594 | nd->flags &= ~LOOKUP_RCU; | ||
1595 | nd->root.mnt = NULL; | ||
1596 | rcu_read_unlock(); | ||
1597 | br_read_unlock(vfsmount_lock); | ||
1598 | } | ||
1605 | } | 1599 | } |
1606 | 1600 | ||
1607 | if (!retval) | 1601 | if (!retval) |