Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+34 -18
+34 -18
fs/namei.c
··· 1383 1383 } 1384 1384 1385 1385 /* 1386 + * We know there's a real path component here of at least 1387 + * one character. 1388 + */ 1389 + static 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 1405 * Name resolution. 1387 1406 * This is the basic name resolution function, turning a pathname into 1388 1407 * the final dentry. We expect 'base' to be positive and a directory. ··· 1421 1402 1422 1403 /* At this point we know we have a real path component. */ 1423 1404 for(;;) { 1424 - unsigned long hash; 1425 1405 struct qstr this; 1426 - unsigned int c; 1406 + long len; 1427 1407 int type; 1428 1408 1429 1409 err = may_lookup(nd); 1430 1410 if (err) 1431 1411 break; 1432 1412 1413 + len = hash_name(name, &this.hash); 1433 1414 this.name = name; 1434 - c = *(const unsigned char *)name; 1435 - 1436 - hash = init_name_hash(); 1437 - do { 1438 - name++; 1439 - hash = partial_name_hash(c, hash); 1440 - c = *(const unsigned char *)name; 1441 - } while (c && (c != '/')); 1442 - this.len = name - (const char *) this.name; 1443 - this.hash = end_name_hash(hash); 1415 + this.len = len; 1444 1416 1445 1417 type = LAST_NORM; 1446 - if (this.name[0] == '.') switch (this.len) { 1418 + if (name[0] == '.') switch (len) { 1447 1419 case 2: 1448 - if (this.name[1] == '.') { 1420 + if (name[1] == '.') { 1449 1421 type = LAST_DOTDOT; 1450 1422 nd->flags |= LOOKUP_JUMPED; 1451 1423 } ··· 1455 1445 } 1456 1446 } 1457 1447 1458 - /* remove trailing slashes? */ 1459 - if (!c) 1448 + if (!name[len]) 1460 1449 goto last_component; 1461 - while (*++name == '/'); 1462 - if (!*name) 1450 + /* 1451 + * If it wasn't NUL, we know it was '/'. Skip that 1452 + * slash, and continue until no more slashes. 1453 + */ 1454 + do { 1455 + len++; 1456 + } while (unlikely(name[len] == '/')); 1457 + if (!name[len]) 1463 1458 goto last_component; 1459 + name += len; 1464 1460 1465 1461 err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW); 1466 1462 if (err < 0)