From 99f390a4e8015ddd72e91fd20840ca3847704ec6 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Tue, 13 Sep 2011 21:01:26 +0000 Subject: [PATCH] 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. Tested by: hrs Reviewed by: jhb, pjd (earlier version) Approved by: re (kib) MFC after: 1 month --- UPDATING | 12 ++++++++++++ sys/kern/vfs_init.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/UPDATING b/UPDATING index f5c6f4de7ad..dd351316650 100644 --- a/UPDATING +++ b/UPDATING @@ -22,6 +22,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW: machines to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +20110913: + This commit modifies vfs_register() so that it uses a hash + calculation to set vfc_typenum, which is enabled by default. + The first time a system is booted after this change, the + vfc_typenum values will change for all file systems. The + main effect of this is a change to the NFS server file handles + for file systems that use vfc_typenum in their fsid, such as ZFS. + It will, however, prevent vfc_typenum from changing when file + systems are loaded in a different order for subsequent reboots. + To disable this, you can set vfs.typenumhash=0 in /boot/loader.conf + until you are ready to remount all NFS clients after a reboot. + 20110828: Bump the shared library version numbers for libraries that do not use symbol versioning, have changed the ABI compared diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 4367b8c8096..0165b38c3cd 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -64,6 +65,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 = 1; +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. * @@ -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); /* -- 2.45.0