Commit 0fed3ac8 authored by George Spelvin's avatar George Spelvin Committed by Linus Torvalds

namei: Improve hash mixing if CONFIG_DCACHE_WORD_ACCESS

The hash mixing between adding the next 64 bits of name
was just a bit weak.

Replaced with a still very fast but slightly more effective
mixing function.
Signed-off-by: default avatarGeorge Spelvin <linux@horizon.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2dcd0af5
...@@ -1794,30 +1794,49 @@ static inline unsigned int fold_hash(unsigned long hash) ...@@ -1794,30 +1794,49 @@ static inline unsigned int fold_hash(unsigned long hash)
return hash_64(hash, 32); return hash_64(hash, 32);
} }
/*
* This is George Marsaglia's XORSHIFT generator.
* It implements a maximum-period LFSR in only a few
* instructions. It also has the property (required
* by hash_name()) that mix_hash(0) = 0.
*/
static inline unsigned long mix_hash(unsigned long hash)
{
hash ^= hash << 13;
hash ^= hash >> 7;
hash ^= hash << 17;
return hash;
}
#else /* 32-bit case */ #else /* 32-bit case */
#define fold_hash(x) (x) #define fold_hash(x) (x)
static inline unsigned long mix_hash(unsigned long hash)
{
hash ^= hash << 13;
hash ^= hash >> 17;
hash ^= hash << 5;
return hash;
}
#endif #endif
unsigned int full_name_hash(const unsigned char *name, unsigned int len) unsigned int full_name_hash(const unsigned char *name, unsigned int len)
{ {
unsigned long a, mask; unsigned long a, hash = 0;
unsigned long hash = 0;
for (;;) { for (;;) {
a = load_unaligned_zeropad(name); a = load_unaligned_zeropad(name);
if (len < sizeof(unsigned long)) if (len < sizeof(unsigned long))
break; break;
hash += a; hash = mix_hash(hash + a);
hash *= 9;
name += sizeof(unsigned long); name += sizeof(unsigned long);
len -= sizeof(unsigned long); len -= sizeof(unsigned long);
if (!len) if (!len)
goto done; goto done;
} }
mask = bytemask_from_count(len); hash += a & bytemask_from_count(len);
hash += mask & a;
done: done:
return fold_hash(hash); return fold_hash(hash);
} }
...@@ -1835,7 +1854,7 @@ static inline u64 hash_name(const char *name) ...@@ -1835,7 +1854,7 @@ static inline u64 hash_name(const char *name)
hash = a = 0; hash = a = 0;
len = -sizeof(unsigned long); len = -sizeof(unsigned long);
do { do {
hash = (hash + a) * 9; hash = mix_hash(hash + a);
len += sizeof(unsigned long); len += sizeof(unsigned long);
a = load_unaligned_zeropad(name+len); a = load_unaligned_zeropad(name+len);
b = a ^ REPEAT_BYTE('/'); b = a ^ REPEAT_BYTE('/');
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment