Pawel Jakub Dawidek wrote:
> On Tue, Aug 23, 2011 at 10:09:41AM -0400, Rick Macklem wrote:
> > Ok, I'll admit I wasn't very fond of a fixed table that would
> > inevitably
> > get out of date someday, either.
> >
> > I didn't think hashing for the cases not in the table was worth the
> > effort,
> > but doing a hash instead of a table seems reasonable.
> >
> > I see that ZFS only uses the low order 8 bits, so I'll try and come
> > up
> > with an 8bit hash solution and will post a patch for testing/review
> > soon.
> >
> > I don't think the vfs_sysctl() is that great a concern, given that
> > it
> > appears to be deprecated already anyhow. (With an 8bit hash,
> > vfs_typenum
> > won't be that sparse.) I'll also make sure that whatever hash I use
> > doesn't collide for the current list of file names (although I will
> > include
> > code that handles a collision in the patch).
> 
> Sounds great. Thanks!
> 
Here's the patch. (Hiroki could you please test this, thanks, rick.)
ps: If the white space gets trashed, the same patch is at:
   http://people.freebsd.org/~rmacklem/fsid.patch

--- kern/vfs_init.c.sav 2011-06-11 18:58:33.000000000 -0400
+++ kern/vfs_init.c     2011-08-23 15:55:30.000000000 -0400
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD: head/sys/kern/vfs_in
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/hash.h>
 #include <sys/kernel.h>
 #include <sys/linker.h>
 #include <sys/mount.h>
@@ -138,6 +139,8 @@ vfs_register(struct vfsconf *vfc)
        struct sysctl_oid *oidp;
        struct vfsops *vfsops;
        static int once;
+       struct vfsconf *tvfc;
+       uint32_t hashval;
 
        if (!once) {
                vattr_null(&va_null);
@@ -152,7 +155,27 @@ vfs_register(struct vfsconf *vfc)
        if (vfs_byname(vfc->vfc_name) != NULL)
                return EEXIST;
 
-       vfc->vfc_typenum = maxvfsconf++;
+       /*
+        * Calculate a hash on vfc_name to use for vfc_typenum. Unless
+        * a collision occurs, it is limited to 8bits since that is
+        * what ZFS uses from vfc_typenum and that also limits how sparsely
+        * distributed vfc_typenum becomes.
+        */
+       hashval = hash32_str(vfc->vfc_name, 0);
+       hashval = ((hashval & 0xff) + ((hashval >> 8) & 0xff) +
+           ((hashval >> 16) & 0xff) + (hashval >> 24)) & 0xff;
+       do {
+               /* Look for and fix any collision. */
+               TAILQ_FOREACH(tvfc, &vfsconf, vfc_list) {
+                       if (hashval == tvfc->vfc_typenum) {
+                               hashval++; /* Can exceed 8bits, if needed. */
+                               break;
+                       }
+               }
+       } while (tvfc != NULL);
+       vfc->vfc_typenum = hashval;
+       if (vfc->vfc_typenum >= maxvfsconf)
+               maxvfsconf = vfc->vfc_typenum + 1;
        TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list);
 
        /*
_______________________________________________
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscr...@freebsd.org"

Reply via email to