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 #include #include +#include #include #include #include @@ -76,6 +77,8 @@ #include #include +#include + 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 #include #include +#include #include #include #include @@ -59,6 +60,8 @@ #include #include +#include + #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); } /*