Hi, here is a patch I must have written after fixing the bugs in mount one or two years ago. It changes do_sys_mount() so that it only takes as argument the type of the drive instead of its associated vfsops.
It does change the behavior for the compat layers: now that the associated vfsops is retrieved via mount_get_vfsops(), the MODULE_CLASS_VFS modules are autoloaded when a compat binary wants to mount something. Curiously, it hasn't been the case so far. Tested quickly on amd64. Ok? Index: kern/vfs_syscalls.c =================================================================== RCS file: /cvsroot/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.500 diff -u -r1.500 vfs_syscalls.c --- kern/vfs_syscalls.c 24 Jul 2015 13:02:52 -0000 1.500 +++ kern/vfs_syscalls.c 21 Oct 2015 10:49:53 -0000 @@ -360,13 +360,20 @@ } static int -mount_get_vfsops(const char *fstype, struct vfsops **vfsops) +mount_get_vfsops(const char *fstype, enum uio_seg type_seg, + struct vfsops **vfsops) { char fstypename[sizeof(((struct statvfs *)NULL)->f_fstypename)]; int error; - /* Copy file-system type from userspace. */ - error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL); + if (type_seg == UIO_USERSPACE) { + /* Copy file-system type from userspace. */ + error = copyinstr(fstype, fstypename, sizeof(fstypename), NULL); + } else { + error = copystr(fstype, fstypename, sizeof(fstypename), NULL); + KASSERT(error != 0); + } + if (error) { /* * Historically, filesystem types were identified by numbers. @@ -445,26 +452,23 @@ syscallarg(size_t) data_len; } */ - return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path), + return do_sys_mount(l, SCARG(uap, type), UIO_USERSPACE, SCARG(uap, path), SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, SCARG(uap, data_len), retval); } int -do_sys_mount(struct lwp *l, struct vfsops *vfsops, const char *type, +do_sys_mount(struct lwp *l, const char *type, enum uio_seg type_seg, const char *path, int flags, void *data, enum uio_seg data_seg, size_t data_len, register_t *retval) { + struct vfsops *vfsops; struct vnode *vp; void *data_buf = data; bool vfsopsrele = false; size_t alloc_sz = 0; int error; - /* XXX: The calling convention of this routine is totally bizarre */ - if (vfsops) - vfsopsrele = true; - /* * Get vnode to be covered */ @@ -474,16 +478,14 @@ goto done; } - if (vfsops == NULL) { - if (flags & (MNT_GETARGS | MNT_UPDATE)) { - vfsops = vp->v_mount->mnt_op; - } else { - /* 'type' is userspace */ - error = mount_get_vfsops(type, &vfsops); - if (error != 0) - goto done; - vfsopsrele = true; - } + if (flags & (MNT_GETARGS | MNT_UPDATE)) { + vfsops = vp->v_mount->mnt_op; + } else { + /* 'type' is userspace */ + error = mount_get_vfsops(type, type_seg, &vfsops); + if (error != 0) + goto done; + vfsopsrele = true; } /* Index: sys/mount.h =================================================================== RCS file: /cvsroot/src/sys/sys/mount.h,v retrieving revision 1.217 diff -u -r1.217 mount.h --- sys/mount.h 6 May 2015 15:57:08 -0000 1.217 +++ sys/mount.h 21 Oct 2015 10:49:53 -0000 @@ -475,7 +475,7 @@ int mount_domount(struct lwp *, struct vnode **, struct vfsops *, const char *, int, void *, size_t *); int dounmount(struct mount *, int, struct lwp *); -int do_sys_mount(struct lwp *, struct vfsops *, const char *, const char *, +int do_sys_mount(struct lwp *, const char *, enum uio_seg, const char *, int, void *, enum uio_seg, size_t, register_t *); void vfsinit(void); void vfs_opv_init(const struct vnodeopv_desc * const *); Index: compat/common/vfs_syscalls_40.c =================================================================== RCS file: /cvsroot/src/sys/compat/common/vfs_syscalls_40.c,v retrieving revision 1.3 diff -u -r1.3 vfs_syscalls_40.c --- compat/common/vfs_syscalls_40.c 19 Jan 2011 10:21:16 -0000 1.3 +++ compat/common/vfs_syscalls_40.c 21 Oct 2015 10:49:53 -0000 @@ -81,6 +81,6 @@ } */ register_t dummy; - return do_sys_mount(l, NULL, SCARG(uap, type), SCARG(uap, path), + return do_sys_mount(l, SCARG(uap, type), UIO_USERSPACE, SCARG(uap, path), SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, 0, &dummy); } Index: compat/freebsd/freebsd_file.c =================================================================== RCS file: /cvsroot/src/sys/compat/freebsd/freebsd_file.c,v retrieving revision 1.33 diff -u -r1.33 freebsd_file.c --- compat/freebsd/freebsd_file.c 9 Nov 2014 18:30:38 -0000 1.33 +++ compat/freebsd/freebsd_file.c 21 Oct 2015 10:49:53 -0000 @@ -98,16 +98,12 @@ syscallarg(void *) data; } */ const char *type; - struct vfsops *vfsops; register_t dummy; if ((type = convert_from_freebsd_mount_type(SCARG(uap, type))) == NULL) return ENODEV; - vfsops = vfs_getopsbyname(type); - if (vfsops == NULL) - return ENODEV; - return do_sys_mount(l, vfsops, NULL, SCARG(uap, path), + return do_sys_mount(l, type, UIO_SYSSPACE, SCARG(uap, path), SCARG(uap, flags), SCARG(uap, data), UIO_USERSPACE, 0, &dummy); } Index: compat/netbsd32/netbsd32_fs.c =================================================================== RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_fs.c,v retrieving revision 1.72 diff -u -r1.72 netbsd32_fs.c --- compat/netbsd32/netbsd32_fs.c 5 Oct 2014 20:17:28 -0000 1.72 +++ compat/netbsd32/netbsd32_fs.c 21 Oct 2015 10:49:54 -0000 @@ -958,7 +958,7 @@ } else { data_seg = UIO_USERSPACE; } - error = do_sys_mount(l, NULL, type, path, flags, data, data_seg, + error = do_sys_mount(l, mtype, UIO_SYSSPACE, path, flags, data, data_seg, data_len, retval); if (error) return error; Index: compat/osf1/osf1_mount.c =================================================================== RCS file: /cvsroot/src/sys/compat/osf1/osf1_mount.c,v retrieving revision 1.52 diff -u -r1.52 osf1_mount.c --- compat/osf1/osf1_mount.c 5 Sep 2014 09:21:54 -0000 1.52 +++ compat/osf1/osf1_mount.c 21 Oct 2015 10:49:54 -0000 @@ -261,7 +261,7 @@ bsd_ma.base = osf_ma.base; bsd_ma.size = osf_ma.size; - return do_sys_mount(l, vfs_getopsbyname("mfs"), NULL, SCARG(uap, path), + return do_sys_mount(l, "mfs", UIO_SYSSPACE, SCARG(uap, path), SCARG(uap, flags), &bsd_ma, UIO_SYSSPACE, sizeof bsd_ma, &dummy); } @@ -312,6 +312,6 @@ if (bsd_na.flags & NFSMNT_RETRANS) bsd_na.retrans = osf_na.retrans; - return do_sys_mount(l, vfs_getopsbyname("nfs"), NULL, SCARG(uap, path), + return do_sys_mount(l, "nfs", UIO_SYSSPACE, SCARG(uap, path), SCARG(uap, flags), &bsd_na, UIO_SYSSPACE, sizeof bsd_na, &dummy); } Index: compat/sunos/sunos_misc.c =================================================================== RCS file: /cvsroot/src/sys/compat/sunos/sunos_misc.c,v retrieving revision 1.169 diff -u -r1.169 sunos_misc.c --- compat/sunos/sunos_misc.c 5 Sep 2014 09:21:55 -0000 1.169 +++ compat/sunos/sunos_misc.c 21 Oct 2015 10:49:54 -0000 @@ -279,7 +279,7 @@ na.retrans = sna.retrans; na.hostname = /* (char *)(u_long) */ sna.hostname; - return do_sys_mount(l, vfs_getopsbyname("nfs"), NULL, + return do_sys_mount(l, "nfs", UIO_SYSSPACE, SCARG(uap, dir), nflags, &na, UIO_SYSSPACE, sizeof na, &dummy); } @@ -287,7 +287,7 @@ if (strcmp(fsname, "4.2") == 0) strcpy(fsname, "ffs"); - return do_sys_mount(l, vfs_getopsbyname(fsname), NULL, + return do_sys_mount(l, fsname, UIO_SYSSPACE, SCARG(uap, dir), nflags, SCARG(uap, data), UIO_USERSPACE, 0, &dummy); } Index: compat/sunos32/sunos32_misc.c =================================================================== RCS file: /cvsroot/src/sys/compat/sunos32/sunos32_misc.c,v retrieving revision 1.75 diff -u -r1.75 sunos32_misc.c --- compat/sunos32/sunos32_misc.c 5 Sep 2014 09:21:55 -0000 1.75 +++ compat/sunos32/sunos32_misc.c 21 Oct 2015 10:49:54 -0000 @@ -522,7 +522,7 @@ na.retrans = sna.retrans; na.hostname = (char *)(u_long)sna.hostname; - return do_sys_mount(l, vfs_getopsbyname("nfs"), NULL, + return do_sys_mount(l, "nfs", UIO_SYSSPACE, SCARG_P32(uap, path), nflags, &na, UIO_SYSSPACE, sizeof na, &dummy); } @@ -530,7 +530,7 @@ if (strcmp(fsname, "4.2") == 0) strcpy(fsname, "ffs"); - return do_sys_mount(l, vfs_getopsbyname(fsname), NULL, + return do_sys_mount(l, fsname, UIO_SYSSPACE, SCARG_P32(uap, path), nflags, SCARG_P32(uap, data), UIO_USERSPACE, 0, &dummy); } Index: compat/ultrix/ultrix_fs.c =================================================================== RCS file: /cvsroot/src/sys/compat/ultrix/ultrix_fs.c,v retrieving revision 1.55 diff -u -r1.55 ultrix_fs.c --- compat/ultrix/ultrix_fs.c 24 Jul 2015 13:02:52 -0000 1.55 +++ compat/ultrix/ultrix_fs.c 21 Oct 2015 10:49:54 -0000 @@ -401,7 +401,7 @@ na.timeo = una.timeo; na.retrans = una.retrans; na.hostname = una.hostname; - return do_sys_mount(l, vfs_getopsbyname("nfs"), NULL, + return do_sys_mount(l, "nfs", UIO_SYSSPACE, SCARG(uap, special), nflags, &na, UIO_SYSSPACE, sizeof na, &dummy); } @@ -431,7 +431,7 @@ printf("COMPAT_ULTRIX: mount with MNT_UPDATE on %s\n", fsname); } - return do_sys_mount(l, vfs_getopsbyname("ffs"), NULL, + return do_sys_mount(l, "ffs", UIO_SYSSPACE, SCARG(uap, dir), nflags, &ua, UIO_SYSSPACE, sizeof ua, &dummy); }