summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_subr.c
diff options
context:
space:
mode:
authorBruce Evans <bde@FreeBSD.org>2000-03-12 14:23:21 +0000
committerBruce Evans <bde@FreeBSD.org>2000-03-12 14:23:21 +0000
commit61214975daeca6b801d3406854b50ffb97530004 (patch)
tree50a5aa3d99834eda76b1cde80f7b5bed7429a891 /sys/kern/vfs_subr.c
parent4c435787ab9535ef122967ee5aa92a0562289faf (diff)
Notes
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r--sys/kern/vfs_subr.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 9120f7710c1d..7d61a1864a23 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);
}