For more than a decade I have pointed out vfs_shutdown does a terrible
job, but noone took the bait to fix it. It uses proc0, does spl0, and
a loop which makes it clear the operation may fail... and we've see
evidence the loop fails. It really cannot gaurantee the filesystem is
clean.
bluhm recently pointed out a problem where the failure could cause
entry into ddb (long story removed), so I rolled up my sleeves.
kettenis suggested rather than unmounting filesystems we could try
downgrading them to read-only. That exposed a deep-down copyin in
each filesystem's VOP handling function for mounts, vfs_init
infrastructure needed to some love.
After all that work, it turns out writeable vnodes on a readonly
filesystem can cause the change to readonly to fail, so we need to
invalidate such vnodes with a hammer.
This seems to be working. I'd like to know of anyone sees failures,
otherwise in few days I'll test this in snapshots. (Besides building
a new kernel, you want to make includes, build a new sysctl binary,
and install that).
Index: sys/ddb/db_command.c
===================================================================
RCS file: /cvs/src/sys/ddb/db_command.c,v
retrieving revision 1.80
diff -u -p -u -r1.80 db_command.c
--- sys/ddb/db_command.c 27 Nov 2017 09:23:44 -0000 1.80
+++ sys/ddb/db_command.c 29 Nov 2017 18:36:03 -0000
@@ -770,39 +770,48 @@ db_fncall(db_expr_t addr, int have_addr,
}
void
+db_reboot(int howto)
+{
+ spl0();
+ if (!curproc)
+ curproc = &proc0;
+ reboot(howto);
+}
+
+void
db_boot_sync_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif)
{
- reboot(RB_AUTOBOOT | RB_TIMEBAD | RB_USERREQ);
+ db_reboot(RB_AUTOBOOT | RB_TIMEBAD | RB_USERREQ);
}
void
db_boot_crash_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif)
{
- reboot(RB_NOSYNC | RB_DUMP | RB_TIMEBAD | RB_USERREQ);
+ db_reboot(RB_NOSYNC | RB_DUMP | RB_TIMEBAD | RB_USERREQ);
}
void
db_boot_dump_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif)
{
- reboot(RB_DUMP | RB_TIMEBAD | RB_USERREQ);
+ db_reboot(RB_DUMP | RB_TIMEBAD | RB_USERREQ);
}
void
db_boot_halt_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif)
{
- reboot(RB_NOSYNC | RB_HALT | RB_TIMEBAD | RB_USERREQ);
+ db_reboot(RB_NOSYNC | RB_HALT | RB_TIMEBAD | RB_USERREQ);
}
void
db_boot_reboot_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif)
{
- reboot(RB_AUTOBOOT | RB_NOSYNC | RB_TIMEBAD | RB_USERREQ);
+ db_reboot(RB_AUTOBOOT | RB_NOSYNC | RB_TIMEBAD | RB_USERREQ);
}
void
db_boot_poweroff_cmd(db_expr_t addr, int haddr, db_expr_t count, char *modif)
{
- reboot(RB_NOSYNC | RB_HALT | RB_POWERDOWN | RB_TIMEBAD | RB_USERREQ);
+ db_reboot(RB_NOSYNC | RB_HALT | RB_POWERDOWN | RB_TIMEBAD | RB_USERREQ);
}
void
Index: sys/isofs/cd9660/cd9660_vfsops.c
===================================================================
RCS file: /cvs/src/sys/isofs/cd9660/cd9660_vfsops.c,v
retrieving revision 1.84
diff -u -p -u -r1.84 cd9660_vfsops.c
--- sys/isofs/cd9660/cd9660_vfsops.c 20 Apr 2017 14:13:00 -0000 1.84
+++ sys/isofs/cd9660/cd9660_vfsops.c 29 Nov 2017 15:55:34 -0000
@@ -135,7 +135,7 @@ cd9660_mount(mp, path, data, ndp, p)
struct proc *p;
{
struct iso_mnt *imp = NULL;
- struct iso_args args;
+ struct iso_args *args = data;
struct vnode *devvp;
char fspec[MNAMELEN];
int error;
@@ -143,26 +143,23 @@ cd9660_mount(mp, path, data, ndp, p)
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EROFS);
- error = copyin(data, &args, sizeof(struct iso_args));
- if (error)
- return (error);
-
/*
* 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 == NULL)
+ if (args && args->fspec == NULL)
return (vfs_export(mp, &imp->im_export,
- &args.export_info));
+ &args->export_info));
+ return (0);
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
- error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
return (error);
NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p);
@@ -180,7 +177,7 @@ cd9660_mount(mp, path, data, ndp, p)
}
if ((mp->mnt_flag & MNT_UPDATE) == 0)
- error = iso_mountfs(devvp, mp, p, &args);
+ error = iso_mountfs(devvp, mp, p, args);
else {
if (devvp != imp->im_devvp)
error = EINVAL; /* needs translation */
@@ -198,7 +195,7 @@ cd9660_mount(mp, path, data, ndp, p)
strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
- bcopy(&args, &mp->mnt_stat.mount_info.iso_args, sizeof(args));
+ bcopy(args, &mp->mnt_stat.mount_info.iso_args, sizeof(*args));
cd9660_statfs(mp, &mp->mnt_stat, p);
Index: sys/isofs/udf/udf_vfsops.c
===================================================================
RCS file: /cvs/src/sys/isofs/udf/udf_vfsops.c,v
retrieving revision 1.60
diff -u -p -u -r1.60 udf_vfsops.c
--- sys/isofs/udf/udf_vfsops.c 8 Sep 2017 05:36:53 -0000 1.60
+++ sys/isofs/udf/udf_vfsops.c 29 Nov 2017 15:55:27 -0000
@@ -122,7 +122,7 @@ udf_mount(struct mount *mp, const char *
struct nameidata *ndp, struct proc *p)
{
struct vnode *devvp; /* vnode of the mount device */
- struct udf_args args;
+ struct udf_args *args = data;
char fspec[MNAMELEN];
int error;
@@ -140,14 +140,15 @@ udf_mount(struct mount *mp, const char *
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
- error = copyin(data, &args, sizeof(struct udf_args));
- if (error)
- return (error);
-
- if (args.fspec == NULL)
- return (EINVAL);
+ /*
+ * 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) {
+ return (0);
+ }
- error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
return (error);
@@ -166,7 +167,7 @@ udf_mount(struct mount *mp, const char *
return (ENXIO);
}
- if ((error = udf_mountfs(devvp, mp, args.lastblock, p))) {
+ if ((error = udf_mountfs(devvp, mp, args->lastblock, p))) {
vrele(devvp);
return (error);
}
Index: sys/kern/vfs_init.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_init.c,v
retrieving revision 1.38
diff -u -p -u -r1.38 vfs_init.c
--- sys/kern/vfs_init.c 15 Sep 2016 02:00:16 -0000 1.38
+++ sys/kern/vfs_init.c 29 Nov 2017 16:48:30 -0000
@@ -92,43 +92,53 @@ extern const struct vfsops tmpfs_vfsops
/* Set up the filesystem operations for vnodes. */
static struct vfsconf vfsconflist[] = {
#ifdef FFS
- { &ffs_vfsops, MOUNT_FFS, 1, 0, MNT_LOCAL, NULL },
+ { &ffs_vfsops, MOUNT_FFS, 1, 0, MNT_LOCAL, NULL,
+ sizeof(struct ufs_args) },
#endif
#ifdef MFS
- { &mfs_vfsops, MOUNT_MFS, 3, 0, MNT_LOCAL, NULL },
+ { &mfs_vfsops, MOUNT_MFS, 3, 0, MNT_LOCAL, NULL,
+ sizeof(struct mfs_args) },
#endif
#ifdef EXT2FS
- { &ext2fs_vfsops, MOUNT_EXT2FS, 17, 0, MNT_LOCAL, NULL },
+ { &ext2fs_vfsops, MOUNT_EXT2FS, 17, 0, MNT_LOCAL, NULL,
+ sizeof(struct ufs_args) },
#endif
#ifdef CD9660
- { &cd9660_vfsops, MOUNT_CD9660, 14, 0, MNT_LOCAL, NULL },
+ { &cd9660_vfsops, MOUNT_CD9660, 14, 0, MNT_LOCAL, NULL,
+ sizeof(struct iso_args) },
#endif
#ifdef MSDOSFS
- { &msdosfs_vfsops, MOUNT_MSDOS, 4, 0, MNT_LOCAL, NULL },
+ { &msdosfs_vfsops, MOUNT_MSDOS, 4, 0, MNT_LOCAL, NULL,
+ sizeof(struct msdosfs_args) },
#endif
#ifdef NFSCLIENT
- { &nfs_vfsops, MOUNT_NFS, 2, 0, 0, NULL },
+ { &nfs_vfsops, MOUNT_NFS, 2, 0, 0, NULL,
+ sizeof(struct nfs_args) },
#endif
#ifdef NTFS
- { &ntfs_vfsops, MOUNT_NTFS, 6, 0, MNT_LOCAL, NULL },
+ { &ntfs_vfsops, MOUNT_NTFS, 6, 0, MNT_LOCAL, NULL,
+ sizeof(struct ntfs_args) },
#endif
#ifdef UDF
- { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, NULL },
+ { &udf_vfsops, MOUNT_UDF, 13, 0, MNT_LOCAL, NULL,
+ sizeof(struct iso_args) },
#endif
#ifdef FUSE
- { &fusefs_vfsops, MOUNT_FUSEFS, 18, 0, MNT_LOCAL, NULL },
+ { &fusefs_vfsops, MOUNT_FUSEFS, 18, 0, MNT_LOCAL, NULL,
+ sizeof(struct fusefs_args) },
#endif
#ifdef TMPFS
- { &tmpfs_vfsops, MOUNT_TMPFS, 19, 0, MNT_LOCAL, NULL },
+ { &tmpfs_vfsops, MOUNT_TMPFS, 19, 0, MNT_LOCAL, NULL,
+ sizeof(struct tmpfs_args) },
#endif
};
Index: sys/kern/vfs_subr.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.260
diff -u -p -u -r1.260 vfs_subr.c
--- sys/kern/vfs_subr.c 31 Jul 2017 16:47:03 -0000 1.260
+++ sys/kern/vfs_subr.c 30 Nov 2017 01:13:17 -0000
@@ -857,7 +857,8 @@ struct vflush_args {
};
int
-vflush_vnode(struct vnode *vp, void *arg) {
+vflush_vnode(struct vnode *vp, void *arg)
+{
struct vflush_args *va = arg;
struct proc *p = curproc;
@@ -903,6 +904,12 @@ vflush_vnode(struct vnode *vp, void *arg
return (0);
}
+ if (va->flags & WRITEDEMOTE) {
+ vp->v_op = &dead_vops;
+ vp->v_tag = VT_NON;
+ return (0);
+ }
+
#ifdef DEBUG
if (busyprt)
vprint("vflush: busy vnode", vp);
@@ -1572,37 +1579,42 @@ vaccess(enum vtype type, mode_t file_mod
return (file_mode & mask) == mask ? 0 : EACCES;
}
+int
+vfs_readonly(struct mount *mp)
+{
+ int error;
+
+ error = vfs_busy(mp, VB_READ|VB_NOWAIT);
+ if (error)
+ return (error);
+ mp->mnt_flag |= MNT_UPDATE | MNT_RDONLY;
+ error = VFS_MOUNT(mp, mp->mnt_stat.f_mntonname, NULL, NULL, curproc);
+ if (error) {
+ printf("%s: failed to remount rdonly, error %d\n",
+ mp->mnt_stat.f_mntonname, error);
+ vfs_unbusy(mp);
+ return (error);
+ }
+ if (mp->mnt_syncer != NULL)
+ vgone(mp->mnt_syncer);
+ mp->mnt_syncer = NULL;
+ vfs_unbusy(mp);
+ return (error);
+}
+
/*
- * Unmount all file systems.
+ * Read-only all file systems.
* We traverse the list in reverse order under the assumption that doing so
* will avoid needing to worry about dependencies.
*/
void
-vfs_unmountall(void)
+vfs_rofs(void)
{
struct mount *mp, *nmp;
- int allerror, error, again = 1;
- retry:
- allerror = 0;
TAILQ_FOREACH_REVERSE_SAFE(mp, &mountlist, mntlist, mnt_list, nmp) {
- if (vfs_busy(mp, VB_WRITE|VB_NOWAIT))
- continue;
/* XXX Here is a race, the next pointer is not locked. */
- if ((error = dounmount(mp, MNT_FORCE, curproc)) != 0) {
- printf("unmount of %s failed with error %d\n",
- mp->mnt_stat.f_mntonname, error);
- allerror = 1;
- }
- }
-
- if (allerror) {
- printf("WARNING: some file systems would not unmount\n");
- if (again) {
- printf("retrying\n");
- again = 0;
- goto retry;
- }
+ (void) vfs_readonly(mp);
}
}
@@ -1616,17 +1628,12 @@ vfs_shutdown(void)
acct_shutdown();
#endif
- /* XXX Should suspend scheduling. */
- (void) spl0();
-
printf("syncing disks... ");
if (panicstr == 0) {
- /* Sync before unmount, in case we hang on something. */
- sys_sync(&proc0, NULL, NULL);
-
- /* Unmount file systems. */
- vfs_unmountall();
+ /* Take all filesystems to read-only */
+ sys_sync(curproc, NULL, NULL);
+ vfs_rofs();
}
if (vfs_syncwait(1))
Index: sys/kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.272
diff -u -p -u -r1.272 vfs_syscalls.c
--- sys/kern/vfs_syscalls.c 15 Apr 2017 13:56:43 -0000 1.272
+++ sys/kern/vfs_syscalls.c 29 Nov 2017 17:19:59 -0000
@@ -114,6 +114,7 @@ sys_mount(struct proc *p, void *v, regis
struct nameidata nd;
struct vfsconf *vfsp;
int flags = SCARG(uap, flags);
+ void *args = NULL;
if ((error = suser(p, 0)))
return (error);
@@ -130,15 +131,24 @@ sys_mount(struct proc *p, void *v, regis
*/
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, p);
if ((error = namei(&nd)) != 0)
- return (error);
+ goto fail;
vp = nd.ni_vp;
if (flags & MNT_UPDATE) {
if ((vp->v_flag & VROOT) == 0) {
vput(vp);
- return (EINVAL);
+ error = EINVAL;
+ goto fail;
}
mp = vp->v_mount;
vfsp = mp->mnt_vfc;
+
+ args = malloc(vfsp->vfc_datasize, M_TEMP, M_WAITOK | M_ZERO);
+ error = copyin(SCARG(uap, data), args, vfsp->vfc_datasize);
+ if (error) {
+ vput(vp);
+ goto fail;
+ }
+
mntflag = mp->mnt_flag;
/*
* We only allow the filesystem to be reloaded if it
@@ -147,12 +157,13 @@ sys_mount(struct proc *p, void *v, regis
if ((flags & MNT_RELOAD) &&
((mp->mnt_flag & MNT_RDONLY) == 0)) {
vput(vp);
- return (EOPNOTSUPP); /* Needs translation */
+ error = EOPNOTSUPP; /* Needs translation */
+ goto fail;
}
if ((error = vfs_busy(mp, VB_READ|VB_NOWAIT)) != 0) {
vput(vp);
- return (error);
+ goto fail;
}
mp->mnt_flag |= flags & (MNT_RELOAD | MNT_UPDATE);
goto update;
@@ -164,20 +175,21 @@ sys_mount(struct proc *p, void *v, regis
if ((flags & MNT_NOPERM) &&
(flags & (MNT_NODEV | MNT_NOEXEC)) != (MNT_NODEV | MNT_NOEXEC)) {
vput(vp);
- return (EPERM);
+ error = EPERM;
+ goto fail;
}
if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
vput(vp);
- return (error);
+ goto fail;
}
if (vp->v_type != VDIR) {
vput(vp);
- return (ENOTDIR);
+ goto fail;
}
error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
if (error) {
vput(vp);
- return (error);
+ goto fail;
}
for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) {
if (!strcmp(vfsp->vfc_name, fstypename))
@@ -186,12 +198,21 @@ sys_mount(struct proc *p, void *v, regis
if (vfsp == NULL) {
vput(vp);
- return (EOPNOTSUPP);
+ error = EOPNOTSUPP;
+ goto fail;
+ }
+
+ args = malloc(vfsp->vfc_datasize, M_TEMP, M_WAITOK | M_ZERO);
+ error = copyin(SCARG(uap, data), args, vfsp->vfc_datasize);
+ if (error) {
+ vput(vp);
+ goto fail;
}
if (vp->v_mountedhere != NULL) {
vput(vp);
- return (EBUSY);
+ error = EBUSY;
+ goto fail;
}
/*
@@ -207,6 +228,7 @@ sys_mount(struct proc *p, void *v, regis
mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
update:
+
/* Ensure that the parent mountpoint does not get unmounted. */
error = vfs_busy(vp->v_mount, VB_READ|VB_NOWAIT);
if (error) {
@@ -218,7 +240,7 @@ update:
free(mp, M_MOUNT, sizeof(*mp));
}
vput(vp);
- return (error);
+ goto fail;
}
/*
@@ -234,10 +256,11 @@ update:
mp->mnt_flag |= flags & (MNT_NOSUID | MNT_NOEXEC | MNT_WXALLOWED |
MNT_NODEV | MNT_SYNCHRONOUS | MNT_ASYNC | MNT_SOFTDEP |
MNT_NOATIME | MNT_NOPERM | MNT_FORCE);
+
/*
* Mount the filesystem.
*/
- error = VFS_MOUNT(mp, fspath, SCARG(uap, data), &nd, p);
+ error = VFS_MOUNT(mp, fspath, args, &nd, p);
if (!error) {
mp->mnt_stat.f_ctime = time_second;
}
@@ -261,7 +284,7 @@ update:
}
vfs_unbusy(mp);
- return (error);
+ goto fail;
}
vp->v_mountedhere = mp;
@@ -289,6 +312,9 @@ update:
vfs_unbusy(vp->v_mount);
vput(vp);
}
+fail:
+ if (args)
+ free(args, M_TEMP, vfsp->vfc_datasize);
return (error);
}
Index: sys/miscfs/fuse/fuse_vfsops.c
===================================================================
RCS file: /cvs/src/sys/miscfs/fuse/fuse_vfsops.c,v
retrieving revision 1.29
diff -u -p -u -r1.29 fuse_vfsops.c
--- sys/miscfs/fuse/fuse_vfsops.c 20 Apr 2017 14:13:00 -0000 1.29
+++ sys/miscfs/fuse/fuse_vfsops.c 29 Nov 2017 15:56:20 -0000
@@ -74,19 +74,14 @@ fusefs_mount(struct mount *mp, const cha
{
struct fusefs_mnt *fmp;
struct fusebuf *fbuf;
- struct fusefs_args args;
+ struct fusefs_args *args = data;
struct vnode *vp;
struct file *fp;
- int error;
if (mp->mnt_flag & MNT_UPDATE)
return (EOPNOTSUPP);
- error = copyin(data, &args, sizeof(struct fusefs_args));
- if (error)
- return (error);
-
- if ((fp = fd_getfile(p->p_fd, args.fd)) == NULL)
+ if ((fp = fd_getfile(p->p_fd, args->fd)) == NULL)
return (EBADF);
if (fp->f_type != DTYPE_VNODE)
@@ -100,8 +95,8 @@ fusefs_mount(struct mount *mp, const cha
fmp->mp = mp;
fmp->sess_init = 0;
fmp->dev = vp->v_rdev;
- if (args.max_read > 0)
- fmp->max_read = MIN(args.max_read, FUSEBUFMAXSIZE);
+ if (args->max_read > 0)
+ fmp->max_read = MIN(args->max_read, FUSEBUFMAXSIZE);
else
fmp->max_read = FUSEBUFMAXSIZE;
Index: sys/msdosfs/msdosfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.84
diff -u -p -u -r1.84 msdosfs_vfsops.c
--- sys/msdosfs/msdosfs_vfsops.c 29 May 2017 14:07:16 -0000 1.84
+++ sys/msdosfs/msdosfs_vfsops.c 29 Nov 2017 16:05:20 -0000
@@ -101,17 +101,13 @@ msdosfs_mount(struct mount *mp, const ch
struct nameidata *ndp, struct proc *p)
{
struct vnode *devvp; /* vnode for blk device to mount */
- struct msdosfs_args args; /* will hold data from mount request */
+ struct msdosfs_args *args = data; /* will hold data from mount request
*/
/* msdosfs specific mount control block */
struct msdosfsmount *pmp = NULL;
char fname[MNAMELEN];
char fspec[MNAMELEN];
int error, flags;
- error = copyin(data, &args, sizeof(struct msdosfs_args));
- if (error)
- return (error);
-
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
@@ -147,11 +143,11 @@ msdosfs_mount(struct mount *mp, const ch
(mp->mnt_flag & MNT_WANTRDWR))
pmp->pm_flags &= ~MSDOSFSMNT_RONLY;
- if (args.fspec == NULL) {
+ if (args && args->fspec == NULL) {
#ifdef __notyet__ /* doesn't work correctly with current mountd
XXX */
- if (args.flags & MSDOSFSMNT_MNTOPT) {
+ if (args->flags & MSDOSFSMNT_MNTOPT) {
pmp->pm_flags &= ~MSDOSFSMNT_MNTOPT;
- pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;
+ pmp->pm_flags |= args->flags &
MSDOSFSMNT_MNTOPT;
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
}
@@ -160,15 +156,17 @@ msdosfs_mount(struct mount *mp, const ch
* Process export requests.
*/
return (vfs_export(mp, &pmp->pm_export,
- &args.export_info));
+ &args->export_info));
}
+ if (args == NULL)
+ return (0);
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
- error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
goto error;
@@ -191,7 +189,7 @@ msdosfs_mount(struct mount *mp, const ch
}
if ((mp->mnt_flag & MNT_UPDATE) == 0)
- error = msdosfs_mountfs(devvp, mp, p, &args);
+ error = msdosfs_mountfs(devvp, mp, p, args);
else {
if (devvp != pmp->pm_devvp)
error = EINVAL; /* XXX needs translation */
@@ -202,10 +200,10 @@ msdosfs_mount(struct mount *mp, const ch
goto error_devvp;
pmp = VFSTOMSDOSFS(mp);
- pmp->pm_gid = args.gid;
- pmp->pm_uid = args.uid;
- pmp->pm_mask = args.mask;
- pmp->pm_flags |= args.flags & MSDOSFSMNT_MNTOPT;
+ pmp->pm_gid = args->gid;
+ pmp->pm_uid = args->uid;
+ pmp->pm_mask = args->mask;
+ pmp->pm_flags |= args->flags & MSDOSFSMNT_MNTOPT;
if (pmp->pm_flags & MSDOSFSMNT_NOWIN95)
pmp->pm_flags |= MSDOSFSMNT_SHORTNAME;
@@ -241,7 +239,7 @@ msdosfs_mount(struct mount *mp, const ch
strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
- bcopy(&args, &mp->mnt_stat.mount_info.msdosfs_args, sizeof(args));
+ bcopy(args, &mp->mnt_stat.mount_info.msdosfs_args, sizeof(*args));
#ifdef MSDOSFS_DEBUG
printf("msdosfs_mount(): mp %p, pmp %p, inusemap %p\n", mp,
Index: sys/nfs/nfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.114
diff -u -p -u -r1.114 nfs_vfsops.c
--- sys/nfs/nfs_vfsops.c 17 May 2017 08:59:05 -0000 1.114
+++ sys/nfs/nfs_vfsops.c 29 Nov 2017 16:52:08 -0000
@@ -554,27 +554,14 @@ nfs_mount(struct mount *mp, const char *
struct nameidata *ndp, struct proc *p)
{
int error;
- struct nfs_args args;
+ struct nfs_args *args = data;
struct mbuf *nam;
char hst[MNAMELEN];
size_t len;
u_char nfh[NFSX_V3FHMAX];
- error = copyin(data, &args, sizeof(args.version));
- if (error)
- return (error);
- if (args.version == 3) {
- error = copyin(data, &args, sizeof(struct nfs_args3));
- args.flags &= ~(NFSMNT_INTERNAL|NFSMNT_NOAC);
- } else if (args.version == NFS_ARGSVERSION) {
- error = copyin(data, &args, sizeof(struct nfs_args));
- args.flags &= ~NFSMNT_NOAC; /* XXX - compatibility */
- } else
- return (EPROGMISMATCH);
- if (error)
- return (error);
-
- if ((args.flags & (NFSMNT_NFSV3|NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS)
+ if (args &&
+ (args->flags & (NFSMNT_NFSV3|NFSMNT_RDIRPLUS)) == NFSMNT_RDIRPLUS)
return (EINVAL);
if (nfs_niothreads < 0) {
@@ -591,26 +578,28 @@ nfs_mount(struct mount *mp, const char *
* When doing an update, we can't change from or to
* v3.
*/
- args.flags = (args.flags & ~(NFSMNT_NFSV3)) |
- (nmp->nm_flag & (NFSMNT_NFSV3));
- nfs_decode_args(nmp, &args, &mp->mnt_stat.mount_info.nfs_args);
+ if (args) {
+ args->flags = (args->flags & ~(NFSMNT_NFSV3)) |
+ (nmp->nm_flag & (NFSMNT_NFSV3));
+ nfs_decode_args(nmp, args,
&mp->mnt_stat.mount_info.nfs_args);
+ }
return (0);
}
- if (args.fhsize < 0 || args.fhsize > NFSX_V3FHMAX)
+ if (args->fhsize < 0 || args->fhsize > NFSX_V3FHMAX)
return (EINVAL);
- error = copyin(args.fh, nfh, args.fhsize);
+ error = copyin(args->fh, nfh, args->fhsize);
if (error)
return (error);
- error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
+ error = copyinstr(args->hostname, hst, MNAMELEN-1, &len);
if (error)
return (error);
memset(&hst[len], 0, MNAMELEN - len);
/* sockargs() call must be after above copyin() calls */
- error = sockargs(&nam, args.addr, args.addrlen, MT_SONAME);
+ error = sockargs(&nam, args->addr, args->addrlen, MT_SONAME);
if (error)
return (error);
- args.fh = nfh;
- error = mountnfs(&args, mp, nam, path, hst);
+ args->fh = nfh;
+ error = mountnfs(args, mp, nam, path, hst);
return (error);
}
Index: sys/ntfs/ntfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ntfs/ntfs_vfsops.c,v
retrieving revision 1.56
diff -u -p -u -r1.56 ntfs_vfsops.c
--- sys/ntfs/ntfs_vfsops.c 20 Mar 2017 16:44:03 -0000 1.56
+++ sys/ntfs/ntfs_vfsops.c 29 Nov 2017 16:06:07 -0000
@@ -119,7 +119,7 @@ ntfs_mount(struct mount *mp, const char
{
int err = 0;
struct vnode *devvp;
- struct ntfs_args args;
+ struct ntfs_args *args = data;
char fname[MNAMELEN];
char fspec[MNAMELEN];
@@ -131,24 +131,19 @@ ntfs_mount(struct mount *mp, const char
***
*/
- /* copy in user arguments*/
- err = copyin(data, (caddr_t)&args, sizeof (struct ntfs_args));
- if (err)
- goto error_1; /* can't get arguments*/
-
/*
* 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) {
/* if not updating name...*/
- if (args.fspec == NULL) {
+ if (args && args->fspec == NULL) {
/*
* Process export requests. Jumping to "success"
* will return the vfs_export() error code.
*/
struct ntfsmount *ntm = VFSTONTFS(mp);
- err = vfs_export(mp, &ntm->ntm_export,
&args.export_info);
+ err = vfs_export(mp, &ntm->ntm_export,
&args->export_info);
goto success;
}
@@ -161,7 +156,7 @@ ntfs_mount(struct mount *mp, const char
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
- err = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ err = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (err)
goto error_1;
@@ -203,7 +198,7 @@ ntfs_mount(struct mount *mp, const char
* Update device name only on success
*/
if( !err) {
- err = set_statfs_info(NULL, UIO_USERSPACE, args.fspec,
+ err = set_statfs_info(NULL, UIO_USERSPACE, args->fspec,
UIO_USERSPACE, mp, p);
}
#endif
@@ -227,9 +222,9 @@ ntfs_mount(struct mount *mp, const char
strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
- bcopy(&args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(args));
+ bcopy(args, &mp->mnt_stat.mount_info.ntfs_args, sizeof(*args));
if ( !err) {
- err = ntfs_mountfs(devvp, mp, &args, p);
+ err = ntfs_mountfs(devvp, mp, args, p);
}
}
if (err) {
Index: sys/sys/mount.h
===================================================================
RCS file: /cvs/src/sys/sys/mount.h,v
retrieving revision 1.131
diff -u -p -u -r1.131 mount.h
--- sys/sys/mount.h 6 Oct 2017 18:44:22 -0000 1.131
+++ sys/sys/mount.h 29 Nov 2017 16:50:47 -0000
@@ -131,27 +131,6 @@ struct nfs_args {
int acdirmin; /* ac for dir recently modified */
int acdirmax; /* ac for dir not recently modified */
};
-/* NFS args version 3 (for backwards compatibility) */
-struct nfs_args3 {
- int version; /* args structure version number */
- struct sockaddr *addr; /* file server address */
- int addrlen; /* length of address */
- int sotype; /* Socket type */
- int proto; /* and Protocol */
- u_char *fh; /* File handle to be mounted */
- int fhsize; /* Size, in bytes, of fh */
- int flags; /* flags */
- int wsize; /* write size in bytes */
- int rsize; /* read size in bytes */
- int readdirsize; /* readdir size in bytes */
- int timeo; /* initial timeout in .1 secs */
- int retrans; /* times to retry send */
- int maxgrouplist; /* Max. size of group list */
- int readahead; /* # of blocks to readahead */
- int leaseterm; /* Term (sec) of lease */
- int deadthresh; /* Retrans threshold */
- char *hostname; /* server's name */
-};
/*
* NFS mount option flags
@@ -468,6 +447,7 @@ struct vfsconf {
int vfc_refcount; /* number mounted of this type */
int vfc_flags; /* permanent flags */
struct vfsconf *vfc_next; /* next in list */
+ size_t vfc_datasize; /* size of data args */
};
/* buffer cache statistics */
@@ -592,7 +572,6 @@ struct mount *vfs_getvfs(fsid_t *);
int vfs_mountedon(struct vnode *);
int vfs_rootmountalloc(char *, char *, struct mount **);
void vfs_unbusy(struct mount *);
-void vfs_unmountall(void);
extern TAILQ_HEAD(mntlist, mount) mountlist;
struct mount *getvfs(fsid_t *); /* return vfs given fsid */
Index: sys/sys/vnode.h
===================================================================
RCS file: /cvs/src/sys/sys/vnode.h,v
retrieving revision 1.140
diff -u -p -u -r1.140 vnode.h
--- sys/sys/vnode.h 13 Aug 2017 22:02:22 -0000 1.140
+++ sys/sys/vnode.h 30 Nov 2017 01:02:24 -0000
@@ -227,6 +227,7 @@ extern int vttoif_tab[];
#define FORCECLOSE 0x0002 /* vflush: force file closeure
*/
#define WRITECLOSE 0x0004 /* vflush: only close writeable
files */
#define DOCLOSE 0x0008 /* vclean: close active files */
+#define WRITEDEMOTE 0x0010 /* vflush: ok if some writes remain */
#define V_SAVE 0x0001 /* vinvalbuf: sync file first */
#define V_SAVEMETA 0x0002 /* vinvalbuf: leave indirect
blocks */
Index: sys/tmpfs/tmpfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/tmpfs/tmpfs_vfsops.c,v
retrieving revision 1.13
diff -u -p -u -r1.13 tmpfs_vfsops.c
--- sys/tmpfs/tmpfs_vfsops.c 8 Sep 2017 05:36:53 -0000 1.13
+++ sys/tmpfs/tmpfs_vfsops.c 29 Nov 2017 15:51:08 -0000
@@ -84,7 +84,7 @@ int
tmpfs_mount(struct mount *mp, const char *path, void *data,
struct nameidata *ndp, struct proc *p)
{
- struct tmpfs_args args;
+ struct tmpfs_args *args = data;
tmpfs_mount_t *tmp;
tmpfs_node_t *root;
uint64_t memlimit;
@@ -121,25 +121,25 @@ tmpfs_mount(struct mount *mp, const char
if (tmpfs_mem_info(1) < TMPFS_PAGES_RESERVED)
return EINVAL;
- error = copyin(data, &args, sizeof(struct tmpfs_args));
+ error = copyin(data, args, sizeof(struct tmpfs_args));
if (error)
return error;
- if (args.ta_root_uid == VNOVAL || args.ta_root_gid == VNOVAL ||
- args.ta_root_mode == VNOVAL)
+ if (args->ta_root_uid == VNOVAL || args->ta_root_gid == VNOVAL ||
+ args->ta_root_mode == VNOVAL)
return EINVAL;
/* Get the memory usage limit for this file-system. */
- if (args.ta_size_max < PAGE_SIZE) {
+ if (args->ta_size_max < PAGE_SIZE) {
memlimit = UINT64_MAX;
} else {
- memlimit = args.ta_size_max;
+ memlimit = args->ta_size_max;
}
KASSERT(memlimit > 0);
- if (args.ta_nodes_max <= 3) {
+ if (args->ta_nodes_max <= 3) {
nodes = 3 + (memlimit / 1024);
} else {
- nodes = args.ta_nodes_max;
+ nodes = args->ta_nodes_max;
}
nodes = MIN(nodes, INT_MAX);
KASSERT(nodes >= 3);
@@ -156,8 +156,8 @@ tmpfs_mount(struct mount *mp, const char
tmpfs_mntmem_init(tmp, memlimit);
/* Allocate the root node. */
- error = tmpfs_alloc_node(tmp, VDIR, args.ta_root_uid,
- args.ta_root_gid, args.ta_root_mode & ALLPERMS, NULL,
+ error = tmpfs_alloc_node(tmp, VDIR, args->ta_root_uid,
+ args->ta_root_gid, args->ta_root_mode & ALLPERMS, NULL,
VNOVAL, &root);
KASSERT(error == 0 && root != NULL);
@@ -180,7 +180,7 @@ tmpfs_mount(struct mount *mp, const char
#endif
vfs_getnewfsid(mp);
- mp->mnt_stat.mount_info.tmpfs_args = args;
+ mp->mnt_stat.mount_info.tmpfs_args = *args;
bzero(&mp->mnt_stat.f_mntonname, sizeof(mp->mnt_stat.f_mntonname));
bzero(&mp->mnt_stat.f_mntfromname, sizeof(mp->mnt_stat.f_mntfromname));
Index: sys/ufs/ext2fs/ext2fs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ext2fs/ext2fs_vfsops.c,v
retrieving revision 1.99
diff -u -p -u -r1.99 ext2fs_vfsops.c
--- sys/ufs/ext2fs/ext2fs_vfsops.c 30 May 2017 10:32:53 -0000 1.99
+++ sys/ufs/ext2fs/ext2fs_vfsops.c 29 Nov 2017 16:06:55 -0000
@@ -162,17 +162,13 @@ ext2fs_mount(struct mount *mp, const cha
struct nameidata *ndp, struct proc *p)
{
struct vnode *devvp;
- struct ufs_args args;
+ struct ufs_args *args = data;
struct ufsmount *ump = NULL;
struct m_ext2fs *fs;
char fname[MNAMELEN];
char fspec[MNAMELEN];
int error, flags;
- error = copyin(data, &args, sizeof(struct ufs_args));
- if (error)
- return (error);
-
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
@@ -208,19 +204,21 @@ ext2fs_mount(struct mount *mp, const cha
fs->e2fs.e2fs_state = E2FS_ERRORS;
fs->e2fs_fmod = 1;
}
- if (args.fspec == NULL) {
+ if (args && args->fspec == NULL) {
/*
* Process export requests.
*/
return (vfs_export(mp, &ump->um_export,
- &args.export_info));
+ &args->export_info));
}
+ if (args == NULL)
+ goto success;
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
- error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
goto error;
@@ -265,7 +263,7 @@ ext2fs_mount(struct mount *mp, const cha
strlcpy(mp->mnt_stat.f_mntfromname, fname, MNAMELEN);
memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
- memcpy(&mp->mnt_stat.mount_info.ufs_args, &args, sizeof(args));
+ memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args));
if (fs->e2fs_fmod != 0) { /* XXX */
fs->e2fs_fmod = 0;
Index: sys/ufs/ffs/ffs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/ffs/ffs_vfsops.c,v
retrieving revision 1.166
diff -u -p -u -r1.166 ffs_vfsops.c
--- sys/ufs/ffs/ffs_vfsops.c 29 May 2017 14:07:16 -0000 1.166
+++ sys/ufs/ffs/ffs_vfsops.c 30 Nov 2017 01:01:30 -0000
@@ -206,7 +206,7 @@ ffs_mount(struct mount *mp, const char *
struct nameidata *ndp, struct proc *p)
{
struct vnode *devvp;
- struct ufs_args args;
+ struct ufs_args *args = data;
struct ufsmount *ump = NULL;
struct fs *fs;
char fname[MNAMELEN];
@@ -214,10 +214,6 @@ ffs_mount(struct mount *mp, const char *
int error = 0, flags;
int ronly;
- error = copyin(data, &args, sizeof(struct ufs_args));
- if (error)
- return (error);
-
#ifndef FFS_SOFTUPDATES
if (mp->mnt_flag & MNT_SOFTDEP) {
printf("WARNING: soft updates isn't compiled in\n");
@@ -255,6 +251,8 @@ ffs_mount(struct mount *mp, const char *
* Get rid of files open for writing.
*/
flags = WRITECLOSE;
+ if (args == NULL)
+ flags |= WRITEDEMOTE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
if (fs->fs_flags & FS_DOSOFTDEP) {
@@ -342,12 +340,14 @@ ffs_mount(struct mount *mp, const char *
ronly = 0;
}
- if (args.fspec == NULL) {
+ if (args == NULL)
+ goto success;
+ if (args->fspec == NULL) {
/*
* Process export requests.
*/
error = vfs_export(mp, &ump->um_export,
- &args.export_info);
+ &args->export_info);
if (error)
goto error_1;
else
@@ -359,7 +359,7 @@ ffs_mount(struct mount *mp, const char *
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
- error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
goto error_1;
@@ -435,7 +435,8 @@ ffs_mount(struct mount *mp, const char *
*
* This code is common to root and non-root mounts
*/
- memcpy(&mp->mnt_stat.mount_info.ufs_args, &args, sizeof(args));
+ if (args)
+ memcpy(&mp->mnt_stat.mount_info.ufs_args, args, sizeof(*args));
VFS_STATFS(mp, &mp->mnt_stat, p);
success:
Index: sys/ufs/mfs/mfs_vfsops.c
===================================================================
RCS file: /cvs/src/sys/ufs/mfs/mfs_vfsops.c,v
retrieving revision 1.54
diff -u -p -u -r1.54 mfs_vfsops.c
--- sys/ufs/mfs/mfs_vfsops.c 10 Jan 2017 19:48:32 -0000 1.54
+++ sys/ufs/mfs/mfs_vfsops.c 29 Nov 2017 16:00:27 -0000
@@ -85,17 +85,13 @@ mfs_mount(struct mount *mp, const char *
struct nameidata *ndp, struct proc *p)
{
struct vnode *devvp;
- struct mfs_args args;
+ struct mfs_args *args = data;
struct ufsmount *ump;
struct fs *fs;
struct mfsnode *mfsp;
char fspec[MNAMELEN];
int flags, error;
- error = copyin(data, &args, sizeof(struct mfs_args));
- if (error)
- return (error);
-
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
@@ -114,13 +110,13 @@ mfs_mount(struct mount *mp, const char *
if (fs->fs_ronly && (mp->mnt_flag & MNT_WANTRDWR))
fs->fs_ronly = 0;
#ifdef EXPORTMFS
- if (args.fspec == NULL)
+ if (args && args->fspec == NULL)
return (vfs_export(mp, &ump->um_export,
- &args.export_info));
+ &args->export_info));
#endif
return (0);
}
- error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
+ error = copyinstr(args->fspec, fspec, sizeof(fspec), NULL);
if (error)
return (error);
error = getnewvnode(VT_MFS, NULL, &mfs_vops, &devvp);
@@ -132,8 +128,8 @@ mfs_mount(struct mount *mp, const char *
mfs_minor++;
mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK | M_ZERO);
devvp->v_data = mfsp;
- mfsp->mfs_baseoff = args.base;
- mfsp->mfs_size = args.size;
+ mfsp->mfs_baseoff = args->base;
+ mfsp->mfs_size = args->size;
mfsp->mfs_vnode = devvp;
mfsp->mfs_tid = p->p_tid;
bufq_init(&mfsp->mfs_bufq, BUFQ_FIFO);
@@ -152,7 +148,7 @@ mfs_mount(struct mount *mp, const char *
strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
memset(mp->mnt_stat.f_mntfromspec, 0, MNAMELEN);
strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
- memcpy(&mp->mnt_stat.mount_info.mfs_args, &args, sizeof(args));
+ memcpy(&mp->mnt_stat.mount_info.mfs_args, args, sizeof(*args));
return (0);
}