PERFORCE change 187242 for review
Zheng Liu
lz at FreeBSD.org
Tue Dec 28 11:42:43 UTC 2010
http://p4web.freebsd.org/@@187242?ac=10
Change 187242 by lz at gnehzuil-freebsd on 2010/12/28 11:41:50
Replace two functions.
* Replace str2hashbuf_unsigned and str2hashbuf_signed functions becuase of
license. Now I re-implement them according to Haiku's implemention. Haiku's
implementation is MIT license.
Affected files ...
.. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_htree.c#3 edit
.. //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_lookup.c#4 edit
Differences ...
==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_htree.c#3 (text+ko) ====
@@ -148,77 +148,88 @@
}
/*
- * XXX: maybe this function need to be re-implemented because it is very
- * similar to str2hashbuf_signed() function in Linux. However, I don't
- * have a good implementation.
+ * It does not implement signed version of str2hashbuf function in Haiku.
+ * But in Linux, the difference between signed's and unsigned's just
+ * is variable type.
*/
static void
str2hashbuf_signed(const char *msg, int len, u_int32_t *buf, int num)
{
- u_int32_t pad, val;
- int cnt = 0;
- int max_len = num << 2;
- const signed char *p = (const signed char *) msg;
+ u_int32_t pad, val;
+ int i, cnt, max_len, remain;
+ const signed char *scp = (const signed char *)msg;
+
+ pad = (u_int32_t)len;
+ pad = (pad << 8) | pad;
+ pad = (pad << 16) | pad;
+
+ max_len = num * 4;
+ if (len > max_len)
+ len = max_len;
+
+ cnt = len / 4;
+
+ for (i = 0; i < cnt; i++) {
+ val = (pad << 8) | *(scp++);
+ val = (val << 8) | *(scp++);
+ val = (val << 8) | *(scp++);
+ val = (val << 8) | *(scp++);
+ buf[i] = val;
+ }
+
+ if (cnt < num) {
+ remain = len % 4;
+ val = pad;
+ for (i = 0; i < remain; i++)
+ val = (val << 8) + *(scp++);
- pad = (u_int32_t)len | ((u_int32_t)len << 8);
- pad |= pad << 16;
+ buf[cnt] = val;
- val = pad;
- if (len > max_len)
- len = max_len;
- while (len > 0) {
- if ((cnt % 4) == 0)
- val = pad;
- val = ((int)(*p++)) + (val << 8);
- if ((cnt % 4) == 3) {
- *buf++ = val;
- val = pad;
- num--;
- }
- cnt++;
- len--;
+ for (i = cnt + 1; i < num; i++)
+ buf[i] = pad;
}
- if (--num >= 0)
- *buf++ = val;
- while (--num >= 0)
- *buf++ = pad;
}
/*
- * XXX: maybe this function need to be re-implemented because it is very
- * similar to str2hashbuf_unsigned() function in Linux. However, I don't
- * have a good implementation.
+ * Refer Haiku's implementation. This implemention is MIT license.
+ * So the kernel can not be contaminated.
*/
static void
str2hashbuf_unsigned(const char *msg, int len, u_int32_t *buf, int num)
{
- u_int32_t pad, val;
- int cnt = 0;
- int max_len = num << 2;
- const unsigned char *p = (const signed char *) msg;
+ u_int32_t pad, val;
+ int i, cnt, max_len, remain;
+ const unsigned char *ucp = (const unsigned char *)msg;
+
+ pad = (u_int32_t)len;
+ pad = (pad << 8) | pad;
+ pad = (pad << 16) | pad;
+
+ max_len = num * 4;
+ if (len > max_len)
+ len = max_len;
+
+ cnt = len / 4;
+
+ for (i = 0; i < cnt; i++) {
+ val = (pad << 8) | *(ucp++);
+ val = (val << 8) | *(ucp++);
+ val = (val << 8) | *(ucp++);
+ val = (val << 8) | *(ucp++);
+ buf[i] = val;
+ }
+
+ if (cnt < num) {
+ remain = len % 4;
+ val = pad;
+ for (i = 0; i < remain; i++)
+ val = (val << 8) + *(ucp++);
- pad = (u_int32_t)len | ((u_int32_t)len << 8);
- pad |= pad << 16;
+ buf[cnt] = val;
- val = pad;
- if (len > max_len)
- len = max_len;
- while (len > 0) {
- if ((cnt % 4) == 0)
- val = pad;
- val = ((int)(*p++)) + (val << 8);
- if ((cnt % 4) == 3) {
- *buf++ = val;
- val = pad;
- num--;
- }
- cnt++;
- len--;
+ for (i = cnt + 1; i < num; i++)
+ buf[i] = pad;
}
- if (--num >= 0)
- *buf++ = val;
- while (--num >= 0)
- *buf++ = pad;
}
int
@@ -269,7 +280,7 @@
char *p;
int i;
u_int32_t in[8], buf[4];
- u_int32_t hash, minhash = 0;
+ u_int32_t hash = 0, minhash = 0;
/* initialize default hash value */
buf[0] = 0x67452301;
@@ -285,18 +296,42 @@
memcpy(buf, hp->di_seed, sizeof(buf));
}
- p = name;
- while (namelen > 0) {
- if (hp->di_hashversion == DIRINDEX_HASH_HALF_MD4)
+ switch (hp->di_hashversion) {
+ case DIRINDEX_HASH_HALF_MD4:
+ p = name;
+ while (namelen > 0) {
str2hashbuf_signed(p, namelen, in, 8);
- else
+ half_md4_transform(buf, in);
+ namelen -= 32;
+ p += 32;
+ }
+ minhash = buf[2];
+ hash = buf[1];
+ break;
+ case DIRINDEX_HASH_HALF_MD4_UNSIGNED:
+ p = name;
+ while (namelen > 0) {
str2hashbuf_unsigned(p, namelen, in, 8);
- half_md4_transform(buf, in);
- namelen -= 32;
- p += 32;
+ half_md4_transform(buf, in);
+ namelen -= 32;
+ p += 32;
+ }
+ minhash = buf[2];
+ hash = buf[1];
+ break;
+ case DIRINDEX_HASH_LEGACY:
+ break;
+ case DIRINDEX_HASH_LEGACY_UNSIGNED:
+ break;
+ case DIRINDEX_HASH_TEA:
+ break;
+ case DIRINDEX_HASH_TEA_UNSIGNED:
+ break;
+ default:
+ hp->di_hash = 0;
+ return (-1);
}
- minhash = buf[2];
- hash = buf[1];
+
hash = hash & ~1;
if (hash == (0x7fffffff << 1))
hash = (0x7fffffff - 1) << 1;
==== //depot/projects/soc2010/ext4fs/src/sys/fs/ext4fs/ext4_lookup.c#4 (text+ko) ====
@@ -351,7 +351,7 @@
bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1;
- /* Use hash directory index to search a large direcotries. */
+ /* Use hash directory index to search a large directories. */
numdirpasses = 2;
prevoff = 0;
if (ext4_is_dirindex(dp)) {
More information about the p4-projects
mailing list