Index: init_main.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/init_main.c,v
retrieving revision 1.195
diff -u -p -r1.195 init_main.c
--- init_main.c	16 May 2002 21:28:11 -0000	1.195
+++ init_main.c	5 Jun 2002 16:36:46 -0000
@@ -52,6 +52,7 @@
 #include <sys/lock.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
+#include <sys/namei.h>
 #include <sys/sysctl.h>
 #include <sys/proc.h>
 #include <sys/resourcevar.h>
@@ -76,6 +77,8 @@
 #include <sys/user.h>
 #include <sys/copyright.h>
 
+#include <fs/rootfs/rootfs.h>
+
 void mi_startup(void);				/* Should be elsewhere */
 
 /* Components of the first process -- never freed. */
@@ -487,34 +490,20 @@ start_init(void *dummy)
 	td = curthread;
 	p = td->td_proc;
 
-	vfs_mountroot(NULL);
-
-	/* Get the vnode for '/'.  Set p->p_fd->fd_cdir to reference it. */
-	if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode))
-		panic("cannot find root vnode");
-	FILEDESC_LOCK(p->p_fd);
-	p->p_fd->fd_cdir = rootvnode;
-	VREF(p->p_fd->fd_cdir);
-	p->p_fd->fd_rdir = rootvnode;
-	VREF(p->p_fd->fd_rdir);
-	FILEDESC_UNLOCK(p->p_fd);
-	VOP_UNLOCK(rootvnode, 0, td);
-
-	if (devfs_present) {
-		/*
-		 * For disk based systems, we probably cannot do this yet
-		 * since the fs will be read-only.  But a NFS root
-		 * might be ok.  It is worth a shot.
-		 */
-		error = vn_mkdir("/dev", 0700, UIO_SYSSPACE, td);
-		if (error == EEXIST)
-			error = 0;
-		if (error == 0)
-			error = kernel_vmount(0, "fstype", "devfs",
-			    "fspath", "/dev", NULL);
-		if (error != 0)
-			init_does_devfs = 1;
-	}
+	vfs_mountroot();
+	/*
+	 * For disk based systems, we probably cannot do this yet
+	 * since the fs will be read-only.  But a NFS root
+	 * might be ok.  It is worth a shot.
+	 */
+	error = vn_mkdir("/dev", 0700, UIO_SYSSPACE, td);
+	if (error == EEXIST)
+		error = 0;
+	if (error == 0)
+		error = kernel_vmount(0, "fstype", "devfs",
+		    "fspath", "/dev", NULL);
+	if (error)
+		init_does_devfs = 1;
 
 	/*
 	 * Need just enough stack to hold the faked-up "execve()" arguments.
Index: vfs_conf.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_conf.c,v
retrieving revision 1.68
diff -u -p -r1.68 vfs_conf.c
--- vfs_conf.c	17 Apr 2002 13:06:36 -0000	1.68
+++ vfs_conf.c	5 Jun 2002 16:36:46 -0000
@@ -52,6 +52,7 @@
 #include <sys/vnode.h>
 #include <sys/mount.h>
 #include <sys/malloc.h>
+#include <sys/namei.h>
 #include <sys/reboot.h>
 #include <sys/diskslice.h>
 #include <sys/disklabel.h>
@@ -59,6 +60,8 @@
 #include <sys/cons.h>
 #include <sys/proc.h>
 
+#include <fs/rootfs/rootfs.h>
+
 #include "opt_ddb.h"
 
 #ifdef DDB
@@ -100,7 +103,7 @@ dev_t		rootdev = NODEV;
  * Find and mount the root filesystem
  */
 void
