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
This commit is contained in:
parent
43fb93b0da
commit
4d30adc494
12
UPDATING
12
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
|
||||
|
@ -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>
|
||||
@ -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);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user