ia64/linux-2.6.18-xen.hg

annotate fs/ext3/hash.c @ 524:7f8b544237bf

netfront: Allow netfront in domain 0.

This is useful if your physical network device is in a utility domain.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Apr 15 15:18:58 2008 +0100 (2008-04-15)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 * linux/fs/ext3/hash.c
ian@0 3 *
ian@0 4 * Copyright (C) 2002 by Theodore Ts'o
ian@0 5 *
ian@0 6 * This file is released under the GPL v2.
ian@0 7 *
ian@0 8 * This file may be redistributed under the terms of the GNU Public
ian@0 9 * License.
ian@0 10 */
ian@0 11
ian@0 12 #include <linux/fs.h>
ian@0 13 #include <linux/jbd.h>
ian@0 14 #include <linux/sched.h>
ian@0 15 #include <linux/ext3_fs.h>
ian@0 16 #include <linux/cryptohash.h>
ian@0 17
ian@0 18 #define DELTA 0x9E3779B9
ian@0 19
ian@0 20 static void TEA_transform(__u32 buf[4], __u32 const in[])
ian@0 21 {
ian@0 22 __u32 sum = 0;
ian@0 23 __u32 b0 = buf[0], b1 = buf[1];
ian@0 24 __u32 a = in[0], b = in[1], c = in[2], d = in[3];
ian@0 25 int n = 16;
ian@0 26
ian@0 27 do {
ian@0 28 sum += DELTA;
ian@0 29 b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
ian@0 30 b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
ian@0 31 } while(--n);
ian@0 32
ian@0 33 buf[0] += b0;
ian@0 34 buf[1] += b1;
ian@0 35 }
ian@0 36
ian@0 37
ian@0 38 /* The old legacy hash */
ian@0 39 static __u32 dx_hack_hash (const char *name, int len)
ian@0 40 {
ian@0 41 __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
ian@0 42 while (len--) {
ian@0 43 __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
ian@0 44
ian@0 45 if (hash & 0x80000000) hash -= 0x7fffffff;
ian@0 46 hash1 = hash0;
ian@0 47 hash0 = hash;
ian@0 48 }
ian@0 49 return (hash0 << 1);
ian@0 50 }
ian@0 51
ian@0 52 static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
ian@0 53 {
ian@0 54 __u32 pad, val;
ian@0 55 int i;
ian@0 56
ian@0 57 pad = (__u32)len | ((__u32)len << 8);
ian@0 58 pad |= pad << 16;
ian@0 59
ian@0 60 val = pad;
ian@0 61 if (len > num*4)
ian@0 62 len = num * 4;
ian@0 63 for (i=0; i < len; i++) {
ian@0 64 if ((i % 4) == 0)
ian@0 65 val = pad;
ian@0 66 val = msg[i] + (val << 8);
ian@0 67 if ((i % 4) == 3) {
ian@0 68 *buf++ = val;
ian@0 69 val = pad;
ian@0 70 num--;
ian@0 71 }
ian@0 72 }
ian@0 73 if (--num >= 0)
ian@0 74 *buf++ = val;
ian@0 75 while (--num >= 0)
ian@0 76 *buf++ = pad;
ian@0 77 }
ian@0 78
ian@0 79 /*
ian@0 80 * Returns the hash of a filename. If len is 0 and name is NULL, then
ian@0 81 * this function can be used to test whether or not a hash version is
ian@0 82 * supported.
ian@0 83 *
ian@0 84 * The seed is an 4 longword (32 bits) "secret" which can be used to
ian@0 85 * uniquify a hash. If the seed is all zero's, then some default seed
ian@0 86 * may be used.
ian@0 87 *
ian@0 88 * A particular hash version specifies whether or not the seed is
ian@0 89 * represented, and whether or not the returned hash is 32 bits or 64
ian@0 90 * bits. 32 bit hashes will return 0 for the minor hash.
ian@0 91 */
ian@0 92 int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
ian@0 93 {
ian@0 94 __u32 hash;
ian@0 95 __u32 minor_hash = 0;
ian@0 96 const char *p;
ian@0 97 int i;
ian@0 98 __u32 in[8], buf[4];
ian@0 99
ian@0 100 /* Initialize the default seed for the hash checksum functions */
ian@0 101 buf[0] = 0x67452301;
ian@0 102 buf[1] = 0xefcdab89;
ian@0 103 buf[2] = 0x98badcfe;
ian@0 104 buf[3] = 0x10325476;
ian@0 105
ian@0 106 /* Check to see if the seed is all zero's */
ian@0 107 if (hinfo->seed) {
ian@0 108 for (i=0; i < 4; i++) {
ian@0 109 if (hinfo->seed[i])
ian@0 110 break;
ian@0 111 }
ian@0 112 if (i < 4)
ian@0 113 memcpy(buf, hinfo->seed, sizeof(buf));
ian@0 114 }
ian@0 115
ian@0 116 switch (hinfo->hash_version) {
ian@0 117 case DX_HASH_LEGACY:
ian@0 118 hash = dx_hack_hash(name, len);
ian@0 119 break;
ian@0 120 case DX_HASH_HALF_MD4:
ian@0 121 p = name;
ian@0 122 while (len > 0) {
ian@0 123 str2hashbuf(p, len, in, 8);
ian@0 124 half_md4_transform(buf, in);
ian@0 125 len -= 32;
ian@0 126 p += 32;
ian@0 127 }
ian@0 128 minor_hash = buf[2];
ian@0 129 hash = buf[1];
ian@0 130 break;
ian@0 131 case DX_HASH_TEA:
ian@0 132 p = name;
ian@0 133 while (len > 0) {
ian@0 134 str2hashbuf(p, len, in, 4);
ian@0 135 TEA_transform(buf, in);
ian@0 136 len -= 16;
ian@0 137 p += 16;
ian@0 138 }
ian@0 139 hash = buf[0];
ian@0 140 minor_hash = buf[1];
ian@0 141 break;
ian@0 142 default:
ian@0 143 hinfo->hash = 0;
ian@0 144 return -1;
ian@0 145 }
ian@0 146 hash = hash & ~1;
ian@0 147 if (hash == (EXT3_HTREE_EOF << 1))
ian@0 148 hash = (EXT3_HTREE_EOF-1) << 1;
ian@0 149 hinfo->hash = hash;
ian@0 150 hinfo->minor_hash = minor_hash;
ian@0 151 return 0;
ian@0 152 }