Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Dec 2010 11:42:42 GMT
From:      Zheng Liu <lz@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 187242 for review
Message-ID:  <201012281142.oBSBggLb019110@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@187242?ac=10

Change 187242 by lz@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)) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012281142.oBSBggLb019110>