diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-06 16:54:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-06 16:54:56 -0400 |
commit | f68e556e23d1a4176b563bcb25d8baf2c5313f91 (patch) | |
tree | 4c43c375dd0c608ed506953d80ebfedacca37161 /fs/namei.c | |
parent | 23f347ef63aa36b5a001b6791f657cd0e2a04de3 (diff) |
Make the "word-at-a-time" helper functions more commonly usable
I have a new optimized x86 "strncpy_from_user()" that will use these
same helper functions for all the same reasons the name lookup code uses
them. This is preparation for that.
This moves them into an architecture-specific header file. It's
architecture-specific for two reasons:
- some of the functions are likely to want architecture-specific
implementations. Even if the current code happens to be "generic" in
the sense that it should work on any little-endian machine, it's
likely that the "multiply by a big constant and shift" implementation
is less than optimal for an architecture that has a guaranteed fast
bit count instruction, for example.
- I expect that if architectures like sparc want to start playing
around with this, we'll need to abstract out a few more details (in
particular the actual unaligned accesses). So we're likely to have
more architecture-specific stuff if non-x86 architectures start using
this.
(and if it turns out that non-x86 architectures don't start using
this, then having it in an architecture-specific header is still the
right thing to do, of course)
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 35 |
1 files changed, 3 insertions, 32 deletions
diff --git a/fs/namei.c b/fs/namei.c index 1898198abc3d..0062dd17eb55 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1407,18 +1407,9 @@ static inline int can_lookup(struct inode *inode) | |||
1407 | */ | 1407 | */ |
1408 | #ifdef CONFIG_DCACHE_WORD_ACCESS | 1408 | #ifdef CONFIG_DCACHE_WORD_ACCESS |
1409 | 1409 | ||
1410 | #ifdef CONFIG_64BIT | 1410 | #include <asm/word-at-a-time.h> |
1411 | 1411 | ||
1412 | /* | 1412 | #ifdef CONFIG_64BIT |
1413 | * Jan Achrenius on G+: microoptimized version of | ||
1414 | * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56" | ||
1415 | * that works for the bytemasks without having to | ||
1416 | * mask them first. | ||
1417 | */ | ||
1418 | static inline long count_masked_bytes(unsigned long mask) | ||
1419 | { | ||
1420 | return mask*0x0001020304050608ul >> 56; | ||
1421 | } | ||
1422 | 1413 | ||
1423 | static inline unsigned int fold_hash(unsigned long hash) | 1414 | static inline unsigned int fold_hash(unsigned long hash) |
1424 | { | 1415 | { |
@@ -1428,15 +1419,6 @@ static inline unsigned int fold_hash(unsigned long hash) | |||
1428 | 1419 | ||
1429 | #else /* 32-bit case */ | 1420 | #else /* 32-bit case */ |
1430 | 1421 | ||
1431 | /* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ | ||
1432 | static inline long count_masked_bytes(long mask) | ||
1433 | { | ||
1434 | /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ | ||
1435 | long a = (0x0ff0001+mask) >> 23; | ||
1436 | /* Fix the 1 for 00 case */ | ||
1437 | return a & mask; | ||
1438 | } | ||
1439 | |||
1440 | #define fold_hash(x) (x) | 1422 | #define fold_hash(x) (x) |
1441 | 1423 | ||
1442 | #endif | 1424 | #endif |
@@ -1464,17 +1446,6 @@ done: | |||
1464 | } | 1446 | } |
1465 | EXPORT_SYMBOL(full_name_hash); | 1447 | EXPORT_SYMBOL(full_name_hash); |
1466 | 1448 | ||
1467 | #define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) | ||
1468 | #define ONEBYTES REPEAT_BYTE(0x01) | ||
1469 | #define SLASHBYTES REPEAT_BYTE('/') | ||
1470 | #define HIGHBITS REPEAT_BYTE(0x80) | ||
1471 | |||
1472 | /* Return the high bit set in the first byte that is a zero */ | ||
1473 | static inline unsigned long has_zero(unsigned long a) | ||
1474 | { | ||
1475 | return ((a - ONEBYTES) & ~a) & HIGHBITS; | ||
1476 | } | ||
1477 | |||
1478 | /* | 1449 | /* |
1479 | * Calculate the length and hash of the path component, and | 1450 | * Calculate the length and hash of the path component, and |
1480 | * return the length of the component; | 1451 | * return the length of the component; |
@@ -1490,7 +1461,7 @@ static inline unsigned long hash_name(const char *name, unsigned int *hashp) | |||
1490 | len += sizeof(unsigned long); | 1461 | len += sizeof(unsigned long); |
1491 | a = *(unsigned long *)(name+len); | 1462 | a = *(unsigned long *)(name+len); |
1492 | /* Do we have any NUL or '/' bytes in this word? */ | 1463 | /* Do we have any NUL or '/' bytes in this word? */ |
1493 | mask = has_zero(a) | has_zero(a ^ SLASHBYTES); | 1464 | mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/')); |
1494 | } while (!mask); | 1465 | } while (!mask); |
1495 | 1466 | ||
1496 | /* The mask *below* the first high bit set */ | 1467 | /* The mask *below* the first high bit set */ |