Re: fsid change of ZFS?

From: Rick Macklem <rmacklem_at_uoguelph.ca>
Date: Tue, 23 Aug 2011 16:11:20 -0400 (EDT)
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
_at__at_ -39,6 +39,7 _at__at_ __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>
_at__at_ -138,6 +139,8 _at__at_ 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);
_at__at_ -152,7 +155,27 _at__at_ 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);
 
 	/*
Received on Tue Aug 23 2011 - 18:11:28 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:17 UTC