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
This commit is contained in:
Bruce Evans 2000-03-12 14:23:21 +00:00
parent 4c435787ab
commit 61214975da
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=57931
2 changed files with 50 additions and 30 deletions

View file

@ -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);
}

View file

@ -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);
}