Fix BOOTP root FS mounts. Also cleanup vfs_getnewfsid() and collapse

addaliasu() into addalias() (no operational change) and clarify comments
    relating to a trick that vclean() uses.

    The fix to BOOTP is yet another hack.  Actually, rootfsid handling
    is already a major hack.  The whole thing needs to be cleaned up.

Reviewed by:	David Greenman <dg@root.com>, Alan Cox <alc@cs.rice.edu>
This commit is contained in:
dillon 1999-09-19 06:24:21 +00:00
parent 9e003228b6
commit beba2c930c
5 changed files with 117 additions and 44 deletions

View File

@ -136,7 +136,27 @@ vfs_mountrootfs(void *unused)
mp->mnt_flag |= MNT_ROOTFS;
/*
* Attempt the mount
* If we have no idea what the device is because the VFS root mount
* initialization code couldn't figure it out, take a guess by
* assuming that vfs_getnewfsid() will be called when we try the
* mount. For the moment this is necessary for NFS-baesd BOOTP
* boots. Ultimately we would like to get rid of 'rootdev' entirely
* and go with a linked list of possible roots and device-specific
* auxillary data that we do not try to interpret ourselves.
*/
if (rootdev == NODEV && rootdevs[0] == NODEV)
rootdev = vfs_getrootfsid(mp);
/*
* Attempt the mount. This is rather messy due to many historical
* layers. Basically what it comes down to is that 'rootdev' is an
* override to the rootdevs[] array. The rootdevs[] array itself
* cannot normally be accessed directly by other modules, but FFS
* plays with it. NFS, on the otherhand, has no clue what the
* device assignment for a mount will be until it actually does it.
*
* During the loop we set rootdev to rootdevs[i]. This is used
* by FFS and a few other modules. It is ignored by NFS.
*/
err = ENXIO;
orootdev = rootdev;

View File

