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);
 }

Reply via email to