diff options
author | bde <bde@FreeBSD.org> | 2000-03-12 14:23:21 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 2000-03-12 14:23:21 +0000 |
commit | 2af0bce593c23afaabec3f094696e6a79dc50448 (patch) | |
tree | 11259a788c35d35d1bdf1c1f13c197771aa4e64f /sys/kern/vfs_subr.c | |
parent | faa77986fd8f89097b47ce4e976e9a5f451f045f (diff) | |
download | FreeBSD-src-2af0bce593c23afaabec3f094696e6a79dc50448.zip FreeBSD-src-2af0bce593c23afaabec3f094696e6a79dc50448.tar.gz |
Try harder to make the lower 16 bits of fsids unique. The vfs type
number was packed very wastefully, giving perfect non-uniqeness in
the lower 16 bits of fsids for filesystems with the same vfs type.
This made linux_stat() return perfectly non-unique (broken) 16-bit
st_dev's for nfs mount points, and effectively reduced mntid_base to
8 bits so that the vfs_getnewfsid() looped endlessly when there are
already 256 mounted filesystems with the required vfs type.
Approved by: jkh
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r-- | sys/kern/vfs_subr.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 9120f77..7d61a18 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -328,35 +328,45 @@ vfs_getvfs(fsid) } /* - * Get a new unique fsid + * Get a new unique fsid. Try to make its val[0] unique mod 2^16, since + * this value may be used to create fake device numbers for stat(), and + * some emulators only support 16-bit device numbers. * - * Keep in mind that several mounts may be running in parallel, - * so always increment mntid_base even if lower numbers are available. + * Keep in mind that several mounts may be running in parallel. Starting + * the search one past where the previous search terminated (mod 0x10) is + * both a micro-optimization and (incomplete) defense against returning + * the same fsid to different mounts. */ - -static u_short mntid_base; - void vfs_getnewfsid(mp) struct mount *mp; { + static u_int mntid_base; fsid_t tfsid; - int mtype; - - simple_lock(&mntid_slock); + u_int i; + int mtype, mynor; + simple_lock(&mntid_slock); mtype = mp->mnt_vfc->vfc_typenum; - for (;;) { - tfsid.val[0] = makeudev(255, mtype + (mntid_base << 16)); - tfsid.val[1] = mtype; - ++mntid_base; + tfsid.val[1] = mtype; + for (i = 0; ; i++) { + /* + * mtype needs to be uniquely encoded in the minor number + * so that uniqueness of the full fsid implies uniqueness + * of the device number. We are short of bits and only + * guarantee uniqueness of the device number mod 2^16 if + * mtype is always < 16 and there are never more than + * 16 mounts per vfs type. + */ + mynor = ((mntid_base++ & 0xFFFFF) << 4) | (mtype & 0xF); + if (i < 0x10) + mynor &= 0xFF; + tfsid.val[0] = makeudev(255, mynor); if (vfs_getvfs(&tfsid) == NULL) break; } - mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; mp->mnt_stat.f_fsid.val[1] = tfsid.val[1]; - simple_unlock(&mntid_slock); } |