Bug 176173 - The hash.h hash_long function, when used on a 64 bit machine, ignores many of the middle-order bits.
The hash.h hash_long function, when used on a 64 bit machine, ignores many o...
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: kernel (Show other bugs)
ia64 Linux
medium Severity medium
: ---
: ---
Assigned To: Steve Dickson
Brian Brock
Depends On:
Blocks: 181409
  Show dependency treegraph
Reported: 2005-12-19 15:12 EST by John Shakshober
Modified: 2007-11-30 17:07 EST (History)
1 user (show)

See Also:
Fixed In Version: RHSA-2006-0575
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2006-08-10 17:46:28 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description John Shakshober 2005-12-19 15:12:20 EST
Description of problem:

(Input from Partner HP - Eric Whitney (eric.whitney@hp.com)
In the svcauth code there are places that do:

       hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);

That seems reasonable, but then again...maybe not....

I believe that s_addr is an IP address in Network Neutral format (Big Endian)

When one is on a Little Endian system, the hash_long
function gets handed a Big Endian value as a long, and
later, via the magic of being a Little Endian system,
gets byte swapped.

Version-Release number of selected component (if applicable):
 RHEL4 U2 IPF 2.6.9-22.ELsmp

How reproducible:
 Every time

Steps to Reproduce:
1. becomes (byte swap)
2. The 32 bit IP address becomes a 64 bit long when
                 this code is compiled and run on an Opteron, or
                 an IA-64 system.
3. Call the hash_long() and get back a hash value
                that is IP_HASHBITS (8) in size.

Actual results:

You'll notice that the hash distribution is not nearly as
    good as one might believe.  If one would have done:

        hash_long( inet_lnaof(item->m_addr.s_addr)),IP_HASHBITS)

The hash_long function would have done a nice job.  Since
one is not converting the network neutral IP address into a
host binary format.  

Expected results:

With the patch below, we the hash can work better in either direction.
Not the only fix, just one suggestion.

Additional info: (one proposed patch is included)

Thanks to "Iozone" < capps@iozone.org> for identifying this problem.
Signed-off-by: Neil Brown < neilb@suse.de>

### Diffstat output
 ./net/sunrpc/svcauth_unix.c |   14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff ./net/sunrpc/svcauth_unix.c~current~ ./net/sunrpc/svcauth_unix.c
--- ./net/sunrpc/svcauth_unix.c~current~ 2005-12-16 15:10:12.000000000 +1100
+++ ./net/sunrpc/svcauth_unix.c 2005-12-16 15:12:00.000000000 +1100
@@ -101,10 +101,22 @@ static void ip_map_put(struct cache_head
+#if IP_HASHBITS == 8
+/* hash_long on a 64 bit machine is currently REALLY BAD for
+ * IP addresses in reverse-endian (i.e. on a little-endian machine).
+ * So use a trivial but reliable hash instead
+ */
+static inline int hash_ip(unsigned long ip)
+ int hash = ip ^ (ip>>16);
+ return (hash ^ (hash>>8)) & 0xff;
 static inline int ip_map_hash(struct ip_map *item)
  return hash_str(item->m_class, IP_HASHBITS) ^ 
- hash_long((unsigned long)item->m_addr.s_addr, IP_HASHBITS);
+ hash_ip((unsigned long)item->m_addr.s_addr);
 static inline int ip_map_match(struct ip_map *item, struct ip_map *tmp)
Comment 3 Jason Baron 2006-03-19 13:45:02 EST
committed in stream u4 build 34.5. A test kernel with this patch is available
from http://people.redhat.com/~jbaron/rhel4/
Comment 7 Red Hat Bugzilla 2006-08-10 17:46:29 EDT
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.


Note You need to log in before you can comment on or make changes to this bug.