aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c48
1 files changed, 22 insertions, 26 deletions
diff --git a/fs/namei.c b/fs/namei.c
index b9e537980ef5..4521b5ff7c93 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1362,6 +1362,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1362 unsigned long hash; 1362 unsigned long hash;
1363 struct qstr this; 1363 struct qstr this;
1364 unsigned int c; 1364 unsigned int c;
1365 int type;
1365 1366
1366 nd->flags |= LOOKUP_CONTINUE; 1367 nd->flags |= LOOKUP_CONTINUE;
1367 1368
@@ -1381,6 +1382,16 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1381 this.len = name - (const char *) this.name; 1382 this.len = name - (const char *) this.name;
1382 this.hash = end_name_hash(hash); 1383 this.hash = end_name_hash(hash);
1383 1384
1385 type = LAST_NORM;
1386 if (this.name[0] == '.') switch (this.len) {
1387 case 2:
1388 if (this.name[1] == '.')
1389 type = LAST_DOTDOT;
1390 break;
1391 case 1:
1392 type = LAST_DOT;
1393 }
1394
1384 /* remove trailing slashes? */ 1395 /* remove trailing slashes? */
1385 if (!c) 1396 if (!c)
1386 goto last_component; 1397 goto last_component;
@@ -1393,21 +1404,17 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1393 * to be able to know about the current root directory and 1404 * to be able to know about the current root directory and
1394 * parent relationships. 1405 * parent relationships.
1395 */ 1406 */
1396 if (this.name[0] == '.') switch (this.len) { 1407 if (unlikely(type != LAST_NORM)) {
1397 default: 1408 if (type == LAST_DOTDOT) {
1398 break;
1399 case 2:
1400 if (this.name[1] != '.')
1401 break;
1402 if (nd->flags & LOOKUP_RCU) { 1409 if (nd->flags & LOOKUP_RCU) {
1403 if (follow_dotdot_rcu(nd)) 1410 if (follow_dotdot_rcu(nd))
1404 return -ECHILD; 1411 return -ECHILD;
1405 } else 1412 } else
1406 follow_dotdot(nd); 1413 follow_dotdot(nd);
1407 /* fallthrough */ 1414 }
1408 case 1: 1415 continue;
1409 continue;
1410 } 1416 }
1417
1411 /* This does the actual lookups.. */ 1418 /* This does the actual lookups.. */
1412 err = do_lookup(nd, &this, &next, &inode); 1419 err = do_lookup(nd, &this, &next, &inode);
1413 if (err) 1420 if (err)
@@ -1441,20 +1448,15 @@ last_component:
1441 nd->flags &= lookup_flags | ~LOOKUP_CONTINUE; 1448 nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
1442 if (lookup_flags & LOOKUP_PARENT) 1449 if (lookup_flags & LOOKUP_PARENT)
1443 goto lookup_parent; 1450 goto lookup_parent;
1444 if (this.name[0] == '.') switch (this.len) { 1451 if (unlikely(type != LAST_NORM)) {
1445 default: 1452 if (type == LAST_DOTDOT) {
1446 break;
1447 case 2:
1448 if (this.name[1] != '.')
1449 break;
1450 if (nd->flags & LOOKUP_RCU) { 1453 if (nd->flags & LOOKUP_RCU) {
1451 if (follow_dotdot_rcu(nd)) 1454 if (follow_dotdot_rcu(nd))
1452 return -ECHILD; 1455 return -ECHILD;
1453 } else 1456 } else
1454 follow_dotdot(nd); 1457 follow_dotdot(nd);
1455 /* fallthrough */ 1458 }
1456 case 1: 1459 goto return_reval;
1457 goto return_reval;
1458 } 1460 }
1459 err = do_lookup(nd, &this, &next, &inode); 1461 err = do_lookup(nd, &this, &next, &inode);
1460 if (err) 1462 if (err)
@@ -1480,14 +1482,8 @@ last_component:
1480 goto return_base; 1482 goto return_base;
1481lookup_parent: 1483lookup_parent:
1482 nd->last = this; 1484 nd->last = this;
1483 nd->last_type = LAST_NORM; 1485 nd->last_type = type;
1484 if (this.name[0] != '.') 1486 if (type == LAST_NORM)
1485 goto return_base;
1486 if (this.len == 1)
1487 nd->last_type = LAST_DOT;
1488 else if (this.len == 2 && this.name[1] == '.')
1489 nd->last_type = LAST_DOTDOT;
1490 else
1491 goto return_base; 1487 goto return_base;
1492return_reval: 1488return_reval:
1493 /* 1489 /*