summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>1999-09-19 06:24:21 +0000
committerdillon <dillon@FreeBSD.org>1999-09-19 06:24:21 +0000
commitbeba2c930cbfe78cec732754669e47738f9929b5 (patch)
tree8f84c2568016a03436e9257970bd0d9f79c57265
parent9e003228b65115ddf59cf0d8ac934fbc2c771d09 (diff)
downloadFreeBSD-src-beba2c930cbfe78cec732754669e47738f9929b5.zip
FreeBSD-src-beba2c930cbfe78cec732754669e47738f9929b5.tar.gz
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>
-rw-r--r--sys/kern/vfs_conf.c22
-rw-r--r--sys/kern/vfs_export.c58
-rw-r--r--sys/kern/vfs_mount.c22
-rw-r--r--sys/kern/vfs_subr.c58
-rw-r--r--sys/sys/mount.h1
5 files changed, 117 insertions, 44 deletions
diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c
index 87f3e4a..7c11af7 100644
--- a/sys/kern/vfs_conf.c
+++ b/sys/kern/vfs_conf.c
@@ -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;
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 757e4aa..6737312 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -333,36 +333,55 @@ 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:
*
* 0 = seconds only; nanoseconds zeroed.
@@ -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 {
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 87f3e4a..7c11af7 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -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;
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 757e4aa..6737312 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -333,36 +333,55 @@ 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:
*
* 0 = seconds only; nanoseconds zeroed.
@@ -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 {
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index bb4b490..2da7a1e 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -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 */
OpenPOWER on IntegriCloud