svn commit: r226926 - stable/8/sys/kern

Rick Macklem rmacklem at FreeBSD.org
Sun Oct 30 02:36:50 UTC 2011


Author: rmacklem
Date: Sun Oct 30 02:36:49 2011
New Revision: 226926
URL: http://svn.freebsd.org/changeset/base/226926

Log:
  MFC: r225537
  Modify vfs_register() to use a hash calculation
  on vfc_name to set vfc_typenum, so that vfc_typenum doesn't
  change when file systems are loaded in different orders. This
  keeps NFS file handles from changing, for file systems that
  use vfc_typenum in their fsid. This change is controlled via
  a loader.conf variable called vfs.typenumhash, since vfc_typenum
  will change once when this is enabled. It defaults to 1 for
  9.0, but will default to 0 when MFC'd to stable/8.

Modified:
  stable/8/sys/kern/vfs_init.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/kern/vfs_init.c
==============================================================================
--- stable/8/sys/kern/vfs_init.c	Sun Oct 30 02:19:39 2011	(r226925)
+++ stable/8/sys/kern/vfs_init.c	Sun Oct 30 02:36:49 2011	(r226926)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/fnv_hash.h>
 #include <sys/kernel.h>
 #include <sys/linker.h>
 #include <sys/mount.h>
@@ -65,6 +66,18 @@ int maxvfsconf = VFS_GENERIC + 1;
 struct vfsconfhead vfsconf = TAILQ_HEAD_INITIALIZER(vfsconf);
 
 /*
+ * Loader.conf variable vfs.typenumhash enables setting vfc_typenum using a hash
+ * calculation on vfc_name, so that it doesn't change when file systems are
+ * loaded in a different order. This will avoid the NFS server file handles from
+ * changing for file systems that use vfc_typenum in their fsid.
+ */
+static int	vfs_typenumhash = 0;
+TUNABLE_INT("vfs.typenumhash", &vfs_typenumhash);
+SYSCTL_INT(_vfs, OID_AUTO, typenumhash, CTLFLAG_RDTUN, &vfs_typenumhash, 0,
+    "Set vfc_typenum using a hash calculation on vfc_name, so that it does not"
+    "change when file systems are loaded in a different order.");
+
+/*
  * A Zen vnode attribute structure.
  *
  * Initialized when the first filesystem registers by vfs_register().
@@ -138,6 +151,9 @@ vfs_register(struct vfsconf *vfc)
 	struct sysctl_oid *oidp;
 	struct vfsops *vfsops;
 	static int once;
+	struct vfsconf *tvfc;
+	uint32_t hashval;
+	int secondpass;
 
 	if (!once) {
 		vattr_null(&va_null);
@@ -152,7 +168,34 @@ vfs_register(struct vfsconf *vfc)
 	if (vfs_byname(vfc->vfc_name) != NULL)
 		return EEXIST;
 
-	vfc->vfc_typenum = maxvfsconf++;
+	if (vfs_typenumhash != 0) {
+		/*
+		 * Calculate a hash on vfc_name to use for vfc_typenum. Unless
+		 * all of 1<->255 are assigned, it is limited to 8bits since
+		 * that is what ZFS uses from vfc_typenum and is also the
+		 * preferred range for vfs_getnewfsid().
+		 */
+		hashval = fnv_32_str(vfc->vfc_name, FNV1_32_INIT);
+		hashval &= 0xff;
+		secondpass = 0;
+		do {
+			/* Look for and fix any collision. */
+			TAILQ_FOREACH(tvfc, &vfsconf, vfc_list) {
+				if (hashval == tvfc->vfc_typenum) {
+					if (hashval == 255 && secondpass == 0) {
+						hashval = 1;
+						secondpass = 1;
+					} else
+						hashval++;
+					break;
+				}
+			}
+		} while (tvfc != NULL);
+		vfc->vfc_typenum = hashval;
+		if (vfc->vfc_typenum >= maxvfsconf)
+			maxvfsconf = vfc->vfc_typenum + 1;
+	} else
+		vfc->vfc_typenum = maxvfsconf++;
 	TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list);
 
 	/*


More information about the svn-src-stable-8 mailing list