aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/word-at-a-time.h46
-rw-r--r--fs/namei.c35
2 files changed, 49 insertions, 32 deletions
diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h
new file mode 100644
index 00000000000..6fe6767b712
--- /dev/null
+++ b/arch/x86/include/asm/word-at-a-time.h
@@ -0,0 +1,46 @@
1#ifndef _ASM_WORD_AT_A_TIME_H
2#define _ASM_WORD_AT_A_TIME_H
3
4/*
5 * This is largely generic for little-endian machines, but the
6 * optimal byte mask counting is probably going to be something
7 * that is architecture-specific. If you have a reliably fast
8 * bit count instruction, that might be better than the multiply
9 * and shift, for example.
10 */
11
12#ifdef CONFIG_64BIT
13
14/*
15 * Jan Achrenius on G+: microoptimized version of
16 * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
17 * that works for the bytemasks without having to
18 * mask them first.
19 */
20static inline long count_masked_bytes(unsigned long mask)
21{
22 return mask*0x0001020304050608ul >> 56;
23}
24
25#else /* 32-bit case */
26
27/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
28static inline long count_masked_bytes(long mask)
29{
30 /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
31 long a = (0x0ff0001+mask) >> 23;
32 /* Fix the 1 for 00 case */
33 return a & mask;
34}
35
36#endif
37
38#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
39
40/* Return the high bit set in the first byte that is a zero */
41static inline unsigned long has_zero(unsigned long a)
42{
43 return ((a - REPEAT_BYTE(0x01)) & ~a) & REPEAT_BYTE(0x80);
44}
45
46#endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/fs/namei.c b/fs/namei.c
index 1898198abc3..0062dd17eb5 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 */
1418static inline long count_masked_bytes(unsigned long mask)
1419{
1420 return mask*0x0001020304050608ul >> 56;
1421}
1422 1413
1423static inline unsigned int fold_hash(unsigned long hash) 1414static 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 */
1432static 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}
1465EXPORT_SYMBOL(full_name_hash); 1447EXPORT_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 */
1473static 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 */