-vfs_mountroot(void *foo __unused)
+vfs_mountroot(void)
 {
 	char		*cp;
 	int		i, error;
@@ -181,20 +184,20 @@ vfs_mountroot(void *foo __unused)
 static int
 vfs_mountroot_try(char *mountfrom)
 {
-        struct mount	*mp;
-	char		*vfsname, *path;
-	int		error;
-	char		patt[32];
-	int		s;
-
-	vfsname = NULL;
-	path    = NULL;
-	mp      = NULL;
-	error   = EINVAL;
+	struct thread *td;
+	struct mount *mp;
+	struct nameidata nd;
+	struct proc *p;
+	struct vnode *vp;
+	char *vfsname, *path;
+	char patt[32];
+	int error, mntflags, s;
 
 	if (mountfrom == NULL)
-		return(error);		/* don't complain */
+		return (EINVAL);	/* don't complain */
 
+	td = curthread;
+	p = td->td_proc;
 	s = splcam();			/* Overkill, but annoying without it */
 	printf("Mounting root from %s\n", mountfrom);
 	splx(s);
@@ -202,63 +205,92 @@ vfs_mountroot_try(char *mountfrom)
 	/* parse vfs name and path */
 	vfsname = malloc(MFSNAMELEN, M_MOUNT, M_WAITOK);
 	path = malloc(MNAMELEN, M_MOUNT, M_WAITOK);
-	vfsname[0] = path[0] = 0;
+	vfsname[0] = path[0] = '\0';
 	sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN);
-	if (sscanf(mountfrom, patt, vfsname, path) < 1)
-		goto done;
-
-	/* allocate a root mount */
-	error = vfs_rootmountalloc(vfsname, path[0] != 0 ? path : ROOTNAME,
-				   &mp);
-	if (error != 0) {
-		printf("Can't allocate root mount for filesystem '%s': %d\n",
-		       vfsname, error);
+	if (sscanf(mountfrom, patt, vfsname, path) < 1) {
+		error = EINVAL;
 		goto done;
 	}
-	mp->mnt_flag |= MNT_ROOTFS;
 
 	/* do our best to set rootdev */
 	if ((path[0] != 0) && setrootbyname(path))
 		printf("setrootbyname failed\n");
 
+	rootfs_init();
+
+	/*
+	 * Set cdir and rdir to make namei() work.
+	 */
+	FILEDESC_LOCK(p->p_fd);
+	p->p_fd->fd_cdir = rootvnode;
+	VREF(p->p_fd->fd_cdir);
+	p->p_fd->fd_rdir = rootvnode;
+	VREF(p->p_fd->fd_rdir);
+	FILEDESC_UNLOCK(p->p_fd);
+	VOP_UNLOCK(rootvnode, 0, td);
+
+	error = kernel_vmount(0, "fstype", "devfs", "fspath", "/dev", NULL);
+	if (error)
+		panic("%s: unable to mount devfs on rootfs, error = %d",
+		    __func__, error);
+
 	/* If the root device is a type "memory disk", mount RW */
 	if (rootdev != NODEV && devsw(rootdev) &&
 	    (devsw(rootdev)->d_flags & D_MEMDISK))
-		mp->mnt_flag &= ~MNT_RDONLY;
+		mntflags = 0;
+	else
+		mntflags = MNT_RDONLY;
+
+	error = kernel_vmount(mntflags, "fstype", vfsname, "fspath", "/root",
+	    "from", path, NULL);
+	if (error)
+		panic("%s: unable to mount root filesystem, error = %d",
+		    __func__, error);
+	/* Unmount devfs. */
+	error = kernel_umount("/dev", MNT_FORCE, td);
+	if (error)
+		panic("%s: unable to unmount devfs, error = %d\n",
+		    __func__, error);
 
+	/*
+	 * Do the vnode translation trick.
+	 * Here we assume that rootfs mounted the real
+	 * fs in /root.
+	 */
+	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/root", td);
+	if ((error = namei(&nd)) != 0)
+		panic("%s: can't find /root vnode, error = %d",
+		    __func__, error);
+	vp = nd.ni_vp;
+	NDFREE(&nd, NDF_ONLY_PNBUF);
+	rootvnode = vp;
+	mp = vp->v_mount;
+	mp->mnt_vnodecovered = NULLVP;
 	/* 
-	 * Set the mount path to be something useful, because the
-	 * filesystem code isn't responsible now for initialising
-	 * f_mntonname unless they want to override the default
-	 * (which is `path'.)
+	 * f_mntonname now contains "/root", change it to "/".
 	 */
 	strncpy(mp->mnt_stat.f_mntonname, "/", MNAMELEN);
+	rootfs_fini();
 
-	error = VFS_MOUNT(mp, NULL, NULL, NULL, curthread);
+	/*
+	 * Properly reset the filedesc structure with the new rootvnode.
+	 */
+	FILEDESC_LOCK(p->p_fd);
+	vrele(p->p_fd->fd_cdir);
+	p->p_fd->fd_cdir = rootvnode;
+	VREF(p->p_fd->fd_cdir);
+	vrele(p->p_fd->fd_rdir);
+	p->p_fd->fd_rdir = rootvnode;
+	VREF(p->p_fd->fd_rdir);
+	FILEDESC_UNLOCK(p->p_fd);
+	VOP_UNLOCK(rootvnode, 0, td);
 
 done:
-	if (vfsname != NULL)
-		free(vfsname, M_MOUNT);
-	if (path != NULL)
-		free(path, M_MOUNT);
-	if (error != 0) {
-		if (mp != NULL) {
-			vfs_unbusy(mp, curthread);
-			free(mp, M_MOUNT);
-		}
+	if (error)
 		printf("Root mount failed: %d\n", error);
-	} else {
-
-		/* register with list of mounted filesystems */
-		mtx_lock(&mountlist_mtx);
-		TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
-		mtx_unlock(&mountlist_mtx);
-
-		/* sanity check system clock against root filesystem timestamp */
+	else	/* initialize the time of day register */
 		inittodr(mp->mnt_time);
-		vfs_unbusy(mp, curthread);
-	}
-	return(error);
+	return (error);
 }
 
 /*
Index: vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.362
diff -u -p -r1.362 vfs_subr.c
--- vfs_subr.c	20 Jun 2002 20:03:41 -0000	1.362
+++ vfs_subr.c	26 Jun 2002 23:12:55 -0000
@@ -319,50 +319,6 @@ vfs_unbusy(mp, td)
 }
 
 /*
- * Lookup a filesystem type, and if found allocate and initialize
- * a mount structure for it.
- *
- * Devname is usually updated by mount(8) after booting.
- */
-int
-vfs_rootmountalloc(fstypename, devname, mpp)
-	char *fstypename;
-	char *devname;
-	struct mount **mpp;
-{
-	struct thread *td = curthread;	/* XXX */
-	struct vfsconf *vfsp;
-	struct mount *mp;
-
-	if (fstypename == NULL)
-		return (ENODEV);
-	for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next)
-		if (!strcmp(vfsp->vfc_name, fstypename))
-			break;
-	if (vfsp == NULL)
-		return (ENODEV);
-	mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO);
-	lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE);
-	(void)vfs_busy(mp, LK_NOWAIT, 0, td);
-	TAILQ_INIT(&mp->mnt_nvnodelist);
-	TAILQ_INIT(&mp->mnt_reservedvnlist);
-	mp->mnt_vfc = vfsp;
-	mp->mnt_op = vfsp->vfc_vfsops;
-	mp->mnt_flag = MNT_RDONLY;
-	mp->mnt_vnodecovered = NULLVP;
-	vfsp->vfc_refcount++;
-	mp->mnt_iosize_max = DFLTPHYS;
-	mp->mnt_stat.f_type = vfsp->vfc_typenum;
-	mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK;
-	strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN);
-	mp->mnt_stat.f_mntonname[0] = '/';
-	mp->mnt_stat.f_mntonname[1] = 0;
-	(void) copystr(devname, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0);
-	*mpp = mp;
-	return (0);
-}
-
-/*
  * Find an appropriate filesystem to use for the root. If a filesystem
  * has not been preselected, walk through the list of known filesystems
  * trying those that have mountroot routines, and try them until one
Index: vfs_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.263
diff -u -p -r1.263 vfs_syscalls.c
--- vfs_syscalls.c	24 Jun 2002 07:14:44 -0000	1.263
+++ vfs_syscalls.c	26 Jun 2002 23:13:34 -0000
@@ -563,10 +563,8 @@ update:
 		if ((mp->mnt_flag & MNT_RDONLY) == 0)
 			error = vfs_allocate_syncvnode(mp);
 		vfs_unbusy(mp, td);
-		if ((error = VFS_START(mp, 0, td)) != 0) {
+		if ((error = VFS_START(mp, 0, td)) != 0)
 			vrele(vp);
-			goto bad;
-		}
 	} else {
 		mtx_lock(&vp->v_interlock);
 		vp->v_flag &= ~VMOUNT;
@@ -575,9 +573,8 @@ update:
 		vfs_unbusy(mp, td);
 		free((caddr_t)mp, M_MOUNT);
 		vput(vp);
-		goto bad;
 	}
-	return (0);
+	return (error);
 bad:
 	vfs_freeopts(optlist);
 	return (error);
@@ -1129,6 +1126,30 @@ dounmount(mp, flags, td)
 		vfs_freeopts(mp->mnt_opt);
 	free((caddr_t)mp, M_MOUNT);
 	return (0);
+}
+
+int
+kernel_umount(path, flags, td)
+	const char *path;
+	int flags;
+	struct thread *td;
+{
+	struct mount *mp;
+	struct nameidata nd;
+	struct vnode *vp;
+	int error;
+
+	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, path, td);
+	if ((error = namei(&nd)) != 0)
+		return (error);
+	vp = nd.ni_vp;
+	NDFREE(&nd, NDF_ONLY_PNBUF);
+	mp = vp->v_mount;
+	KASSERT(vp->v_flag & VROOT, ("%s(%s): vnode is not VROOT",
+	    __func__, path));
+	vput(vp);
+	error = dounmount(mp, flags, td);
+	return (error);
 }
 
 /*
