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(/).
This commit is contained in:
parent
47837a50b0
commit
20a92a18f1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=138509
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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, '-');
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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 @@ 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
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,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
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user