From 20a92a18f1fb48db2bb6fcb4c03501b5ca3c3b5e Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Tue, 7 Dec 2004 08:15:41 +0000 Subject: [PATCH] The remaining part of nmount/omount/rootfs mount changes. I cannot sensibly split the conversion of the remaining three filesystems out from the root mounting changes, so in one go: cd9660: Convert to nmount. Add omount compat shims. Remove dedicated rootfs mounting code. Use vfs_mountedfrom() Rely on vfs_mount.c calling VFS_STATFS() nfs(client): Convert to nmount (the simple way, mount_nfs(8) is still necessary). Add omount compat shims. Drop COMPAT_PRELITE2 mount arg compatibility. ffs: Convert to nmount. Add omount compat shims. Remove dedicated rootfs mounting code. Use vfs_mountedfrom() Rely on vfs_mount.c calling VFS_STATFS() Remove vfs_omount() method, all filesystems are now converted. Remove MNTK_WANTRDWR, handling RO/RW conversions is a filesystem task, and they all do it now. Change rootmounting to use DEVFS trampoline: vfs_mount.c: Mount devfs on /. Devfs needs no 'from' so this is clean. symlink /dev to /. This makes it possible to lookup /dev/foo. Mount "real" root filesystem on /. Surgically move the devfs mountpoint from under the real root filesystem onto /dev in the real root filesystem. Remove now unnecessary getdiskbyname(). kern_init.c: Don't do devfs mounting and rootvnode assignment here, it was already handled by vfs_mount.c. Remove now unused bdevvp(), addaliasu() and addalias(). Put the few necessary lines in devfs where they belong. This eliminates the second-last source of bogo vnodes, leaving only the lemming-syncer. Remove rootdev variable, it doesn't give meaning in a global context and was not trustworth anyway. Correct information is provided by statfs(/). --- sys/fs/cd9660/cd9660_vfsops.c | 219 ++++++---------- sys/fs/devfs/devfs_vnops.c | 9 +- sys/isofs/cd9660/cd9660_vfsops.c | 219 ++++++---------- sys/kern/init_main.c | 29 --- sys/kern/vfs_init.c | 4 +- sys/kern/vfs_mount.c | 419 ++++++++++++++++--------------- sys/kern/vfs_subr.c | 114 --------- sys/nfsclient/nfs_vfsops.c | 72 ++++-- sys/sys/mount.h | 12 +- sys/sys/systm.h | 2 +- sys/sys/vnode.h | 2 - sys/ufs/ffs/ffs_vfsops.c | 151 +++++------ 12 files changed, 498 insertions(+), 754 deletions(-) diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index 63582c078ac4..865a2e532d05 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -67,7 +67,8 @@ MALLOC_DEFINE(M_ISOFSNODE, "ISOFS node", "ISOFS vnode private part"); struct iconv_functions *cd9660_iconv = NULL; -static vfs_omount_t cd9660_omount; +static vfs_mount_t cd9660_mount; +static vfs_cmount_t cd9660_cmount; static vfs_unmount_t cd9660_unmount; static vfs_root_t cd9660_root; static vfs_statfs_t cd9660_statfs; @@ -78,7 +79,8 @@ static vfs_vptofh_t cd9660_vptofh; static struct vfsops cd9660_vfsops = { .vfs_fhtovp = cd9660_fhtovp, .vfs_init = cd9660_init, - .vfs_omount = cd9660_omount, + .vfs_mount = cd9660_mount, + .vfs_cmount = cd9660_cmount, .vfs_root = cd9660_root, .vfs_statfs = cd9660_statfs, .vfs_uninit = cd9660_uninit, @@ -89,140 +91,79 @@ static struct vfsops cd9660_vfsops = { VFS_SET(cd9660_vfsops, cd9660, VFCF_READONLY); MODULE_VERSION(cd9660, 1); -/* - * Called by vfs_mountroot when iso is going to be mounted as root. - */ - -static int iso_get_ssector(struct cdev *dev, struct thread *td); static int iso_mountfs(struct vnode *devvp, struct mount *mp, - struct thread *td, struct iso_args *argp); - -/* - * Try to find the start of the last data track on this CD-ROM. This - * is used to mount the last session of a multi-session CD. Bail out - * and return 0 if we fail, this is always a safe bet. - */ -static int -iso_get_ssector(dev, td) - struct cdev *dev; - struct thread *td; -{ - struct ioc_toc_header h; - struct ioc_read_toc_single_entry t; - int i, error; - struct cdevsw *bd; - d_ioctl_t *ioctlp; - - bd = dev_refthread(dev); - if (bd == NULL) - return 0; - ioctlp = bd->d_ioctl; - - error = ioctlp(dev, CDIOREADTOCHEADER, (caddr_t)&h, FREAD, td); - if (error) { - dev_relthread(dev); - return 0; - } - - for (i = h.ending_track; i >= 0; i--) { - t.address_format = CD_LBA_FORMAT; - t.track = i; - error = ioctlp(dev, CDIOREADTOCENTRY, (caddr_t)&t, FREAD, td); - if (error) { - dev_relthread(dev); - return 0; - } - if ((t.entry.control & 4) != 0) - /* found a data track */ - break; - } - dev_relthread(dev); - - if (i < 0) - return 0; - - return ntohl(t.entry.addr.lba); -} - -static int iso_mountroot(struct mount *mp, struct thread *td); - -static int -iso_mountroot(mp, td) - struct mount *mp; - struct thread *td; -{ - struct iso_args args; - struct vnode *rootvp; - int error; - - if ((error = bdevvp(rootdev, &rootvp))) { - printf("iso_mountroot: can't find rootvp\n"); - return (error); - } - args.flags = ISOFSMNT_ROOT; - - vn_lock(rootvp, LK_EXCLUSIVE | LK_RETRY, td); - error = VOP_OPEN(rootvp, FREAD, FSCRED, td, -1); - VOP_UNLOCK(rootvp, 0, td); - if (error) - return error; - - args.ssector = iso_get_ssector(rootdev, td); - - (void)VOP_CLOSE(rootvp, FREAD, NOCRED, td); - - if (bootverbose) - printf("iso_mountroot(): using session at block %d\n", - args.ssector); - if ((error = iso_mountfs(rootvp, mp, td, &args)) != 0) - return (error); - - (void)cd9660_statfs(mp, &mp->mnt_stat, td); - return (0); -} + struct thread *td); /* * VFS Operations. - * - * mount system call */ + static int -cd9660_omount(mp, path, data, td) - struct mount *mp; - char *path; - caddr_t data; - struct thread *td; +cd9660_cmount(struct mntarg *ma, void *data, int flags, struct thread *td) +{ + struct iso_args args; + int error; + + error = copyin(data, &args, sizeof args); + if (error) + return (error); + + ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); + ma = mount_arg(ma, "export", &args.export, sizeof args.export); + ma = mount_argsu(ma, "cs_disk", args.cs_disk, 64); + ma = mount_argsu(ma, "cs_local", args.cs_local, 64); + ma = mount_argf(ma, "ssector", "%u", args.ssector); + ma = mount_argb(ma, !(args.flags & ISOFSMNT_NORRIP), "norrip"); + ma = mount_argb(ma, args.flags & ISOFSMNT_GENS, "nogens"); + ma = mount_argb(ma, args.flags & ISOFSMNT_EXTATT, "noextatt"); + ma = mount_argb(ma, !(args.flags & ISOFSMNT_NOJOLIET), "nojoliet"); + ma = mount_argb(ma, + args.flags & ISOFSMNT_BROKENJOLIET, "nobrokenjoliet"); + ma = mount_argb(ma, args.flags & ISOFSMNT_KICONV, "nokiconv"); + ma = mount_argb(ma, args.flags & ISOFSMNT_EXTATT, "nogens"); + + error = kernel_mount(ma, flags); + + return (error); +} + +static int +cd9660_mount(struct mount *mp, struct thread *td) { struct vnode *devvp; - struct iso_args args; - size_t size; - int error; + struct export_args *export; + char *fspec; + int error, len; mode_t accessmode; - struct iso_mnt *imp = 0; struct nameidata ndp; - - if (mp->mnt_flag & MNT_ROOTFS) - return (iso_mountroot(mp, td)); - if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))) - return (error); + struct iso_mnt *imp = 0; if ((mp->mnt_flag & MNT_RDONLY) == 0) return (EROFS); + fspec = vfs_getopts(mp->mnt_optnew, "from", &error); + if (error) + return (error); + + imp = VFSTOISOFS(mp); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { - imp = VFSTOISOFS(mp); - if (args.fspec == 0) - return (vfs_export(mp, &args.export)); + if (fspec == NULL) { + error = vfs_getopt(mp->mnt_optnew, + "export", (void **)&export, &len); + if (error || len != sizeof *export) + return (EINVAL); + return (vfs_export(mp, export)); + } } /* * 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); + NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td); if ((error = namei(&ndp))) return (error); NDFREE(&ndp, NDF_ONLY_PNBUF); @@ -249,7 +190,7 @@ cd9660_omount(mp, path, data, td) VOP_UNLOCK(devvp, 0, td); if ((mp->mnt_flag & MNT_UPDATE) == 0) { - error = iso_mountfs(devvp, mp, td, &args); + error = iso_mountfs(devvp, mp, td); } else { if (devvp != imp->im_devvp) error = EINVAL; /* needs translation */ @@ -260,11 +201,7 @@ cd9660_omount(mp, path, data, td) vrele(devvp); return error; } - imp = VFSTOISOFS(mp); - (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, - &size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); - (void) cd9660_statfs(mp, &mp->mnt_stat, td); + vfs_mountedfrom(mp, fspec); return 0; } @@ -272,11 +209,10 @@ cd9660_omount(mp, path, data, td) * Common code for mount and mountroot */ static int -iso_mountfs(devvp, mp, td, argp) +iso_mountfs(devvp, mp, td) struct vnode *devvp; struct mount *mp; struct thread *td; - struct iso_args *argp; { struct iso_mnt *isomp = (struct iso_mnt *)0; struct buf *bp = NULL; @@ -292,12 +228,10 @@ iso_mountfs(devvp, mp, td, argp) struct iso_sierra_primary_descriptor *pri_sierra = NULL; struct iso_supplementary_descriptor *sup = NULL; struct iso_directory_record *rootp; - int logical_block_size; + int logical_block_size, ssector; struct g_consumer *cp; struct bufobj *bo; - - if (!(mp->mnt_flag & MNT_RDONLY)) - return EROFS; + char *cs_local, *cs_disk; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); DROP_GIANT(); @@ -324,8 +258,10 @@ iso_mountfs(devvp, mp, td, argp) iso_bsize = ISO_DEFAULT_BLOCK_SIZE; joliet_level = 0; - for (iso_blknum = 16 + argp->ssector; - iso_blknum < 100 + argp->ssector; + if (1 != vfs_scanopt(mp->mnt_optnew, "ssector", "%d", &ssector)) + ssector = 0; + for (iso_blknum = 16 + ssector; + iso_blknum < 100 + ssector; iso_blknum++) { if ((error = bread(devvp, iso_blknum * btodb(iso_bsize), iso_bsize, NOCRED, &bp)) != 0) @@ -357,7 +293,7 @@ iso_mountfs(devvp, mp, td, argp) bp = NULL; sup = (struct iso_supplementary_descriptor *)vdp; - if (!(argp->flags & ISOFSMNT_NOJOLIET)) { + if (vfs_flagopt(mp->mnt_optnew, "joliet", NULL, 0)) { if (bcmp(sup->escape, "%/@", 3) == 0) joliet_level = 1; if (bcmp(sup->escape, "%/C", 3) == 0) @@ -366,7 +302,7 @@ iso_mountfs(devvp, mp, td, argp) joliet_level = 3; if ((isonum_711 (sup->flags) & 1) && - (argp->flags & ISOFSMNT_BROKENJOLIET) == 0) + !vfs_flagopt(mp->mnt_optnew, "brokenjoliet", NULL, 0)) joliet_level = 0; } } @@ -427,7 +363,7 @@ iso_mountfs(devvp, mp, td, argp) * can't do much better. This is also important for the NFS * filehandle validation. */ - isomp->volume_space_size += argp->ssector; + isomp->volume_space_size += ssector; bcopy (rootp, isomp->root, sizeof isomp->root); isomp->root_extent = isonum_733 (rootp->extent); isomp->root_size = isonum_733 (rootp->size); @@ -448,8 +384,14 @@ iso_mountfs(devvp, mp, td, argp) isomp->im_dev = dev; isomp->im_devvp = devvp; + vfs_flagopt(mp->mnt_optnew, "rrip", &isomp->im_flags, ISOFSMNT_NORRIP); + vfs_flagopt(mp->mnt_optnew, "gens", &isomp->im_flags, ISOFSMNT_GENS); + vfs_flagopt(mp->mnt_optnew, "extatt", &isomp->im_flags, ISOFSMNT_EXTATT); + vfs_flagopt(mp->mnt_optnew, "joliet", &isomp->im_flags, ISOFSMNT_NOJOLIET); + vfs_flagopt(mp->mnt_optnew, "kiconv", &isomp->im_flags, ISOFSMNT_KICONV); + isomp->im_flags ^= (ISOFSMNT_NORRIP | ISOFSMNT_NOJOLIET); /* Check the Rock Ridge Extention support */ - if (!(argp->flags & ISOFSMNT_NORRIP)) { + if (vfs_flagopt(mp->mnt_optnew, "rrip", NULL, 0)) { if ((error = bread(isomp->im_devvp, (isomp->root_extent + isonum_711(rootp->ext_attr_length)) << (isomp->im_bshift - DEV_BSHIFT), @@ -459,9 +401,9 @@ iso_mountfs(devvp, mp, td, argp) rootp = (struct iso_directory_record *)bp->b_data; if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) { - argp->flags |= ISOFSMNT_NORRIP; + isomp->im_flags |= ISOFSMNT_NORRIP; } else { - argp->flags &= ~ISOFSMNT_GENS; + isomp->im_flags &= ~ISOFSMNT_GENS; } /* @@ -472,13 +414,16 @@ iso_mountfs(devvp, mp, td, argp) brelse(bp); bp = NULL; } - isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS | - ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | - ISOFSMNT_KICONV); if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) { - cd9660_iconv->open(argp->cs_local, argp->cs_disk, &isomp->im_d2l); - cd9660_iconv->open(argp->cs_disk, argp->cs_local, &isomp->im_l2d); + cs_local = vfs_getopts(mp->mnt_optnew, "cs_local", &error); + if (error) + goto out; + cs_disk = vfs_getopts(mp->mnt_optnew, "cs_disk", &error); + if (error) + goto out; + cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l); + cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d); } else { isomp->im_d2l = NULL; isomp->im_l2d = NULL; diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 1eecbf1b80cb..8833baf21493 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -194,7 +194,14 @@ devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, stru if (de->de_dirent->d_type == DT_CHR) { vp->v_type = VCHR; - vp = addaliasu(vp, dev->si_udev); + VI_LOCK(vp); + dev_lock(); + dev->si_refcount++; + vp->v_rdev = dev; + SLIST_INSERT_HEAD(&dev->si_hlist, vp, v_specnext); + dev->si_usecount += vp->v_usecount; + dev_unlock(); + VI_UNLOCK(vp); vp->v_op = &devfs_specops; } else if (de->de_dirent->d_type == DT_DIR) { vp->v_type = VDIR; diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c index 63582c078ac4..865a2e532d05 100644 --- a/sys/isofs/cd9660/cd9660_vfsops.c +++ b/sys/isofs/cd9660/cd9660_vfsops.c @@ -67,7 +67,8 @@ MALLOC_DEFINE(M_ISOFSNODE, "ISOFS node", "ISOFS vnode private part"); struct iconv_functions *cd9660_iconv = NULL; -static vfs_omount_t cd9660_omount; +static vfs_mount_t cd9660_mount; +static vfs_cmount_t cd9660_cmount; static vfs_unmount_t cd9660_unmount; static vfs_root_t cd9660_root; static vfs_statfs_t cd9660_statfs; @@ -78,7 +79,8 @@ static vfs_vptofh_t cd9660_vptofh; static struct vfsops cd9660_vfsops = { .vfs_fhtovp = cd9660_fhtovp, .vfs_init = cd9660_init, - .vfs_omount = cd9660_omount, + .vfs_mount = cd9660_mount, + .vfs_cmount = cd9660_cmount, .vfs_root = cd9660_root, .vfs_statfs = cd9660_statfs, .vfs_uninit = cd9660_uninit, @@ -89,140 +91,79 @@ static struct vfsops cd9660_vfsops = { VFS_SET(cd9660_vfsops, cd9660, VFCF_READONLY); MODULE_VERSION(cd9660, 1); -/* - * Called by vfs_mountroot when iso is going to be mounted as root. - */ - -static int iso_get_ssector(struct cdev *dev, struct thread *td); static int iso_mountfs(struct vnode *devvp, struct mount *mp, - struct thread *td, struct iso_args *argp); - -/* - * Try to find the start of the last data track on this CD-ROM. This - * is used to mount the last session of a multi-session CD. Bail out - * and return 0 if we fail, this is always a safe bet. - */ -static int -iso_get_ssector(dev, td) - struct cdev *dev; - struct thread *td; -{ - struct ioc_toc_header h; - struct ioc_read_toc_single_entry t; - int i, error; - struct cdevsw *bd; - d_ioctl_t *ioctlp; - - bd = dev_refthread(dev); - if (bd == NULL) - return 0; - ioctlp = bd->d_ioctl; - - error = ioctlp(dev, CDIOREADTOCHEADER, (caddr_t)&h, FREAD, td); - if (error) { - dev_relthread(dev); - return 0; - } - - for (i = h.ending_track; i >= 0; i--) { - t.address_format = CD_LBA_FORMAT; - t.track = i; - error = ioctlp(dev, CDIOREADTOCENTRY, (caddr_t)&t, FREAD, td); - if (error) { - dev_relthread(dev); - return 0; - } - if ((t.entry.control & 4) != 0) - /* found a data track */ - break; - } - dev_relthread(dev); - - if (i < 0) - return 0; - - return ntohl(t.entry.addr.lba); -} - -static int iso_mountroot(struct mount *mp, struct thread *td); - -static int -iso_mountroot(mp, td) - struct mount *mp; - struct thread *td; -{ - struct iso_args args; - struct vnode *rootvp; - int error; - - if ((error = bdevvp(rootdev, &rootvp))) { - printf("iso_mountroot: can't find rootvp\n"); - return (error); - } - args.flags = ISOFSMNT_ROOT; - - vn_lock(rootvp, LK_EXCLUSIVE | LK_RETRY, td); - error = VOP_OPEN(rootvp, FREAD, FSCRED, td, -1); - VOP_UNLOCK(rootvp, 0, td); - if (error) - return error; - - args.ssector = iso_get_ssector(rootdev, td); - - (void)VOP_CLOSE(rootvp, FREAD, NOCRED, td); - - if (bootverbose) - printf("iso_mountroot(): using session at block %d\n", - args.ssector); - if ((error = iso_mountfs(rootvp, mp, td, &args)) != 0) - return (error); - - (void)cd9660_statfs(mp, &mp->mnt_stat, td); - return (0); -} + struct thread *td); /* * VFS Operations. - * - * mount system call */ + static int -cd9660_omount(mp, path, data, td) - struct mount *mp; - char *path; - caddr_t data; - struct thread *td; +cd9660_cmount(struct mntarg *ma, void *data, int flags, struct thread *td) +{ + struct iso_args args; + int error; + + error = copyin(data, &args, sizeof args); + if (error) + return (error); + + ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); + ma = mount_arg(ma, "export", &args.export, sizeof args.export); + ma = mount_argsu(ma, "cs_disk", args.cs_disk, 64); + ma = mount_argsu(ma, "cs_local", args.cs_local, 64); + ma = mount_argf(ma, "ssector", "%u", args.ssector); + ma = mount_argb(ma, !(args.flags & ISOFSMNT_NORRIP), "norrip"); + ma = mount_argb(ma, args.flags & ISOFSMNT_GENS, "nogens"); + ma = mount_argb(ma, args.flags & ISOFSMNT_EXTATT, "noextatt"); + ma = mount_argb(ma, !(args.flags & ISOFSMNT_NOJOLIET), "nojoliet"); + ma = mount_argb(ma, + args.flags & ISOFSMNT_BROKENJOLIET, "nobrokenjoliet"); + ma = mount_argb(ma, args.flags & ISOFSMNT_KICONV, "nokiconv"); + ma = mount_argb(ma, args.flags & ISOFSMNT_EXTATT, "nogens"); + + error = kernel_mount(ma, flags); + + return (error); +} + +static int +cd9660_mount(struct mount *mp, struct thread *td) { struct vnode *devvp; - struct iso_args args; - size_t size; - int error; + struct export_args *export; + char *fspec; + int error, len; mode_t accessmode; - struct iso_mnt *imp = 0; struct nameidata ndp; - - if (mp->mnt_flag & MNT_ROOTFS) - return (iso_mountroot(mp, td)); - if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))) - return (error); + struct iso_mnt *imp = 0; if ((mp->mnt_flag & MNT_RDONLY) == 0) return (EROFS); + fspec = vfs_getopts(mp->mnt_optnew, "from", &error); + if (error) + return (error); + + imp = VFSTOISOFS(mp); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { - imp = VFSTOISOFS(mp); - if (args.fspec == 0) - return (vfs_export(mp, &args.export)); + if (fspec == NULL) { + error = vfs_getopt(mp->mnt_optnew, + "export", (void **)&export, &len); + if (error || len != sizeof *export) + return (EINVAL); + return (vfs_export(mp, export)); + } } /* * 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); + NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td); if ((error = namei(&ndp))) return (error); NDFREE(&ndp, NDF_ONLY_PNBUF); @@ -249,7 +190,7 @@ cd9660_omount(mp, path, data, td) VOP_UNLOCK(devvp, 0, td); if ((mp->mnt_flag & MNT_UPDATE) == 0) { - error = iso_mountfs(devvp, mp, td, &args); + error = iso_mountfs(devvp, mp, td); } else { if (devvp != imp->im_devvp) error = EINVAL; /* needs translation */ @@ -260,11 +201,7 @@ cd9660_omount(mp, path, data, td) vrele(devvp); return error; } - imp = VFSTOISOFS(mp); - (void) copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, - &size); - bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); - (void) cd9660_statfs(mp, &mp->mnt_stat, td); + vfs_mountedfrom(mp, fspec); return 0; } @@ -272,11 +209,10 @@ cd9660_omount(mp, path, data, td) * Common code for mount and mountroot */ static int -iso_mountfs(devvp, mp, td, argp) +iso_mountfs(devvp, mp, td) struct vnode *devvp; struct mount *mp; struct thread *td; - struct iso_args *argp; { struct iso_mnt *isomp = (struct iso_mnt *)0; struct buf *bp = NULL; @@ -292,12 +228,10 @@ iso_mountfs(devvp, mp, td, argp) struct iso_sierra_primary_descriptor *pri_sierra = NULL; struct iso_supplementary_descriptor *sup = NULL; struct iso_directory_record *rootp; - int logical_block_size; + int logical_block_size, ssector; struct g_consumer *cp; struct bufobj *bo; - - if (!(mp->mnt_flag & MNT_RDONLY)) - return EROFS; + char *cs_local, *cs_disk; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); DROP_GIANT(); @@ -324,8 +258,10 @@ iso_mountfs(devvp, mp, td, argp) iso_bsize = ISO_DEFAULT_BLOCK_SIZE; joliet_level = 0; - for (iso_blknum = 16 + argp->ssector; - iso_blknum < 100 + argp->ssector; + if (1 != vfs_scanopt(mp->mnt_optnew, "ssector", "%d", &ssector)) + ssector = 0; + for (iso_blknum = 16 + ssector; + iso_blknum < 100 + ssector; iso_blknum++) { if ((error = bread(devvp, iso_blknum * btodb(iso_bsize), iso_bsize, NOCRED, &bp)) != 0) @@ -357,7 +293,7 @@ iso_mountfs(devvp, mp, td, argp) bp = NULL; sup = (struct iso_supplementary_descriptor *)vdp; - if (!(argp->flags & ISOFSMNT_NOJOLIET)) { + if (vfs_flagopt(mp->mnt_optnew, "joliet", NULL, 0)) { if (bcmp(sup->escape, "%/@", 3) == 0) joliet_level = 1; if (bcmp(sup->escape, "%/C", 3) == 0) @@ -366,7 +302,7 @@ iso_mountfs(devvp, mp, td, argp) joliet_level = 3; if ((isonum_711 (sup->flags) & 1) && - (argp->flags & ISOFSMNT_BROKENJOLIET) == 0) + !vfs_flagopt(mp->mnt_optnew, "brokenjoliet", NULL, 0)) joliet_level = 0; } } @@ -427,7 +363,7 @@ iso_mountfs(devvp, mp, td, argp) * can't do much better. This is also important for the NFS * filehandle validation. */ - isomp->volume_space_size += argp->ssector; + isomp->volume_space_size += ssector; bcopy (rootp, isomp->root, sizeof isomp->root); isomp->root_extent = isonum_733 (rootp->extent); isomp->root_size = isonum_733 (rootp->size); @@ -448,8 +384,14 @@ iso_mountfs(devvp, mp, td, argp) isomp->im_dev = dev; isomp->im_devvp = devvp; + vfs_flagopt(mp->mnt_optnew, "rrip", &isomp->im_flags, ISOFSMNT_NORRIP); + vfs_flagopt(mp->mnt_optnew, "gens", &isomp->im_flags, ISOFSMNT_GENS); + vfs_flagopt(mp->mnt_optnew, "extatt", &isomp->im_flags, ISOFSMNT_EXTATT); + vfs_flagopt(mp->mnt_optnew, "joliet", &isomp->im_flags, ISOFSMNT_NOJOLIET); + vfs_flagopt(mp->mnt_optnew, "kiconv", &isomp->im_flags, ISOFSMNT_KICONV); + isomp->im_flags ^= (ISOFSMNT_NORRIP | ISOFSMNT_NOJOLIET); /* Check the Rock Ridge Extention support */ - if (!(argp->flags & ISOFSMNT_NORRIP)) { + if (vfs_flagopt(mp->mnt_optnew, "rrip", NULL, 0)) { if ((error = bread(isomp->im_devvp, (isomp->root_extent + isonum_711(rootp->ext_attr_length)) << (isomp->im_bshift - DEV_BSHIFT), @@ -459,9 +401,9 @@ iso_mountfs(devvp, mp, td, argp) rootp = (struct iso_directory_record *)bp->b_data; if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) { - argp->flags |= ISOFSMNT_NORRIP; + isomp->im_flags |= ISOFSMNT_NORRIP; } else { - argp->flags &= ~ISOFSMNT_GENS; + isomp->im_flags &= ~ISOFSMNT_GENS; } /* @@ -472,13 +414,16 @@ iso_mountfs(devvp, mp, td, argp) brelse(bp); bp = NULL; } - isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS | - ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET | - ISOFSMNT_KICONV); if (isomp->im_flags & ISOFSMNT_KICONV && cd9660_iconv) { - cd9660_iconv->open(argp->cs_local, argp->cs_disk, &isomp->im_d2l); - cd9660_iconv->open(argp->cs_disk, argp->cs_local, &isomp->im_l2d); + cs_local = vfs_getopts(mp->mnt_optnew, "cs_local", &error); + if (error) + goto out; + cs_disk = vfs_getopts(mp->mnt_optnew, "cs_disk", &error); + if (error) + goto out; + cd9660_iconv->open(cs_local, cs_disk, &isomp->im_d2l); + cd9660_iconv->open(cs_disk, cs_local, &isomp->im_l2d); } else { isomp->im_d2l = NULL; isomp->im_l2d = NULL; diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 84f6fd2a2b51..a83fbaf2e0f5 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -512,7 +512,6 @@ start_init(void *dummy) char *ucp, **uap, *arg0, *arg1; struct thread *td; struct proc *p; - int init_does_devfs = 0; mtx_lock(&Giant); @@ -523,34 +522,10 @@ start_init(void *dummy) vfs_mountroot(); - /* Get the vnode for '/'. Set p->p_fd->fd_cdir to reference it. */ - if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode, td)) - 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); #ifdef MAC mac_create_root_mount(td->td_ucred, TAILQ_FIRST(&mountlist)); #endif - /* - * 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 = kern_mkdir(td, "/dev", UIO_SYSSPACE, 0700); - if (error == EEXIST) - error = 0; - if (error == 0) - error = kernel_vmount(0, "fstype", "devfs", - "fspath", "/dev", NULL); - if (error != 0) - init_does_devfs = 1; - /* * Need just enough stack to hold the faked-up "execve()" arguments. */ @@ -598,10 +573,6 @@ start_init(void *dummy) (void)subyte(--ucp, 'C'); options = 1; #endif - if (init_does_devfs) { - (void)subyte(--ucp, 'd'); - options = 1; - } if (options == 0) (void)subyte(--ucp, '-'); diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index da365d4f1891..8ce79d3298c8 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -216,8 +216,8 @@ vfs_register(struct vfsconf *vfc) * Check the mount and unmount operations. */ vfsops = vfc->vfc_vfsops; - KASSERT(vfsops->vfs_mount != NULL || vfsops->vfs_omount != NULL, - ("Filesystem %s has no (o)mount op", vfc->vfc_name)); + KASSERT(vfsops->vfs_mount != NULL, + ("Filesystem %s has no mount op", vfc->vfc_name)); KASSERT(vfsops->vfs_unmount != NULL, ("Filesystem %s has no unmount op", vfc->vfc_name)); diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index d2e823e564cc..5be63c97f26a 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -73,10 +74,9 @@ __FBSDID("$FreeBSD$"); #define VFS_MOUNTARG_SIZE_MAX (1024 * 64) static void checkdirs(struct vnode *olddp, struct vnode *newdp); -static struct cdev *getdiskbyname(char *_name); static void gets(char *cp); static int vfs_domount(struct thread *td, const char *fstype, - char *fspath, int fsflags, void *fsdata, int compat); + char *fspath, int fsflags, void *fsdata); static int vfs_mount_alloc(struct vnode *dvp, struct vfsconf *vfsp, const char *fspath, struct thread *td, struct mount **mpp); static int vfs_mountroot_ask(void); @@ -144,12 +144,15 @@ static char *cdrom_rootdevnames[] = { /* legacy find-root code */ char *rootdevnames[2] = {NULL, NULL}; -struct cdev *rootdev = NULL; -#ifdef ROOTDEVNAME -const char *ctrootdevname = ROOTDEVNAME; -#else -const char *ctrootdevname = NULL; +#ifndef ROOTDEVNAME +# define ROOTDEVNAME NULL #endif +const char *ctrootdevname = ROOTDEVNAME; + +/* + * --------------------------------------------------------------------- + * Functions for building and sanitizing the mount options + */ /* Remove one mount option. */ static void @@ -344,7 +347,8 @@ vfs_mergeopts(struct vfsoptlist *toopts, struct vfsoptlist *opts) } /* - * New mount API. + * --------------------------------------------------------------------- + * Mount a filesystem */ int nmount(td, uap) @@ -389,6 +393,11 @@ nmount(td, uap) return (error); } +/* + * --------------------------------------------------------------------- + * Various utility functions + */ + /* * Allocate and initialize the mount point struct. */ @@ -487,7 +496,7 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions) } mtx_lock(&Giant); - error = vfs_domount(td, fstype, fspath, fsflags, optlist, 0); + error = vfs_domount(td, fstype, fspath, fsflags, optlist); mtx_unlock(&Giant); bail: if (error) @@ -496,6 +505,7 @@ vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions) } /* + * --------------------------------------------------------------------- * Old mount API. */ #ifndef _SYS_SYSPROTO_H_ @@ -518,49 +528,42 @@ mount(td, uap) } */ *uap; { char *fstype; - char *fspath; - struct vfsconf *vfsp; + struct vfsconf *vfsp = NULL; struct mntarg *ma = NULL; int error; /* Kick out MNT_ROOTFS early as it is legal internally */ uap->flags &= ~MNT_ROOTFS; - fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK); + if (uap->data == NULL) + return (EINVAL); - /* - * vfs_mount() actually takes a kernel string for `type' and - * `path' now, so extract them. - */ + fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK); error = copyinstr(uap->type, fstype, MFSNAMELEN, NULL); - mtx_lock(&Giant); /* XXX ? */ - vfsp = vfs_byname_kld(fstype, td, &error); - mtx_unlock(&Giant); /* XXX ? */ - if (vfsp == NULL) { - free(fstype, M_TEMP); - return (ENOENT); - } - fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK); - error = copyinstr(uap->path, fspath, MNAMELEN, NULL); - if (error == 0 && vfsp->vfc_vfsops->vfs_cmount != NULL) { - ma = mount_argsu(ma, "fstype", uap->type, MNAMELEN); - ma = mount_argsu(ma, "fspath", uap->path, MNAMELEN); - ma = mount_argb(ma, uap->flags & MNT_RDONLY, "noro"); - ma = mount_argb(ma, !(uap->flags & MNT_NOSUID), "nosuid"); - ma = mount_argb(ma, !(uap->flags & MNT_NOEXEC), "noexec"); - error = vfsp->vfc_vfsops->vfs_cmount( - ma, uap->data, uap->flags, td); - } else if (error == 0) { - mtx_lock(&Giant); - error = vfs_domount(td, fstype, fspath, - uap->flags, uap->data, 1); + if (!error) { + mtx_lock(&Giant); /* XXX ? */ + vfsp = vfs_byname_kld(fstype, td, &error); mtx_unlock(&Giant); } free(fstype, M_TEMP); - free(fspath, M_TEMP); + if (error) + return (error); + if (vfsp == NULL) + return (ENOENT); + if (vfsp->vfc_vfsops->vfs_cmount == NULL) + return (EOPNOTSUPP); + + ma = mount_argsu(ma, "fstype", uap->type, MNAMELEN); + ma = mount_argsu(ma, "fspath", uap->path, MNAMELEN); + ma = mount_argb(ma, uap->flags & MNT_RDONLY, "noro"); + ma = mount_argb(ma, !(uap->flags & MNT_NOSUID), "nosuid"); + ma = mount_argb(ma, !(uap->flags & MNT_NOEXEC), "noexec"); + + error = vfsp->vfc_vfsops->vfs_cmount(ma, uap->data, uap->flags, td); return (error); } + /* * vfs_domount(): actually attempt a filesystem mount. */ @@ -570,8 +573,7 @@ vfs_domount( const char *fstype, /* Filesystem type. */ char *fspath, /* Mount path. */ int fsflags, /* Flags common to all filesystems. */ - void *fsdata, /* Options local to the filesystem. */ - int compat /* Invocation from compat syscall. */ + void *fsdata /* Options local to the filesystem. */ ) { struct vnode *vp; @@ -660,12 +662,10 @@ vfs_domount( vp->v_iflag |= VI_MOUNT; VI_UNLOCK(vp); mp->mnt_flag |= fsflags & - (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); + (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT | MNT_ROOTFS); VOP_UNLOCK(vp, 0, td); - if (compat == 0) { - mp->mnt_optnew = fsdata; - vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt); - } + mp->mnt_optnew = fsdata; + vfs_mergeopts(mp->mnt_optnew, mp->mnt_opt); } else { /* * If the user is not root, ensure that they own the directory @@ -682,7 +682,8 @@ vfs_domount( return (error); } } - if ((error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0)) != 0) { + error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0); + if (error != 0) { vput(vp); return (error); } @@ -716,26 +717,7 @@ vfs_domount( VOP_UNLOCK(vp, 0, td); /* XXXMAC: pass to vfs_mount_alloc? */ - if (compat == 0) - mp->mnt_optnew = fsdata; - } - /* - * Check if the fs implements the type VFS_[O]MOUNT() - * function we are looking for. - */ - if ((compat && (mp->mnt_op->vfs_omount == NULL)) || - (!compat && (mp->mnt_op->vfs_mount == NULL))) { - printf("%s doesn't support the %s mount syscall\n", - mp->mnt_vfc->vfc_name, compat ? "old" : "new"); - VI_LOCK(vp); - vp->v_iflag &= ~VI_MOUNT; - VI_UNLOCK(vp); - if (mp->mnt_flag & MNT_UPDATE) - vfs_unbusy(mp, td); - else - vfs_mount_destroy(mp, td); - vrele(vp); - return (EOPNOTSUPP); + mp->mnt_optnew = fsdata; } /* @@ -743,19 +725,14 @@ vfs_domount( */ if (fsflags & MNT_RDONLY) mp->mnt_flag |= MNT_RDONLY; - else if (mp->mnt_flag & MNT_RDONLY) - mp->mnt_kern_flag |= MNTK_WANTRDWR; mp->mnt_flag &=~ MNT_UPDATEMASK; - mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE); + mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS); /* * Mount the filesystem. * XXX The final recipients of VFS_MOUNT just overwrite the ndp they * get. No freeing of cn_pnbuf. */ - if (compat) - error = VFS_OMOUNT(mp, fspath, fsdata, td); - else - error = VFS_MOUNT(mp, td); + error = VFS_MOUNT(mp, td); if (!error) { if (mp->mnt_opt != NULL) vfs_freeopts(mp->mnt_opt); @@ -768,11 +745,8 @@ vfs_domount( */ mp->mnt_optnew = NULL; if (mp->mnt_flag & MNT_UPDATE) { - if (mp->mnt_kern_flag & MNTK_WANTRDWR) - mp->mnt_flag &= ~MNT_RDONLY; mp->mnt_flag &= ~(MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT); - mp->mnt_kern_flag &= ~MNTK_WANTRDWR; if (error) { mp->mnt_flag = flag; mp->mnt_kern_flag = kern_flag; @@ -877,6 +851,7 @@ checkdirs(olddp, newdp) } /* + * --------------------------------------------------------------------- * Unmount a filesystem. * * Note: unmount takes a path to the vnode mounted on as argument, @@ -1063,6 +1038,146 @@ dounmount(mp, flags, td) return (0); } +/* + * --------------------------------------------------------------------- + * Mounting of root filesystem + * + */ + +static void +set_rootvnode(struct thread *td) +{ + struct proc *p; + + if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode, td)) + panic("Cannot find root vnode"); + + p = td->td_proc; + FILEDESC_LOCK(p->p_fd); + + if (p->p_fd->fd_cdir != NULL) + vrele(p->p_fd->fd_cdir); + p->p_fd->fd_cdir = rootvnode; + VREF(rootvnode); + + if (p->p_fd->fd_rdir != NULL) + vrele(p->p_fd->fd_rdir); + p->p_fd->fd_rdir = rootvnode; + VREF(rootvnode); + + FILEDESC_UNLOCK(p->p_fd); + + VOP_UNLOCK(rootvnode, 0, td); +} + +/* + * Mount /devfs as our root filesystem, but do not put it on the mountlist + * yet. Create a /dev -> / symlink so that absolute pathnames will lookup. + */ + +static struct mount * +devfs_first(void) +{ + struct thread *td = curthread; + struct vfsconf *vfsp; + struct mount *mp = NULL; + int error; + + vfsp = vfs_byname("devfs"); + KASSERT(vfsp != NULL, ("Could not find devfs by name")); + if (vfsp == NULL) + return(NULL); + + error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp); + KASSERT(error == 0, ("vfs_mount_alloc failed %d", error)); + if (error) + return (NULL); + + error = VFS_MOUNT(mp, curthread); + KASSERT(error == 0, ("VFS_MOUNT(devfs) failed %d", error)); + if (error) + return (NULL); + + VFS_START(mp, 0, td); + + mtx_lock(&mountlist_mtx); + TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list); + mtx_unlock(&mountlist_mtx); + + set_rootvnode(td); + + error = kern_symlink(td, "/", "dev", UIO_SYSSPACE); + printf("kern_symlink = %d\n", error); + + return (mp); +} + +/* + * Surgically move our devfs to be mounted on /dev. + */ + +static void +devfs_fixup(struct thread *td) +{ + struct nameidata nd; + int error; + struct vnode *vp, *dvp; + struct mount *mp; + + /* Remove our devfs mount from the mountlist and purge the cache */ + mtx_lock(&mountlist_mtx); + mp = TAILQ_FIRST(&mountlist); + TAILQ_REMOVE(&mountlist, mp, mnt_list); + mtx_unlock(&mountlist_mtx); + cache_purgevfs(mp); + + VFS_ROOT(mp, &dvp, td); + VI_LOCK(dvp); + dvp->v_iflag &= ~VI_MOUNT; + dvp->v_mountedhere = NULL; + VI_UNLOCK(dvp); + + /* Set up the real rootvnode, and purge the cache */ + TAILQ_FIRST(&mountlist)->mnt_vnodecovered = NULL; + set_rootvnode(td); + cache_purgevfs(rootvnode->v_mount); + + +#if 0 + /* We may have a chance... */ + error = kern_mkdir(td, "/dev", UIO_SYSSPACE, 0700); + printf("kern_mkdir = %d\n", error); +#endif + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, "/dev", td); + error = namei(&nd); + if (error) { + printf("Lookup /dev -> %d\n", error); + return; + } + NDFREE(&nd, NDF_ONLY_PNBUF); + vp = nd.ni_vp; + if (vp->v_type != VDIR) { + vput(vp); + } + error = vinvalbuf(vp, V_SAVE, td->td_ucred, td, 0, 0); + if (error) { + vput(vp); + } + cache_purge(vp); + mp->mnt_vnodecovered = vp; + vp->v_mountedhere = mp; + mtx_lock(&mountlist_mtx); + TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); + mtx_unlock(&mountlist_mtx); + VOP_UNLOCK(vp, 0, td); + vfs_unbusy(mp, td); + VREF(vp); + vput(vp); + vput(dvp); + +} + /* * Find and mount the root filesystem */ @@ -1071,7 +1186,7 @@ vfs_mountroot(void) { char *cp; int error, i, asked = 0; - + struct mount *mp; /* * Wait for GEOM to settle down @@ -1080,6 +1195,8 @@ vfs_mountroot(void) g_waitidle(); PICKUP_GIANT(); + mp = devfs_first(); + /* * We are booted with instructions to prompt for the root filesystem. */ @@ -1138,7 +1255,6 @@ vfs_mountroot(void) if (ctrootdevname != NULL) if (!vfs_mountroot_try(ctrootdevname)) return; - /* * Everything so far has failed, prompt on the console if we haven't * already tried that. @@ -1146,6 +1262,7 @@ vfs_mountroot(void) if (!asked) if (!vfs_mountroot_ask()) return; + panic("Root mount failed, startup aborted."); } @@ -1156,8 +1273,6 @@ static int vfs_mountroot_try(const char *mountfrom) { struct mount *mp; - struct thread *td = curthread; - struct vfsconf *vfsp; char *vfsname, *path; int error; char patt[32]; @@ -1181,68 +1296,36 @@ vfs_mountroot_try(const char *mountfrom) vfsname[0] = path[0] = 0; sprintf(patt, "%%%d[a-z0-9]:%%%ds", MFSNAMELEN, MNAMELEN); if (sscanf(mountfrom, patt, vfsname, path) < 1) - goto done; + return (error); if (path[0] == '\0') strcpy(path, ROOTNAME); - vfsp = vfs_byname(vfsname); - if (vfsp == NULL) { - printf("Can't find filesystem \"%s\"\n", vfsname); - goto done; - } - error = vfs_mount_alloc(NULLVP, vfsp, "/", td, &mp); - if (error) { - printf("Could not alloc mountpoint\n"); - goto done; - } - - mp->mnt_flag |= MNT_RDONLY | MNT_ROOTFS; - - strlcpy(mp->mnt_stat.f_mntfromname, path, MNAMELEN); - - /* - * do our best to set rootdev - * XXX: This does not belong here! - */ - if (path[0] != '\0') { - struct cdev *diskdev; - diskdev = getdiskbyname(path); - if (diskdev != NULL) - rootdev = diskdev; - else - printf("setrootbyname failed\n"); - } - - error = VFS_OMOUNT(mp, path, NULL, curthread); - -done: - if (vfsname != NULL) - free(vfsname, M_MOUNT); - if (path != NULL) - free(path, M_MOUNT); - if (error != 0) { - if (mp != NULL) - vfs_mount_destroy(mp, curthread); - 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); + error = kernel_vmount( + MNT_RDONLY | MNT_ROOTFS, + "fstype", vfsname, + "fspath", "/", + "from", path, + NULL); + printf("kernel_vmount = %d\n", error); + if (error == 0) { + mp = TAILQ_FIRST(&mountlist); /* sanity check system clock against root fs timestamp */ inittodr(mp->mnt_time); vfs_unbusy(mp, curthread); error = VFS_START(mp, 0, curthread); + + devfs_fixup(curthread); } return (error); } /* - * Spin prompting on the console for a suitable root filesystem + * --------------------------------------------------------------------- + * Interactive root filesystem selection code. */ + static int vfs_mountroot_ask(void) { @@ -1313,86 +1396,6 @@ gets(char *cp) } } -/* - * Convert a given name to the cdev pointer of the device, which is probably - * but not by definition, a disk. Mount a DEVFS (on nothing), look the name - * up, extract the cdev from the vnode and unmount it again. Unfortunately - * we cannot use the vnode directly (because we unmount the DEVFS again) - * so the filesystems still have to do the bdevvp() stunt. - */ -static struct cdev * -getdiskbyname(char *name) -{ - char *cp = name; - struct cdev *dev = NULL; - struct thread *td = curthread; - struct vfsconf *vfsp; - struct mount *mp = NULL; - struct vnode *vroot = NULL; - struct nameidata nid; - int error; - - if (!bcmp(cp, "/dev/", 5)) - cp += 5; - - do { - vfsp = vfs_byname("devfs"); - if (vfsp == NULL) - break; - error = vfs_mount_alloc(NULLVP, vfsp, "/dev", td, &mp); - if (error) - break; - mp->mnt_flag |= MNT_RDONLY; - - error = VFS_MOUNT(mp, curthread); - if (error) - break; - VFS_START(mp, 0, td); - VFS_ROOT(mp, &vroot, td); - VOP_UNLOCK(vroot, 0, td); - - NDINIT(&nid, LOOKUP, NOCACHE|FOLLOW, - UIO_SYSSPACE, cp, curthread); - nid.ni_startdir = vroot; - nid.ni_pathlen = strlen(cp); - nid.ni_cnd.cn_cred = curthread->td_ucred; - nid.ni_cnd.cn_nameptr = cp; - - error = lookup(&nid); - if (error) - break; - if (nid.ni_vp->v_type != VCHR) - dev = NULL; - else - dev = nid.ni_vp->v_rdev; - NDFREE(&nid, 0); - } while (0); - - if (vroot != NULL) - VFS_UNMOUNT(mp, 0, td); - if (mp != NULL) - vfs_mount_destroy(mp, td); - return (dev); -} - -/* Show the struct cdev *for a disk specified by name */ -#ifdef DDB -DB_SHOW_COMMAND(disk, db_getdiskbyname) -{ - struct cdev *dev; - - if (modif[0] == '\0') { - db_error("usage: show disk/devicename"); - return; - } - dev = getdiskbyname(modif); - if (dev != NULL) - db_printf("struct cdev *= %p\n", dev); - else - db_printf("No disk device matched.\n"); -} -#endif - /* * --------------------------------------------------------------------- * Functions for querying mount options/arguments from filesystems. @@ -1515,6 +1518,7 @@ vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...) } return (0); } + /* * Find and copy a mount option. * @@ -1545,7 +1549,6 @@ vfs_copyopt(opts, name, dest, len) return (ENOENT); } - /* * This is a helper function for filesystems to traverse their * vnodes. See MNT_VNODE_FOREACH() in sys/mount.h diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index e083aa768753..83230912d4fb 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$"); static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); -static void addalias(struct vnode *vp, struct cdev *nvp_rdev); static void delmntque(struct vnode *vp); static void insmntque(struct vnode *vp, struct mount *mp); static void vclean(struct vnode *vp, int flags, struct thread *td); @@ -1752,39 +1751,6 @@ reassignbuf(struct buf *bp) VI_UNLOCK(vp); } -/* - * Create a vnode for a device. - * Used for mounting the root filesystem. - */ -int -bdevvp(dev, vpp) - struct cdev *dev; - struct vnode **vpp; -{ - register struct vnode *vp; - struct vnode *nvp; - int error; - - if (dev == NULL) { - *vpp = NULLVP; - return (ENXIO); - } - if (vfinddev(dev, vpp)) - return (0); - - error = getnewvnode("none", (struct mount *)0, &devfs_specops, &nvp); - if (error) { - *vpp = NULLVP; - return (error); - } - vp = nvp; - vp->v_type = VCHR; - vp->v_bufobj.bo_bsize = DEV_BSIZE; - addalias(vp, dev); - *vpp = vp; - return (0); -} - static void v_incr_usecount(struct vnode *vp, int delta) { @@ -1797,86 +1763,6 @@ v_incr_usecount(struct vnode *vp, int delta) } } -/* - * Add vnode to the alias list hung off the struct cdev *. - * - * The reason for this gunk is that multiple vnodes can reference - * the same physical device, so checking vp->v_usecount to see - * how many users there are is inadequate; the v_usecount for - * the vnodes need to be accumulated. vcount() does that. - */ -struct vnode * -addaliasu(nvp, nvp_rdev) - struct vnode *nvp; - dev_t nvp_rdev; -{ - struct vnode *ovp; - struct vop_vector *ops; - struct cdev *dev; - - if (nvp->v_type == VBLK) - return (nvp); - if (nvp->v_type != VCHR) - panic("addaliasu on non-special vnode"); - dev = findcdev(nvp_rdev); - if (dev == NULL) - return (nvp); - /* - * Check to see if we have a bdevvp vnode with no associated - * filesystem. If so, we want to associate the filesystem of - * the new newly instigated vnode with the bdevvp vnode and - * discard the newly created vnode rather than leaving the - * bdevvp vnode lying around with no associated filesystem. - */ - if (vfinddev(dev, &ovp) == 0 || ovp->v_data != NULL) { - addalias(nvp, dev); - return (nvp); - } - /* - * Discard unneeded vnode, but save its node specific data. - * Note that if there is a lock, it is carried over in the - * node specific data to the replacement vnode. - */ - vref(ovp); - ovp->v_data = nvp->v_data; - ovp->v_tag = nvp->v_tag; - nvp->v_data = NULL; - lockdestroy(ovp->v_vnlock); - lockinit(ovp->v_vnlock, PVFS, nvp->v_vnlock->lk_wmesg, - nvp->v_vnlock->lk_timo, nvp->v_vnlock->lk_flags & LK_EXTFLG_MASK); - ops = ovp->v_op; - ovp->v_op = nvp->v_op; - if (VOP_ISLOCKED(nvp, curthread)) { - VOP_UNLOCK(nvp, 0, curthread); - vn_lock(ovp, LK_EXCLUSIVE | LK_RETRY, curthread); - } - nvp->v_op = ops; - delmntque(ovp); - insmntque(ovp, nvp->v_mount); - vrele(nvp); - vgone(nvp); - return (ovp); -} - -/* This is a local helper function that do the same as addaliasu, but for a - * struct cdev *instead of an dev_t. */ -static void -addalias(nvp, dev) - struct vnode *nvp; - struct cdev *dev; -{ - - KASSERT(nvp->v_type == VCHR, ("addalias on non-special vnode")); - VI_LOCK(nvp); - dev_lock(); - dev->si_refcount++; - nvp->v_rdev = dev; - SLIST_INSERT_HEAD(&dev->si_hlist, nvp, v_specnext); - dev->si_usecount += nvp->v_usecount; - dev_unlock(); - VI_UNLOCK(nvp); -} - /* * Grab a particular vnode from the free list, increment its * reference count and lock it. The vnode lock bit is set if the diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index ff15eb1de40a..121b6db1e860 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -101,11 +101,12 @@ SYSCTL_INT(_vfs_nfs, NFS_TPRINTF_DELAY, downdelayinterval, CTLFLAG_RW, &nfs_tprintf_delay, 0, ""); static int nfs_iosize(struct nfsmount *nmp); -static void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp); +static void nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp); static int mountnfs(struct nfs_args *, struct mount *, struct sockaddr *, char *, char *, struct vnode **, struct ucred *cred); -static vfs_omount_t nfs_omount; +static vfs_mount_t nfs_mount; +static vfs_cmount_t nfs_cmount; static vfs_unmount_t nfs_unmount; static vfs_root_t nfs_root; static vfs_statfs_t nfs_statfs; @@ -117,7 +118,8 @@ static vfs_sysctl_t nfs_sysctl; */ static struct vfsops nfs_vfsops = { .vfs_init = nfs_init, - .vfs_omount = nfs_omount, + .vfs_mount = nfs_mount, + .vfs_cmount = nfs_cmount, .vfs_root = nfs_root, .vfs_statfs = nfs_statfs, .vfs_sync = nfs_sync, @@ -519,13 +521,17 @@ nfs_mountdiskless(char *path, char *which, int mountflag, } static void -nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) +nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp) { int s; int adjsock; int maxio; s = splnet(); + if (vfs_getopt(mp->mnt_optnew, "ro", NULL, NULL)) + mp->mnt_flag &= ~MNT_RDONLY; + else + mp->mnt_flag |= MNT_RDONLY; /* * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes * no sense in that context. @@ -658,6 +664,8 @@ nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) } } +static const char *nfs_opts[] = { "from", "nfs_args", NULL }; + /* * VFS Operations. * @@ -669,7 +677,7 @@ nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp) */ /* ARGSUSED */ static int -nfs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) +nfs_mount(struct mount *mp, struct thread *td) { int error; struct nfs_args args; @@ -678,27 +686,21 @@ nfs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) char hst[MNAMELEN]; size_t len; u_char nfh[NFSX_V3FHMAX]; + char *path = "XXX: foo"; + + + if (vfs_filteropt(mp->mnt_optnew, nfs_opts)) + return (EINVAL); if (mp->mnt_flag & MNT_ROOTFS) return (nfs_mountroot(mp, td)); - error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); + + error = vfs_copyopt(mp->mnt_optnew, "nfs_args", &args, sizeof args); if (error) return (error); + if (args.version != NFS_ARGSVERSION) { -#ifdef COMPAT_PRELITE2 - /* - * If the argument version is unknown, then assume the - * caller is a pre-lite2 4.4BSD client and convert its - * arguments. - */ - struct onfs_args oargs; - error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args)); - if (error) - return (error); - nfs_convert_oargs(&args,&oargs); -#else /* !COMPAT_PRELITE2 */ return (EPROGMISMATCH); -#endif /* COMPAT_PRELITE2 */ } if (mp->mnt_flag & MNT_UPDATE) { struct nfsmount *nmp = VFSTONFS(mp); @@ -713,7 +715,7 @@ nfs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) ~(NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)) | (nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_NOLOCKD /*|NFSMNT_XLATECOOKIE*/)); - nfs_decode_args(nmp, &args); + nfs_decode_args(mp, nmp, &args); return (0); } @@ -746,6 +748,34 @@ nfs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) return (error); } + +/* + * VFS Operations. + * + * mount system call + * It seems a bit dumb to copyinstr() the host and path here and then + * bcopy() them in mountnfs(), but I wanted to detect errors before + * doing the sockargs() call because sockargs() allocates an mbuf and + * an error after that means that I have to release the mbuf. + */ +/* ARGSUSED */ +static int +nfs_cmount(struct mntarg *ma, void *data, int flags, struct thread *td) +{ + int error; + struct nfs_args args; + + error = copyin(data, &args, sizeof (struct nfs_args)); + if (error) + return (error); + + ma = mount_arg(ma, "nfs_args", &args, sizeof args); + + error = kernel_mount(ma, flags); + + return (error); +} + /* * Common code for mount and mountroot */ @@ -815,7 +845,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam, nmp->nm_soproto = argp->proto; nmp->nm_rpcops = &nfs_rpcops; - nfs_decode_args(nmp, argp); + nfs_decode_args(mp, nmp, argp); if (nmp->nm_sotype == SOCK_STREAM) mtx_init(&nmp->nm_nfstcpstate.mtx, "NFS/TCP state lock", diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 2ab837d1bda3..39c03a19fd8a 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -125,6 +125,7 @@ struct ostatfs { #define MMAXOPTIONLEN 65536 /* maximum length of a mount option */ TAILQ_HEAD(vnodelst, vnode); + struct vfsoptlist; struct vfsopt; @@ -144,7 +145,7 @@ struct mount { struct lock mnt_lock; /* mount structure lock */ struct mtx mnt_mtx; /* mount structure interlock */ int mnt_writeopcount; /* write syscalls in progress */ - int mnt_flag; /* flags shared with user */ + u_int mnt_flag; /* flags shared with user */ struct vfsoptlist *mnt_opt; /* current mount options */ struct vfsoptlist *mnt_optnew; /* new options passed to fs */ int mnt_kern_flag; /* kernel only flags */ @@ -264,7 +265,6 @@ struct vnode *__mnt_vnode_next(struct vnode **nvp, struct mount *mp); #define MNTK_UNMOUNTF 0x00000001 /* forced unmount in progress */ #define MNTK_UNMOUNT 0x01000000 /* unmount in progress */ #define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */ -#define MNTK_WANTRDWR 0x04000000 /* upgrade to read/write requested */ #define MNTK_SUSPEND 0x08000000 /* request write suspension */ #define MNTK_SUSPENDED 0x10000000 /* write operations are suspended */ @@ -462,8 +462,6 @@ struct sysctl_req; struct mntarg; typedef int vfs_cmount_t(struct mntarg *ma, void *data, int flags, struct thread *td); -typedef int vfs_omount_t(struct mount *mp, char *path, caddr_t data, - struct thread *td); typedef int vfs_start_t(struct mount *mp, int flags, struct thread *td); typedef int vfs_unmount_t(struct mount *mp, int mntflags, struct thread *td); typedef int vfs_root_t(struct mount *mp, struct vnode **vpp, struct thread *td); @@ -490,7 +488,6 @@ typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op, struct vfsops { vfs_mount_t *vfs_mount; - vfs_omount_t *vfs_omount; vfs_cmount_t *vfs_cmount; vfs_start_t *vfs_start; vfs_unmount_t *vfs_unmount; @@ -511,8 +508,6 @@ struct vfsops { vfs_statfs_t __vfs_statfs; #define VFS_MOUNT(MP, P) (*(MP)->mnt_op->vfs_mount)(MP, P) -#define VFS_OMOUNT(MP, PATH, DATA, P) \ - (*(MP)->mnt_op->vfs_omount)(MP, PATH, DATA, P) #define VFS_START(MP, FLAGS, P) (*(MP)->mnt_op->vfs_start)(MP, FLAGS, P) #define VFS_UNMOUNT(MP, FORCE, P) (*(MP)->mnt_op->vfs_unmount)(MP, FORCE, P) #define VFS_ROOT(MP, VPP, P) (*(MP)->mnt_op->vfs_root)(MP, VPP, P) @@ -559,13 +554,14 @@ extern char *mountrootfsname; /* * exported vnode operations */ + int dounmount(struct mount *, int, struct thread *); void free_mntarg(struct mntarg *ma); -struct mntarg *mount_argb(struct mntarg *ma, int flag, const char *name); int kernel_mount(struct mntarg *ma, int flags); int kernel_vmount(int flags, ...); struct mntarg *mount_arg(struct mntarg *ma, const char *name, const void *val, int len); +struct mntarg *mount_argb(struct mntarg *ma, int flag, const char *name); struct mntarg *mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...); struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, int len); struct vfsconf *vfs_byname(const char *); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index a3307f07874a..36a841669d92 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -62,7 +62,6 @@ extern struct cv selwait; /* select conditional variable */ extern long physmem; /* physical memory */ -extern struct cdev *rootdev; /* root device */ extern char *rootdevnames[2]; /* names of possible root devices */ extern int boothowto; /* reboot flags, from console subsystem */ @@ -298,6 +297,7 @@ void wakeup_one(void *chan) __nonnull(1); * Common `struct cdev *' stuff are declared here to avoid #include poisoning */ +struct cdev; int major(struct cdev *x); int minor(struct cdev *x); dev_t dev2udev(struct cdev *x); diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index 394dd9bd4f30..ff2a8a0a8e99 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -564,8 +564,6 @@ extern int (*lease_check_hook)(struct vop_lease_args *); extern int (*softdep_fsync_hook)(struct vnode *); extern int (*softdep_process_worklist_hook)(struct mount *); -struct vnode *addaliasu(struct vnode *vp, dev_t nvp_rdev); -int bdevvp(struct cdev *dev, struct vnode **vpp); /* cache_* may belong in namei.h. */ void cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 341179f825e0..7b9f4d542f0c 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -81,13 +81,15 @@ static void ffs_ifree(struct ufsmount *ump, struct inode *ip); static vfs_init_t ffs_init; static vfs_uninit_t ffs_uninit; static vfs_extattrctl_t ffs_extattrctl; -static vfs_omount_t ffs_omount; +static vfs_cmount_t ffs_cmount; +static vfs_mount_t ffs_mount; static struct vfsops ufs_vfsops = { .vfs_extattrctl = ffs_extattrctl, .vfs_fhtovp = ffs_fhtovp, .vfs_init = ffs_init, - .vfs_omount = ffs_omount, + .vfs_mount = ffs_mount, + .vfs_cmount = ffs_cmount, .vfs_quotactl = ufs_quotactl, .vfs_root = ufs_root, .vfs_statfs = ffs_statfs, @@ -108,55 +110,23 @@ static struct buf_ops ffs_ops = { .bop_strategy = ffs_geom_strategy, }; -/* - * ffs_omount - * - * Called when mounting local physical media - * - * PARAMETERS: - * mountroot - * mp mount point structure - * path path to mount point - * 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. - * p process (user credentials check) - * - * RETURNS: 0 Success - * !0 error number (errno.h) - * - * LOCK STATE: - * - * ENTRY - * mount point is locked - * 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. - */ +static const char *ffs_opts[] = { "from", "export", NULL }; + static int -ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) +ffs_mount(struct mount *mp, struct thread *td) { - size_t size; - struct vnode *devvp, *rootvp; - struct ufs_args args; + struct vnode *devvp; struct ufsmount *ump = 0; struct fs *fs; int error, flags; mode_t accessmode; struct nameidata ndp; + struct export_args *export; + char *fspec; + int len; + if (vfs_filteropt(mp->mnt_optnew, ffs_opts)) + return (EINVAL); if (uma_inode == NULL) { uma_inode = uma_zcreate("FFS inode", sizeof(struct inode), NULL, NULL, NULL, NULL, @@ -168,27 +138,10 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) sizeof(struct ufs2_dinode), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); } - if ((mp->mnt_flag & MNT_ROOTFS) && mp->mnt_data == NULL) { - if ((error = bdevvp(rootdev, &rootvp))) { - printf("ffs_mountroot: can't find rootvp\n"); - return (error); - } - if ((error = ffs_mountfs(rootvp, mp, td)) != 0) - return (error); - return (0); - } - - /* - * Get mount options, if any. - */ - if (data != NULL) { - error = copyin(data, (caddr_t)&args, sizeof args); - if (error) - return (error); - } else { - memset(&args, 0, sizeof args); - } + fspec = vfs_getopts(mp->mnt_optnew, "from", &error); + if (error) + return (error); /* * If updating, check whether changing from read-only to @@ -198,7 +151,8 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) ump = VFSTOUFS(mp); fs = ump->um_fs; devvp = ump->um_devvp; - if (fs->fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { + if (fs->fs_ronly == 0 && + vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) return (error); /* @@ -234,7 +188,6 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) fs->fs_pendingblocks = 0; fs->fs_pendinginodes = 0; } - fs->fs_ronly = 1; if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) fs->fs_clean = 1; if ((error = ffs_sbupdate(ump, MNT_WAIT)) != 0) { @@ -249,11 +202,14 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) g_access(ump->um_cp, 0, -1, 0); g_topology_unlock(); PICKUP_GIANT(); + fs->fs_ronly = 1; + mp->mnt_flag |= MNT_RDONLY; } if ((mp->mnt_flag & MNT_RELOAD) && (error = ffs_reload(mp, td)) != 0) return (error); - if (fs->fs_ronly && (mp->mnt_kern_flag & MNTK_WANTRDWR)) { + if (fs->fs_ronly && + !vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0)) { /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. @@ -299,6 +255,7 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) if ((error = vn_start_write(NULL, &mp, V_WAIT)) != 0) return (error); fs->fs_ronly = 0; + mp->mnt_flag &= ~MNT_RDONLY; fs->fs_clean = 0; if ((error = ffs_sbupdate(ump, MNT_WAIT)) != 0) { vn_finished_write(mp); @@ -326,20 +283,25 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) /* * If not updating name, process export requests. */ - if (args.fspec == 0) - return (vfs_export(mp, &args.export)); + if (fspec == NULL) { + error = vfs_getopt(mp->mnt_optnew, + "export", (void **)&export, &len); + if (error || len != sizeof *export) + 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 disk device. */ - NDINIT(&ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, td); + NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td); if ((error = namei(&ndp)) != 0) return (error); NDFREE(&ndp, NDF_ONLY_PNBUF); @@ -392,14 +354,33 @@ ffs_omount(struct mount *mp, char *path, caddr_t data, struct thread *td) return (error); } } - /* - * 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); + vfs_mountedfrom(mp, fspec); return (0); } +/* + * Compatibility with old mount system call. + */ + +static int +ffs_cmount(struct mntarg *ma, void *data, int flags, struct thread *td) +{ + struct ufs_args args; + int error; + + if (data == NULL) + return (EINVAL); + error = copyin(data, &args, sizeof args); + if (error) + return (error); + + ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); + ma = mount_arg(ma, "export", &args.export, sizeof args.export); + error = kernel_mount(ma, flags); + + return (error); +} + /* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must @@ -572,7 +553,6 @@ ffs_mountfs(devvp, mp, td) int error, i, blks, size, ronly; int32_t *lp; struct ucred *cred; - size_t strsize; struct g_consumer *cp; dev = devvp->v_rdev; @@ -580,18 +560,6 @@ ffs_mountfs(devvp, mp, td) vfs_object_create(devvp, td, td->td_ucred); ronly = (mp->mnt_flag & MNT_RDONLY) != 0; -#if 0 - /* - * XXX: check filesystem permissions, they may be more strict - * XXX: than what geom enforces. - * XXX: But since we're root, they wouldn't matter, would they ? - */ - error = VOP_ACCESS(devvp, ronly ? FREAD : FREAD | FWRITE, FSCRED, td); - if (error) { - VOP_UNLOCK(devvp, 0, td); - return (error); - } -#endif DROP_GIANT(); g_topology_lock(); error = g_vfs_open(devvp, &cp, "ffs", ronly ? 0 : 1); @@ -770,11 +738,7 @@ ffs_mountfs(devvp, mp, td) /* * Set FS local "last mounted on" information (NULL pad) */ - copystr( mp->mnt_stat.f_mntonname, /* mount point*/ - fs->fs_fsmnt, /* copy area*/ - sizeof(fs->fs_fsmnt) - 1, /* max size*/ - &strsize); /* real size*/ - bzero( fs->fs_fsmnt + strsize, sizeof(fs->fs_fsmnt) - strsize); + vfs_mountedfrom(mp, fs->fs_fsmnt); if( mp->mnt_flag & MNT_ROOTFS) { /* @@ -800,7 +764,6 @@ ffs_mountfs(devvp, mp, td) /* * Initialize filesystem stat information in mount struct. */ - (void)VFS_STATFS(mp, &mp->mnt_stat, td); #ifdef UFS_EXTATTR #ifdef UFS_EXTATTR_AUTOSTART /*