From owner-freebsd-arch Mon May 20 14:28:38 2002 Delivered-To: freebsd-arch@freebsd.org Received: from elvis.mu.org (elvis.mu.org [192.203.228.196]) by hub.freebsd.org (Postfix) with ESMTP id 1EFB737B406 for ; Mon, 20 May 2002 14:28:01 -0700 (PDT) Received: by elvis.mu.org (Postfix, from userid 1920) id CFCDFAE147; Mon, 20 May 2002 14:28:00 -0700 (PDT) Date: Mon, 20 May 2002 14:28:00 -0700 From: Maxime Henrion To: arch@FreeBSD.org Subject: Re: a virtual fs to allow root mounting of any fs without special code Message-ID: <20020520212800.GI496@elvis.mu.org> References: <20020520212459.GH496@elvis.mu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="JwB53PgKC5A7+0Ej" Content-Disposition: inline In-Reply-To: <20020520212459.GH496@elvis.mu.org> User-Agent: Mutt/1.3.27i Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --JwB53PgKC5A7+0Ej Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Maxime Henrion wrote: > The attached patch implements the above idea with several restrictions. Oops! This was an old patch, please consider this one instead. Sorry, Maxime --JwB53PgKC5A7+0Ej Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="rootfs.diff" Index: fs/rootfs/rootfs.h =================================================================== RCS file: fs/rootfs/rootfs.h diff -N fs/rootfs/rootfs.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ fs/rootfs/rootfs.h 19 May 2002 22:57:17 -0000 @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2002 Maxime Henrion + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _FS_ROOTFS_ROOTFS_H_ +#define _FS_ROOTFS_ROOTFS_H_ + +#define ROOTFS_NONE 0 +#define ROOTFS_ROOT 1 +#define ROOTFS_DIR 2 + +struct rootfs_node { + int de_type; + const char *de_name; + int de_namelen; + struct vnode *de_vnode; +}; + +void rootfs_init(void); +void rootfs_fini(void); + +#endif /* _FS_ROOTFS_ROOTFS_H_ */ Index: fs/rootfs/rootfs_vnops.c =================================================================== RCS file: fs/rootfs/rootfs_vnops.c diff -N fs/rootfs/rootfs_vnops.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ fs/rootfs/rootfs_vnops.c 19 May 2002 23:04:14 -0000 @@ -0,0 +1,272 @@ +/*- + * Copyright (c) 2002 Maxime Henrion + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +static int rootfs_access(struct vop_access_args *); +static int rootfs_getattr(struct vop_getattr_args *); +static int rootfs_inactive(struct vop_inactive_args *); +static int rootfs_lookup(struct vop_lookup_args *); +static int rootfs_reclaim(struct vop_reclaim_args *); +static int rootfs_allocv(struct rootfs_node *, struct vnode **, + struct thread *); + +static struct rootfs_node rootfs_nodes[] = { + { ROOTFS_ROOT, NULL, 0, NULL }, + { ROOTFS_DIR, "dev", 3, NULL }, + { ROOTFS_DIR, "root", 4, NULL }, + { ROOTFS_NONE, NULL, 0, NULL } +}; + +/* + * Rootfs is used internally in the kernel when + * doing root mounting only. We don't need + * to do real access control at this time. + */ +static int +rootfs_access(struct vop_access_args *ap) +{ + int error; + + error = suser(ap->a_td); + KASSERT(error == 0, ("%s: uid is not root", __func__)); + return (error); +} + +/* + * Translation of a component pathname. + */ +static int +rootfs_lookup(struct vop_lookup_args *ap) +{ + struct vnode *dvp, **vpp; + struct componentname *cnp; + struct rootfs_node *de; + struct thread *td; + char *pname; + int error, flags, nameiop, namelen; + + dvp = ap->a_dvp; + vpp = ap->a_vpp; + cnp = ap->a_cnp; + pname = cnp->cn_nameptr; + namelen = cnp->cn_namelen; + nameiop = cnp->cn_nameiop; + td = cnp->cn_thread; + flags = cnp->cn_flags; + + if ((flags & ISLASTCN) && (nameiop != LOOKUP)) + panic("nameiop != LOOKUP in rootfs"); + + /* self */ + if (namelen == 1 && *pname == '.') { + *vpp = dvp; + VREF(dvp); + return (0); + } + + /* parent */ + if (flags & ISDOTDOT) { + de = (struct rootfs_node *)dvp->v_data; + if (de->de_type != ROOTFS_DIR) + goto notfound; + VOP_UNLOCK(dvp, 0, td); + /* + * Since we support only one level of directories, + * we always return the vnode for /. + */ + de = rootfs_nodes; + error = rootfs_allocv(de, vpp, td); + if (error) { + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); + return (error); + } + if ((flags & LOCKPARENT) && (flags & ISLASTCN)) + error = vn_lock(dvp, LK_EXCLUSIVE, td); + if (error) + vput(*vpp); + return (error); + } + + /* directory entry */ + de = (struct rootfs_node *)dvp->v_data; + if (de->de_type != ROOTFS_ROOT) + goto notfound; + de = rootfs_nodes + 1; /* First dir is at offset 1 */ + while (de->de_type != ROOTFS_NONE) { + if (de->de_namelen == namelen && + (bcmp(de->de_name, pname, namelen) == 0)) { + error = rootfs_allocv(de, vpp, td); + if (error) + return (error); + if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) + VOP_UNLOCK(dvp, 0, td); + return (0); + } + de++; + } + +notfound: + return (ENOENT); +} + +/* + * This is for the VOP_GETATTR() call in vfs_nmount(). + */ +static int +rootfs_getattr(struct vop_getattr_args *ap) +{ + struct vattr *vap; + + vap = ap->a_vap; + vattr_null(vap); + vap->va_uid = 0; + return (0); +} + +static int +rootfs_reclaim(struct vop_reclaim_args *ap) +{ + struct rootfs_node *de; + struct vnode *vp; + + vp = ap->a_vp; + de = (struct rootfs_node *)vp->v_data; + if (de != NULL) { + de->de_vnode = NULL; + vp->v_data = NULL; + } + return (0); +} + +static int +rootfs_inactive(struct vop_inactive_args *ap) +{ + struct thread *td; + struct vnode *vp; + + vp = ap->a_vp; + td = ap->a_td; + VOP_UNLOCK(vp, 0, td); + vrecycle(vp, NULL, td); + return (0); +} + +static vop_t **rootfs_vnodeop_p; +static struct vnodeopv_entry_desc rootfs_vnodeop_entries[] = { + { &vop_default_desc, (vop_t *) vop_defaultop }, + { &vop_access_desc, (vop_t *) rootfs_access }, + { &vop_getattr_desc, (vop_t *) rootfs_getattr }, + { &vop_inactive_desc, (vop_t *) rootfs_inactive }, + { &vop_islocked_desc, (vop_t *) vop_stdislocked }, + { &vop_lock_desc, (vop_t *) vop_stdlock }, + { &vop_lookup_desc, (vop_t *) rootfs_lookup }, + { &vop_reclaim_desc, (vop_t *) rootfs_reclaim }, + { &vop_unlock_desc, (vop_t *) vop_stdunlock }, + { NULL, NULL } +}; +static struct vnodeopv_desc rootfs_vnodeop_opv_desc = + { &rootfs_vnodeop_p, rootfs_vnodeop_entries }; + +VNODEOP_SET(rootfs_vnodeop_opv_desc); + +/* + * Returns with the root vnode locked. + */ +void +rootfs_init() +{ + struct thread *td; + struct vnode *vp; + int error; + + td = curthread; + error = rootfs_allocv(rootfs_nodes, &vp, td); + vp->v_type = VDIR; + vp->v_flag |= VROOT; + rootvnode = vp; +} + +/* + * Release our vnodes. + */ +void +rootfs_fini() +{ + struct rootfs_node *de; + struct vnode *vp; + + de = rootfs_nodes; + while (de->de_type != ROOTFS_NONE) { + if (de->de_vnode != NULL) { + vp = de->de_vnode; + vrele(vp); + } + de++; + } +} + +static int +rootfs_allocv(de, vpp, td) + struct rootfs_node *de; + struct vnode **vpp; + struct thread *td; +{ + struct vnode *vp; + int i; + + i = 0; + +loop: + vp = de->de_vnode; + if (vp != NULL) { + if (vget(vp, LK_EXCLUSIVE, td)) + goto loop; + *vpp = vp; + return (0); + } + + getnewvnode(VT_NON, NULL, rootfs_vnodeop_p, &vp); + vp->v_type = VDIR; + vp->v_data = (void *)de; + de->de_vnode = vp; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + *vpp = vp; + return (0); +} Index: kern/init_main.c =================================================================== RCS file: /home/ncvs/src/sys/kern/init_main.c,v retrieving revision 1.194 diff -u -p -r1.194 init_main.c --- kern/init_main.c 2 May 2002 20:27:42 -0000 1.194 +++ kern/init_main.c 19 May 2002 22:58:35 -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: kern/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 --- kern/vfs_conf.c 17 Apr 2002 13:06:36 -0000 1.68 +++ kern/vfs_conf.c 19 May 2002 23:33:55 -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,91 @@ 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; /* - * 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: kern/vfs_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.253 diff -u -p -r1.253 vfs_syscalls.c --- kern/vfs_syscalls.c 14 May 2002 21:59:49 -0000 1.253 +++ kern/vfs_syscalls.c 18 May 2002 16:12:00 -0000 @@ -434,7 +434,6 @@ vfs_nmount(td, fsflags, fsoptions) mp->mnt_flag |= fsflags & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); VOP_UNLOCK(vp, 0, td); - mp->mnt_optnew = optlist; goto update; } /* @@ -528,8 +527,8 @@ vfs_nmount(td, fsflags, fsoptions) mp->mnt_iosize_max = DFLTPHYS; VOP_UNLOCK(vp, 0, td); - mp->mnt_opt = optlist; update: + mp->mnt_optnew = optlist; /* * Check if the fs implements the new VFS_NMOUNT() * function, since the new system call was used. @@ -567,6 +566,17 @@ update: * get. No freeing of cn_pnbuf. */ error = VFS_NMOUNT(mp, &nd, td); + if (!error) { + if (mp->mnt_opt != NULL) + vfs_freeopts(mp->mnt_opt); + mp->mnt_opt = mp->mnt_optnew; + } else + vfs_freeopts(mp->mnt_optnew); + /* + * Prevent external consumers of mount + * options to read mnt_optnew. + */ + mp->mnt_optnew = NULL; if (mp->mnt_flag & MNT_UPDATE) { if (mp->mnt_kern_flag & MNTK_WANTRDWR) mp->mnt_flag &= ~MNT_RDONLY; @@ -576,10 +586,6 @@ update: if (error) { mp->mnt_flag = flag; mp->mnt_kern_flag = kern_flag; - vfs_freeopts(mp->mnt_optnew); - } else { - vfs_freeopts(mp->mnt_opt); - mp->mnt_opt = mp->mnt_optnew; } if ((mp->mnt_flag & MNT_RDONLY) == 0) { if (mp->mnt_syncer == NULL) @@ -619,10 +625,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; @@ -631,9 +635,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); @@ -1185,6 +1188,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); } /* Index: ufs/ffs/ffs_extern.h =================================================================== RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_extern.h,v retrieving revision 1.47 diff -u -p -r1.47 ffs_extern.h --- ufs/ffs/ffs_extern.h 19 Mar 2002 22:40:46 -0000 1.47 +++ ufs/ffs/ffs_extern.h 11 May 2002 16:39:26 -0000 @@ -71,9 +71,7 @@ int ffs_isblock(struct fs *, u_char *, u int ffs_isfreeblock(struct fs *, unsigned char *, ufs_daddr_t); int ffs_mountfs(struct vnode *, struct mount *, struct thread *, struct malloc_type *); -int ffs_mountroot(void); -int ffs_mount(struct mount *, char *, caddr_t, struct nameidata *, - struct thread *); +int ffs_mount(struct mount *, struct nameidata *, struct thread *); int ffs_reallocblks(struct vop_reallocblks_args *); int ffs_realloccg(struct inode *, ufs_daddr_t, ufs_daddr_t, int, int, struct ucred *, struct buf **); Index: ufs/ffs/ffs_snapshot.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_snapshot.c,v retrieving revision 1.35 diff -u -p -r1.35 ffs_snapshot.c --- ufs/ffs/ffs_snapshot.c 12 May 2002 20:21:40 -0000 1.35 +++ ufs/ffs/ffs_snapshot.c 16 May 2002 22:22:07 -0000 @@ -138,7 +138,7 @@ ffs_snapshot(mp, snapfile) * Create the snapshot file. */ restart: - NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, snapfile, td); + NDINIT(&nd, CREATE, LOCKPARENT | LOCKLEAF, UIO_SYSSPACE, snapfile, td); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { Index: ufs/ffs/ffs_vfsops.c =================================================================== RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_vfsops.c,v retrieving revision 1.178 diff -u -p -r1.178 ffs_vfsops.c --- ufs/ffs/ffs_vfsops.c 13 May 2002 09:22:28 -0000 1.178 +++ ufs/ffs/ffs_vfsops.c 16 May 2002 23:39:18 -0000 @@ -72,7 +72,7 @@ static int ffs_oldfscompat(struct fs *); static int ffs_init(struct vfsconf *); static struct vfsops ufs_vfsops = { - ffs_mount, + NULL, ufs_start, ffs_unmount, ufs_root, @@ -90,6 +90,7 @@ static struct vfsops ufs_vfsops = { #else vfs_stdextattrctl, #endif + ffs_mount, }; VFS_SET(ufs_vfsops, ufs, 0); @@ -100,17 +101,8 @@ VFS_SET(ufs_vfsops, ufs, 0); * Called when mounting local physical media * * PARAMETERS: - * mountroot - * mp mount point structure - * path NULL (flag for root mount!!!) - * data - * ndp - * p process (user credentials check [statfs]) - * * mount * mp mount point structure - * path path to mount point - * data pointer to argument struct in user space * ndp mount point namei() return (used for * credentials on reload), reused to look * up block device. @@ -126,47 +118,32 @@ VFS_SET(ufs_vfsops, ufs, 0); * EXIT * mount point is locked * - * NOTES: - * A NULL path can be used for a flag since the mount - * system call will fail with EFAULT in copyinstr in - * namei() if it is a genuine NULL from the user. */ int -ffs_mount(mp, path, data, ndp, td) +ffs_mount(mp, ndp, td) struct mount *mp; /* mount struct pointer*/ - char *path; /* path to mount point*/ - caddr_t data; /* arguments to FS specific mount*/ struct nameidata *ndp; /* mount point credentials*/ struct thread *td; /* process requesting mount*/ { - size_t size; struct vnode *devvp; - struct ufs_args args; struct ufsmount *ump = 0; + struct vfsoptlist *opts; struct fs *fs; - int error, flags; + struct export_args export; + char *path, *fspec; + int error, flags, len; mode_t accessmode; + opts = mp->mnt_optnew; /* - * Use NULL path to indicate we are mounting the root file system. - */ - if (path == NULL) { - if ((error = bdevvp(rootdev, &rootvp))) { - printf("ffs_mountroot: can't find rootvp\n"); - return (error); - } - - if ((error = ffs_mountfs(rootvp, mp, td, M_FFSNODE)) != 0) - return (error); - (void)VFS_STATFS(mp, &mp->mnt_stat, td); - return (0); - } - - /* - * Mounting non-root file system or updating a file system + * The fspath mount option is always present + * and is always a string. */ - if ((error = copyin(data, (caddr_t)&args, sizeof(struct ufs_args)))!= 0) - return (error); + vfs_getopt(opts, "fspath", (void **)&path, NULL); + fspec = NULL; + error = vfs_getopt(opts, "from", (void **)&fspec, &len); + if (!error && fspec[len - 1] != '\0') + return (EINVAL); /* * If updating, check whether changing from read-only to @@ -280,20 +257,27 @@ ffs_mount(mp, path, data, ndp, td) /* * If not updating name, process export requests. */ - if (args.fspec == 0) - return (vfs_export(mp, &args.export)); + if (fspec == NULL) { + error = vfs_getopt(opts, "export", (void **)&export, + &len); + if (error || len != sizeof(struct export_args)) + return (EINVAL); + return (vfs_export(mp, &export)); + } /* * If this is a snapshot request, take the snapshot. */ if (mp->mnt_flag & MNT_SNAPSHOT) - return (ffs_snapshot(mp, args.fspec)); + return (ffs_snapshot(mp, fspec)); } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ - NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, td); + if (fspec == NULL) + return (EINVAL); + NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td); if ((error = namei(ndp)) != 0) return (error); NDFREE(ndp, NDF_ONLY_PNBUF); @@ -350,8 +334,8 @@ ffs_mount(mp, path, data, ndp, td) /* * Save "mounted from" device name info for mount point (NULL pad). */ - copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); - bzero( mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); + strncpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN - 1); + mp->mnt_stat.f_mntfromname[MNAMELEN] = '\0'; /* * Initialize filesystem stat information in mount struct. */ --JwB53PgKC5A7+0Ej-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message