aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-03-13 19:58:58 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-15 17:16:20 -0400
commitce57dfc1791221ef58b6d6b8f5437fccefc4e187 (patch)
treef4745174c126231bbd2c4a652d37f086ad035e3c /fs/namei.c
parent11a7b371b64ef39fc5fb1b6f2218eef7c4d035e3 (diff)
pull handling of one pathname component into a helper
new helper: walk_component(). Handles everything except symlinks; returns negative on error, 0 on success and 1 on symlinks we decided to follow. Drops out of RCU mode on such symlinks. link_path_walk() and do_last() switched to using that. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c123
1 files changed, 55 insertions, 68 deletions
diff --git a/fs/namei.c b/fs/namei.c
index c9b7f5b7e92a..549bbe2f25c6 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -785,16 +785,11 @@ __do_follow_link(const struct path *link, struct nameidata *nd, void **p)
785 * Without that kind of total limit, nasty chains of consecutive 785 * Without that kind of total limit, nasty chains of consecutive
786 * symlinks can cause almost arbitrarily long lookups. 786 * symlinks can cause almost arbitrarily long lookups.
787 */ 787 */
788static inline int do_follow_link(struct inode *inode, struct path *path, struct nameidata *nd) 788static inline int do_follow_link(struct path *path, struct nameidata *nd)
789{ 789{
790 void *cookie; 790 void *cookie;
791 int err = -ELOOP; 791 int err = -ELOOP;
792 792
793 /* We drop rcu-walk here */
794 if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry))
795 return -ECHILD;
796 BUG_ON(inode != path->dentry->d_inode);
797
798 if (current->link_count >= MAX_NESTED_LINKS) 793 if (current->link_count >= MAX_NESTED_LINKS)
799 goto loop; 794 goto loop;
800 if (current->total_link_count >= 40) 795 if (current->total_link_count >= 40)
@@ -1337,6 +1332,39 @@ static void terminate_walk(struct nameidata *nd)
1337 } 1332 }
1338} 1333}
1339 1334
1335static inline int walk_component(struct nameidata *nd, struct path *path,
1336 struct qstr *name, int type, int follow)
1337{
1338 struct inode *inode;
1339 int err;
1340 /*
1341 * "." and ".." are special - ".." especially so because it has
1342 * to be able to know about the current root directory and
1343 * parent relationships.
1344 */
1345 if (unlikely(type != LAST_NORM))
1346 return handle_dots(nd, type);
1347 err = do_lookup(nd, name, path, &inode);
1348 if (unlikely(err)) {
1349 terminate_walk(nd);
1350 return err;
1351 }
1352 if (!inode) {
1353 path_to_nameidata(path, nd);
1354 terminate_walk(nd);
1355 return -ENOENT;
1356 }
1357 if (unlikely(inode->i_op->follow_link) && follow) {
1358 if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry))
1359 return -ECHILD;
1360 BUG_ON(inode != path->dentry->d_inode);
1361 return 1;
1362 }
1363 path_to_nameidata(path, nd);
1364 nd->inode = inode;
1365 return 0;
1366}
1367
1340/* 1368/*
1341 * Name resolution. 1369 * Name resolution.
1342 * This is the basic name resolution function, turning a pathname into 1370 * This is the basic name resolution function, turning a pathname into
@@ -1361,7 +1389,6 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1361 1389
1362 /* At this point we know we have a real path component. */ 1390 /* At this point we know we have a real path component. */
1363 for(;;) { 1391 for(;;) {
1364 struct inode *inode;
1365 unsigned long hash; 1392 unsigned long hash;
1366 struct qstr this; 1393 struct qstr this;
1367 unsigned int c; 1394 unsigned int c;
@@ -1414,34 +1441,16 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1414 if (!*name) 1441 if (!*name)
1415 goto last_with_slashes; 1442 goto last_with_slashes;
1416 1443
1417 /* 1444 err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);
1418 * "." and ".." are special - ".." especially so because it has 1445 if (err < 0)
1419 * to be able to know about the current root directory and 1446 return err;
1420 * parent relationships.
1421 */
1422 if (unlikely(type != LAST_NORM)) {
1423 if (handle_dots(nd, type))
1424 return -ECHILD;
1425 continue;
1426 }
1427
1428 /* This does the actual lookups.. */
1429 err = do_lookup(nd, &this, &next, &inode);
1430 if (err)
1431 break;
1432 1447
1433 if (inode && inode->i_op->follow_link) { 1448 if (err) {
1434 err = do_follow_link(inode, &next, nd); 1449 err = do_follow_link(&next, nd);
1435 if (err) 1450 if (err)
1436 return err; 1451 return err;
1437 nd->inode = nd->path.dentry->d_inode; 1452 nd->inode = nd->path.dentry->d_inode;
1438 } else {
1439 path_to_nameidata(&next, nd);
1440 nd->inode = inode;
1441 } 1453 }
1442 err = -ENOENT;
1443 if (!nd->inode)
1444 break;
1445 err = -ENOTDIR; 1454 err = -ENOTDIR;
1446 if (!nd->inode->i_op->lookup) 1455 if (!nd->inode->i_op->lookup)
1447 break; 1456 break;
@@ -1453,36 +1462,27 @@ last_with_slashes:
1453last_component: 1462last_component:
1454 /* Clear LOOKUP_CONTINUE iff it was previously unset */ 1463 /* Clear LOOKUP_CONTINUE iff it was previously unset */
1455 nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; 1464 nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
1456 if (lookup_flags & LOOKUP_PARENT) 1465 if (lookup_flags & LOOKUP_PARENT) {
1457 goto lookup_parent; 1466 nd->last = this;
1458 if (unlikely(type != LAST_NORM)) 1467 nd->last_type = type;
1459 return handle_dots(nd, type); 1468 return 0;
1460 err = do_lookup(nd, &this, &next, &inode); 1469 }
1461 if (err) 1470 err = walk_component(nd, &next, &this, type,
1462 break; 1471 lookup_flags & LOOKUP_FOLLOW);
1463 if (inode && unlikely(inode->i_op->follow_link) && 1472 if (err < 0)
1464 (lookup_flags & LOOKUP_FOLLOW)) { 1473 return err;
1465 err = do_follow_link(inode, &next, nd); 1474 if (err) {
1475 err = do_follow_link(&next, nd);
1466 if (err) 1476 if (err)
1467 return err; 1477 return err;
1468 nd->inode = nd->path.dentry->d_inode; 1478 nd->inode = nd->path.dentry->d_inode;
1469 } else {
1470 path_to_nameidata(&next, nd);
1471 nd->inode = inode;
1472 } 1479 }
1473 err = -ENOENT;
1474 if (!nd->inode)
1475 break;
1476 if (lookup_flags & LOOKUP_DIRECTORY) { 1480 if (lookup_flags & LOOKUP_DIRECTORY) {
1477 err = -ENOTDIR; 1481 err = -ENOTDIR;
1478 if (!nd->inode->i_op->lookup) 1482 if (!nd->inode->i_op->lookup)
1479 break; 1483 break;
1480 } 1484 }
1481 return 0; 1485 return 0;
1482lookup_parent:
1483 nd->last = this;
1484 nd->last_type = type;
1485 return 0;
1486 } 1486 }
1487 terminate_walk(nd); 1487 terminate_walk(nd);
1488 return err; 1488 return err;
@@ -2068,7 +2068,6 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2068 int want_write = 0; 2068 int want_write = 0;
2069 int acc_mode = op->acc_mode; 2069 int acc_mode = op->acc_mode;
2070 struct file *filp; 2070 struct file *filp;
2071 struct inode *inode;
2072 int error; 2071 int error;
2073 2072
2074 nd->flags &= ~LOOKUP_PARENT; 2073 nd->flags &= ~LOOKUP_PARENT;
@@ -2111,24 +2110,12 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2111 if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW)) 2110 if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
2112 symlink_ok = 1; 2111 symlink_ok = 1;
2113 /* we _can_ be in RCU mode here */ 2112 /* we _can_ be in RCU mode here */
2114 error = do_lookup(nd, &nd->last, path, &inode); 2113 error = walk_component(nd, path, &nd->last, LAST_NORM,
2115 if (error) { 2114 !symlink_ok);
2116 terminate_walk(nd); 2115 if (error < 0)
2117 return ERR_PTR(error); 2116 return ERR_PTR(error);
2118 } 2117 if (error) /* symlink */
2119 if (!inode) {
2120 path_to_nameidata(path, nd);
2121 terminate_walk(nd);
2122 return ERR_PTR(-ENOENT);
2123 }
2124 if (unlikely(inode->i_op->follow_link && !symlink_ok)) {
2125 /* We drop rcu-walk here */
2126 if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry))
2127 return ERR_PTR(-ECHILD);
2128 return NULL; 2118 return NULL;
2129 }
2130 path_to_nameidata(path, nd);
2131 nd->inode = inode;
2132 /* sayonara */ 2119 /* sayonara */
2133 if (nd->flags & LOOKUP_RCU) { 2120 if (nd->flags & LOOKUP_RCU) {
2134 if (nameidata_drop_rcu_last(nd)) 2121 if (nameidata_drop_rcu_last(nd))
@@ -2137,7 +2124,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2137 2124
2138 error = -ENOTDIR; 2125 error = -ENOTDIR;
2139 if (nd->flags & LOOKUP_DIRECTORY) { 2126 if (nd->flags & LOOKUP_DIRECTORY) {
2140 if (!inode->i_op->lookup) 2127 if (!nd->inode->i_op->lookup)
2141 goto exit; 2128 goto exit;
2142 } 2129 }
2143 audit_inode(pathname, nd->path.dentry); 2130 audit_inode(pathname, nd->path.dentry);