summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c199
-rw-r--r--sys/fs/devfs/devfs_vnops.c9
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c199
-rw-r--r--sys/kern/init_main.c29
-rw-r--r--sys/kern/vfs_init.c4
-rw-r--r--sys/kern/vfs_mount.c419
-rw-r--r--sys/kern/vfs_subr.c114
-rw-r--r--sys/nfsclient/nfs_vfsops.c72
-rw-r--r--sys/sys/mount.h12
-rw-r--r--sys/sys/systm.h2
-rw-r--r--sys/sys/vnode.h2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c151
12 files changed, 478 insertions, 734 deletions
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 63582c0..865a2e5 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);
+ struct thread *td);
/*
- * 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.
+ * VFS Operations.
*/
-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;
+cd9660_cmount(struct mntarg *ma, void *data, int flags, 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);
+ error = copyin(data, &args, sizeof args);
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);
+ 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);
}
-/*
- * 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_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 1eecbf1..8833baf 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -194,7 +194,14 @@ loop:
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 63582c0..865a2e5 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);
+ struct thread *td);
/*
- * 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.
+ * VFS Operations.
*/
-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;
+cd9660_cmount(struct mntarg *ma, void *data, int flags, 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);
+ error = copyin(data, &args, sizeof args);
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);
+ 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);
}
-/*
- * 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_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 84f6fd2..a83fbaf 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,35 +522,11 @@ 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.
*/
addr = p->p_sysent->sv_usrstack - PAGE_SIZE;
@@ -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 da365d4..8ce79d3 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 d2e823e5..5be63c9 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <sys/reboot.h>
+#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/sx.h>
#include <sys/sysctl.h>
@@ -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 @@ next:
}
/*
- * New mount API.
+ * ---------------------------------------------------------------------
+ * Mount a filesystem
*/
int
nmount(td, uap)
@@ -390,6 +394,11 @@ nmount(td, uap)
}
/*
+ * ---------------------------------------------------------------------
+ * Various utility functions
+ */
+
+/*
* Allocate and initialize the mount point struct.
*/
static int
@@ -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 @@ bail:
}
/*
+ * ---------------------------------------------------------------------
* 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,
@@ -1064,6 +1039,146 @@ dounmount(mp, flags, td)
}
/*
+ * ---------------------------------------------------------------------
+ * 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
*/
void
@@ -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)
{
@@ -1314,86 +1397,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 e083aa7..8323091 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)
{
@@ -1798,86 +1764,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
* vnode is being eliminated in vgone. The process is awakened
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index ff15eb1..121b6db 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 2ab837d..39c03a1 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 a3307f0..36a8416 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 394dd9b..ff2a8a0 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 341179f..7b9f4d5 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 <unused>
- * ndp <unused>
- * 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,15 +354,34 @@ 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
* be mounted read-only.
@@ -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
/*
OpenPOWER on IntegriCloud