@ -333,35 +333,54 @@ vfs_getvfs(fsid)
/*
* Get a new unique fsid
*
* Keep in mind that several mounts may be running in parallel,
* so always increment mntid_base even if lower numbers are available.
*/
static u_short mntid_base;
void
vfs_getnewfsid(mp)
struct mount *mp;
{
static u_short xxxfs_mntid;
fsid_t tfsid;
int mtype;
simple_lock(&mntid_slock);
mtype = mp->mnt_vfc->vfc_typenum;
mp->mnt_stat.f_fsid.val[0] = makeudev(255, mtype);
mp->mnt_stat.f_fsid.val[1] = mtype;
if (xxxfs_mntid == 0)
++xxxfs_mntid;
tfsid.val[0] = makeudev(255, mtype + (xxxfs_mntid << 16));
tfsid.val[1] = mtype;
if (mountlist.cqh_first != (void *)&mountlist) {
while (vfs_getvfs(&tfsid)) {
xxxfs_mntid++;
tfsid.val[0] = makeudev(255,
mtype + (xxxfs_mntid << 16));
}
for (;;) {
tfsid.val[0] = makeudev(255, mtype + (mntid_base << 16));
tfsid.val[1] = mtype;
++mntid_base;
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);
}
/*
* Get what should become the root fsid.
*
* This is somewhat of a hack. If the rootdev is not known we
* assume that vfs_getnewfsid() will be called momentarily to
* allocate it, and we return what vfs_getnewfsid() will return.
*/
dev_t
vfs_getrootfsid(struct mount *mp)
{
int mtype;
mtype = mp->mnt_vfc->vfc_typenum;
return(makedev(255, mtype + (mntid_base << 16)));
}
/*
* Knob to control the precision of file timestamps:
*
@ -1303,11 +1322,7 @@ addaliasu(nvp, nvp_rdev)
if (nvp->v_type != VBLK && nvp->v_type != VCHR)
panic("addaliasu on non-special vnode");
nvp->v_rdev = udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0);
simple_lock(&spechash_slock);
SLIST_INSERT_HEAD(&nvp->v_rdev->si_hlist, nvp, v_specnext);
simple_unlock(&spechash_slock);
addalias(nvp, udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0));
}
void
@ -1650,8 +1665,9 @@ vclean(vp, flags, p)
if ((obj = vp->v_object) != NULL) {
if (obj->ref_count == 0) {
/*
* This is a normal way of shutting down the object/vnode
* association.
* vclean() may be called twice. The first time removes the
* primary reference to the object, the second time goes
* one further and is a special-case to terminate the object.
*/
vm_object_terminate(obj);
} else {

View File

@ -136,7 +136,27 @@ vfs_mountrootfs(void *unused)
mp->mnt_flag |= MNT_ROOTFS;
/*
* Attempt the mount
* If we have no idea what the device is because the VFS root mount
* initialization code couldn't figure it out, take a guess by
* assuming that vfs_getnewfsid() will be called when we try the
* mount. For the moment this is necessary for NFS-baesd BOOTP
* boots. Ultimately we would like to get rid of 'rootdev' entirely
* and go with a linked list of possible roots and device-specific
* auxillary data that we do not try to interpret ourselves.
*/
if (rootdev == NODEV && rootdevs[0] == NODEV)
rootdev = vfs_getrootfsid(mp);
/*
* Attempt the mount. This is rather messy due to many historical
* layers. Basically what it comes down to is that 'rootdev' is an
* override to the rootdevs[] array. The rootdevs[] array itself
* cannot normally be accessed directly by other modules, but FFS
* plays with it. NFS, on the otherhand, has no clue what the
* device assignment for a mount will be until it actually does it.
*
* During the loop we set rootdev to rootdevs[i]. This is used
* by FFS and a few other modules. It is ignored by NFS.
*/
err = ENXIO;
orootdev = rootdev;

View File

@ -333,35 +333,54 @@ vfs_getvfs(fsid)
/*
* Get a new unique fsid
*
* Keep in mind that several mounts may be running in parallel,
* so always increment mntid_base even if lower numbers are available.
*/
static u_short mntid_base;
void
vfs_getnewfsid(mp)
struct mount *mp;
{
static u_short xxxfs_mntid;
fsid_t tfsid;
int mtype;
simple_lock(&mntid_slock);
mtype = mp->mnt_vfc->vfc_typenum;
mp->mnt_stat.f_fsid.val[0] = makeudev(255, mtype);
mp->mnt_stat.f_fsid.val[1] = mtype;
if (xxxfs_mntid == 0)
++xxxfs_mntid;
tfsid.val[0] = makeudev(255, mtype + (xxxfs_mntid << 16));
tfsid.val[1] = mtype;
if (mountlist.cqh_first != (void *)&mountlist) {
while (vfs_getvfs(&tfsid)) {
xxxfs_mntid++;
tfsid.val[0] = makeudev(255,
mtype + (xxxfs_mntid << 16));
}
for (;;) {
tfsid.val[0] = makeudev(255, mtype + (mntid_base << 16));
tfsid.val[1] = mtype;
++mntid_base;
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);
}
/*
* Get what should become the root fsid.
*
* This is somewhat of a hack. If the rootdev is not known we
* assume that vfs_getnewfsid() will be called momentarily to
* allocate it, and we return what vfs_getnewfsid() will return.
*/
dev_t
vfs_getrootfsid(struct mount *mp)
{
int mtype;
mtype = mp->mnt_vfc->vfc_typenum;
return(makedev(255, mtype + (mntid_base << 16)));
}
/*
* Knob to control the precision of file timestamps:
*
@ -1303,11 +1322,7 @@ addaliasu(nvp, nvp_rdev)
if (nvp->v_type != VBLK && nvp->v_type != VCHR)
panic("addaliasu on non-special vnode");
nvp->v_rdev = udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0);
simple_lock(&spechash_slock);
SLIST_INSERT_HEAD(&nvp->v_rdev->si_hlist, nvp, v_specnext);
simple_unlock(&spechash_slock);
addalias(nvp, udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0));
}
void
@ -1650,8 +1665,9 @@ vclean(vp, flags, p)
if ((obj = vp->v_object) != NULL) {
if (obj->ref_count == 0) {
/*
* This is a normal way of shutting down the object/vnode
* association.
* vclean() may be called twice. The first time removes the
* primary reference to the object, the second time goes
* one further and is a special-case to terminate the object.
*/
vm_object_terminate(obj);
} else {

View File

@ -391,6 +391,7 @@ struct netcred *vfs_export_lookup /* lookup host in fs export list */
__P((struct mount *, struct netexport *, struct sockaddr *));
int vfs_allocate_syncvnode __P((struct mount *));
void vfs_getnewfsid __P((struct mount *));
dev_t vfs_getrootfsid __P((struct mount *));
struct mount *vfs_getvfs __P((fsid_t *)); /* return vfs given fsid */
int vfs_modevent __P((module_t, int, void *));
int vfs_mountedon __P((struct vnode *)); /* is a vfs mounted on vp */