aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-02 17:49:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-02 17:49:24 -0500
commit200e9ef7ab51f3dce4f35f90ea458cf43ea83bb8 (patch)
tree0fb908e21482546aef9c9fff5580ca79fec1cd56
parent5707c87f20bca9e76969bb4096149de6ef74cbb9 (diff)
vfs: split up name hashing in link_path_walk() into helper function
The code in link_path_walk() that finds out the length and the hash of the next path component is some of the hottest code in the kernel. And I have a version of it that does things at the full width of the CPU wordsize at a time, but that means that we *really* want to split it up into a separate helper function. So this re-organizes the code a bit and splits the hashing part into a helper function called "hash_name()". It returns the length of the pathname component, while at the same time computing and writing the hash to the appropriate location. The code generation is slightly changed by this patch, but generally for the better - and the added abstraction actually makes the code easier to read too. And the new interface is well suited for replacing just the "hash_name()" function with alternative implementations. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/namei.c52
1 files changed, 34 insertions, 18 deletions
diff --git a/fs/namei.c b/fs/namei.c
index ec72fa1acb14..71807dc7e402 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1383,6 +1383,25 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
1383} 1383}
1384 1384
1385/* 1385/*
1386 * We know there's a real path component here of at least
1387 * one character.
1388 */
1389static inline unsigned long hash_name(const char *name, unsigned int *hashp)
1390{
1391 unsigned long hash = init_name_hash();
1392 unsigned long len = 0, c;
1393
1394 c = (unsigned char)*name;
1395 do {
1396 len++;
1397 hash = partial_name_hash(c, hash);
1398 c = (unsigned char)name[len];
1399 } while (c && c != '/');
1400 *hashp = end_name_hash(hash);
1401 return len;
1402}
1403
1404/*
1386 * Name resolution. 1405 * Name resolution.
1387 * This is the basic name resolution function, turning a pathname into 1406 * This is the basic name resolution function, turning a pathname into
1388 * the final dentry. We expect 'base' to be positive and a directory. 1407 * the final dentry. We expect 'base' to be positive and a directory.
@@ -1402,31 +1421,22 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1402 1421
1403 /* At this point we know we have a real path component. */ 1422 /* At this point we know we have a real path component. */
1404 for(;;) { 1423 for(;;) {
1405 unsigned long hash;
1406 struct qstr this; 1424 struct qstr this;
1407 unsigned int c; 1425 long len;
1408 int type; 1426 int type;
1409 1427
1410 err = may_lookup(nd); 1428 err = may_lookup(nd);
1411 if (err) 1429 if (err)
1412 break; 1430 break;
1413 1431
1432 len = hash_name(name, &this.hash);
1414 this.name = name; 1433 this.name = name;
1415 c = *(const unsigned char *)name; 1434 this.len = len;
1416
1417 hash = init_name_hash();
1418 do {
1419 name++;
1420 hash = partial_name_hash(c, hash);
1421 c = *(const unsigned char *)name;
1422 } while (c && (c != '/'));
1423 this.len = name - (const char *) this.name;
1424 this.hash = end_name_hash(hash);
1425 1435
1426 type = LAST_NORM; 1436 type = LAST_NORM;
1427 if (this.name[0] == '.') switch (this.len) { 1437 if (name[0] == '.') switch (len) {
1428 case 2: 1438 case 2:
1429 if (this.name[1] == '.') { 1439 if (name[1] == '.') {
1430 type = LAST_DOTDOT; 1440 type = LAST_DOTDOT;
1431 nd->flags |= LOOKUP_JUMPED; 1441 nd->flags |= LOOKUP_JUMPED;
1432 } 1442 }
@@ -1445,12 +1455,18 @@ static int link_path_walk(const char *name, struct nameidata *nd)
1445 } 1455 }
1446 } 1456 }
1447 1457
1448 /* remove trailing slashes? */ 1458 if (!name[len])
1449 if (!c)
1450 goto last_component; 1459 goto last_component;
1451 while (*++name == '/'); 1460 /*
1452 if (!*name) 1461 * If it wasn't NUL, we know it was '/'. Skip that
1462 * slash, and continue until no more slashes.
1463 */
1464 do {
1465 len++;
1466 } while (unlikely(name[len] == '/'));
1467 if (!name[len])
1453 goto last_component; 1468 goto last_component;
1469 name += len;
1454 1470
1455 err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); 1471 err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);
1456 if (err < 0) 1472 if (err < 0)