aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-03-04 14:28:10 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-14 09:15:25 -0400
commit4455ca6223cc59cbc0a75f4be8bce9e84cc0d6b8 (patch)
tree5fb5966330b9dff9a364da07e85c224b89ca9dd2
parent9856fa1b281eccdc9f8d94d716e96818c675e78e (diff)
clear RCU on all failure exits from link_path_walk()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/namei.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/fs/namei.c b/fs/namei.c
index d29f91e8ff3d..f09887a45831 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1405,8 +1405,9 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1405 * parent relationships. 1405 * parent relationships.
1406 */ 1406 */
1407 if (unlikely(type != LAST_NORM)) { 1407 if (unlikely(type != LAST_NORM)) {
1408 if (handle_dots(nd, type)) 1408 err = handle_dots(nd, type);
1409 return -ECHILD; 1409 if (err)
1410 goto return_err;
1410 continue; 1411 continue;
1411 } 1412 }
1412 1413
@@ -1441,8 +1442,9 @@ last_component:
1441 if (lookup_flags & LOOKUP_PARENT) 1442 if (lookup_flags & LOOKUP_PARENT)
1442 goto lookup_parent; 1443 goto lookup_parent;
1443 if (unlikely(type != LAST_NORM)) { 1444 if (unlikely(type != LAST_NORM)) {
1444 if (handle_dots(nd, type)) 1445 err = handle_dots(nd, type);
1445 return -ECHILD; 1446 if (err)
1447 goto return_err;
1446 return 0; 1448 return 0;
1447 } 1449 }
1448 err = do_lookup(nd, &this, &next, &inode); 1450 err = do_lookup(nd, &this, &next, &inode);
@@ -1475,6 +1477,12 @@ lookup_parent:
1475 if (!(nd->flags & LOOKUP_RCU)) 1477 if (!(nd->flags & LOOKUP_RCU))
1476 path_put(&nd->path); 1478 path_put(&nd->path);
1477return_err: 1479return_err:
1480 if (nd->flags & LOOKUP_RCU) {
1481 nd->flags &= ~LOOKUP_RCU;
1482 nd->root.mnt = NULL;
1483 rcu_read_unlock();
1484 br_read_unlock(vfsmount_lock);
1485 }
1478 return err; 1486 return err;
1479} 1487}
1480 1488
@@ -1585,16 +1593,10 @@ static int path_lookupat(int dfd, const char *name,
1585 retval = link_path_walk(name, nd); 1593 retval = link_path_walk(name, nd);
1586 1594
1587 if (nd->flags & LOOKUP_RCU) { 1595 if (nd->flags & LOOKUP_RCU) {
1588 /* RCU dangling. Cancel it. */ 1596 /* went all way through without dropping RCU */
1589 if (!retval) { 1597 BUG_ON(retval);
1590 if (nameidata_drop_rcu_last(nd)) 1598 if (nameidata_drop_rcu_last(nd))
1591 retval = -ECHILD; 1599 retval = -ECHILD;
1592 } else {
1593 nd->flags &= ~LOOKUP_RCU;
1594 nd->root.mnt = NULL;
1595 rcu_read_unlock();
1596 br_read_unlock(vfsmount_lock);
1597 }
1598 } 1600 }
1599 1601
1600 if (!retval) 1602 if (!retval)