aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-02-22 20:56:27 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-14 09:15:24 -0400
commit086e183a641109033420e0b26ddecb6f4abb4c89 (patch)
treec8b0c197c042c51140fc9b8bb8bfcf816fe29448 /fs/namei.c
parent16c2cd7179881d5dd87779512ca5a0d657c64f62 (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/namei.c')
-rw-r--r--fs/namei.c30
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. */
543static 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;
1475lookup_parent: 1467lookup_parent:
1476 nd->last = this; 1468 nd->last = this;
1477 nd->last_type = type; 1469 nd->last_type = type;
1478return_base:
1479 if (nameidata_drop_rcu_last_maybe(nd))
1480 return -ECHILD;
1481 return 0; 1470 return 0;
1482out_dput: 1471out_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)