Subject: netbsd32_mount: one possible solution
To: None <tech-kern@netbsd.org>
From: Quentin Garnier <cube@cubidou.net>
List: tech-kern
Date: 07/22/2005 01:12:27
--WR+jf/RUebEcofwt
Content-Type: multipart/mixed; boundary="r5lq+205vWdkqwtk"
Content-Disposition: inline


--r5lq+205vWdkqwtk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,

Currently, netbsd32_mount() is uterly broken:  the data argument of the
syscall needs a conversion for most file-systems.

However, there is the issue that the actual copyin/copyout are performed
in the file-system code rather than in sys_mount.  Therefore a fix to
that issue goes through a change of all <fs>_mount functions.

I could think of two ways of making netbsd32_mount() work:  the first,
probably cleaner, is to change the VOP_MOUNT interface and introduce a
new parameter to tell the file-system code that it is dealing with
kernel-space memory.

The other way I could find is much less intrusive, and simply burn a
MNT_* flag to do that task.  I'm attaching a proposed patch using that
method which allows netbsd32_mount() to work for mount_msdos(8).

What is lacking from that patch is a way for LKMs implementing an
unknown file-system to register conversion functions.  I don't think it
is critical to do that right now, although it'd be rather easy.

Comments?

--=20
Quentin Garnier - cube@cubidou.net - cube@NetBSD.org
"When I find the controls, I'll go where I like, I'll know where I want
to be, but maybe for now I'll stay right here on a silent sea."
KT Tunstall, Silent Sea, Eye to the Telescope, 2004.

--r5lq+205vWdkqwtk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="mount.diff"
Content-Transfer-Encoding: quoted-printable

Index: compat/netbsd32/files.netbsd32
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /rep/NetBSD-src/cvs/src/sys/compat/netbsd32/files.netbsd32,v
retrieving revision 1.17
diff -u -r1.17 files.netbsd32
--- compat/netbsd32/files.netbsd32	2004/06/17 18:29:40	1.17
+++ compat/netbsd32/files.netbsd32	2005/07/21 21:02:50
@@ -10,11 +10,12 @@
 file	compat/netbsd32/netbsd32_exec_elf32.c	compat_netbsd32 & exec_elf32
 file	compat/netbsd32/netbsd32_exec_aout.c	compat_netbsd32 & exec_aout
 file	compat/netbsd32/netbsd32_netbsd.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_execve.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_fs.c		compat_netbsd32
 file	compat/netbsd32/netbsd32_ioctl.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_ipc.c		compat_netbsd32
+file	compat/netbsd32/netbsd32_mount.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_select.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_signal.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_socket.c	compat_netbsd32
 file	compat/netbsd32/netbsd32_sysctl.c	compat_netbsd32
Index: compat/netbsd32/netbsd32_netbsd.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /rep/NetBSD-src/cvs/src/sys/compat/netbsd32/netbsd32_netbsd.c,v
retrieving revision 1.97
diff -u -r1.97 netbsd32_netbsd.c
--- compat/netbsd32/netbsd32_netbsd.c	2005/07/12 15:06:17	1.97
+++ compat/netbsd32/netbsd32_netbsd.c	2005/07/21 21:40:18
@@ -396,27 +396,6 @@
 }
=20
 int
-netbsd32_mount(l, v, retval)
-	struct lwp *l;
-	void *v;
-	register_t *retval;
-{
-	struct netbsd32_mount_args /* {
-		syscallarg(const netbsd32_charp) type;
-		syscallarg(const netbsd32_charp) path;
-		syscallarg(int) flags;
-		syscallarg(netbsd32_voidp) data;
-	} */ *uap =3D v;
-	struct sys_mount_args ua;
-
-	NETBSD32TOP_UAP(type, const char);
-	NETBSD32TOP_UAP(path, const char);
-	NETBSD32TO64_UAP(flags);
-	NETBSD32TOP_UAP(data, void);
-	return (sys_mount(l, &ua, retval));
-}
-
-int
 netbsd32_unmount(l, v, retval)
 	struct lwp *l;
 	void *v;
Index: kern/vfs_syscalls.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /rep/NetBSD-src/cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.226
diff -u -r1.226 vfs_syscalls.c
--- kern/vfs_syscalls.c	2005/07/16 22:47:18	1.226
+++ kern/vfs_syscalls.c	2005/07/21 21:02:09
@@ -131,6 +131,16 @@
 		syscallarg(int) flags;
 		syscallarg(void *) data;
 	} */ *uap =3D v;
+
+	/* Make sure we'll never do a memcpy() */
+	SCARG(uap, flags) &=3D ~MNT_SYSDATA;
+	return mount1(l, uap, retval);
+}
+
+int
+mount1(struct lwp *l, void *v, register_t *retval)
+{
+	struct sys_mount_args *uap =3D v;
 	struct proc *p =3D l->l_proc;
 	struct vnode *vp;
 	struct mount *mp;
@@ -141,11 +151,12 @@
 	struct vfsops *vfs;
=20
 	/*
-	 * if MNT_GETARGS is specified, it should be only flag.
+	 * if MNT_GETARGS is specified, it should be only flag, with the
+	 * exception of MNT_SYSDATA which is used internally by the kernel.
 	 */
=20
 	if ((SCARG(uap, flags) & MNT_GETARGS) !=3D 0 &&
-	    (SCARG(uap, flags) & ~MNT_GETARGS) !=3D 0) {
+	    (SCARG(uap, flags) & ~(MNT_GETARGS | MNT_SYSDATA)) !=3D 0) {
 		return EINVAL;
 	}
=20
@@ -340,6 +351,11 @@
 		    MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP |
 		    MNT_IGNORE | MNT_MAGICLINKS);
 	}
+	/*
+	 * Pass MNT_SYSDATA down to the file system.
+	 */
+	mp->mnt_flag |=3D SCARG(uap, flags) & MNT_SYSDATA;
+
 	/*
 	 * Mount the filesystem.
 	 */
Index: sys/mount.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /rep/NetBSD-src/cvs/src/sys/sys/mount.h,v
retrieving revision 1.129
diff -u -r1.129 mount.h
--- sys/mount.h	2005/05/29 21:19:41	1.129
+++ sys/mount.h	2005/07/21 22:07:40
@@ -371,6 +371,24 @@
 LIST_HEAD(vfs_list_head, vfsops);
 extern struct vfs_list_head vfs_list;
=20
+#define	MOUNT_COPYIN_DATA(error, flags, src, dst, size)	do {		\
+    	if ((flags) & MNT_SYSDATA) {					\
+    		memcpy((dst), (src), (size));				\
+    		error =3D 0;						\
+    	} else								\
+    		(error) =3D copyin((src), (dst), (size));			\
+    } while (0);
+
+#define	MOUNT_COPYOUT_DATA(error, flags, src, dst, size)	do {	\
+    	if ((flags) & MNT_SYSDATA) {					\
+    		memcpy((dst), (src), (size));				\
+    		error =3D 0;						\
+    	} else								\
+    		(error) =3D copyin((src), (dst), (size));			\
+    } while (0);
+
+int	mount1(struct lwp *, void *, register_t *);
+
 #else /* _KERNEL */
=20
 #include <sys/cdefs.h>
Index: sys/fstypes.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /rep/NetBSD-src/cvs/src/sys/sys/fstypes.h,v
retrieving revision 1.5
diff -u -r1.5 fstypes.h
--- sys/fstypes.h	2005/06/23 01:59:31	1.5
+++ sys/fstypes.h	2005/07/21 20:44:56
@@ -70,7 +70,6 @@
  * one of the __MNT_UNUSED flags.
  */
=20
-#define	__MNT_UNUSED4	0x00200000
 #define	__MNT_UNUSED5	0x01000000
 #define	__MNT_UNUSED6	0x02000000
=20
@@ -83,6 +82,7 @@
 #define	MNT_ASYNC	0x00000040	/* file system written asynchronously */
 #define	MNT_NOCOREDUMP	0x00008000	/* don't write core dumps to this FS */
 #define MNT_IGNORE	0x00100000	/* don't show entry in df */
+#define	MNT_SYSDATA	0x00200000	/* 'data' points to kernel space */
 #define	MNT_MAGICLINKS	0x00800000	/* interpret symlinks for magic names */
 #define MNT_NOATIME	0x04000000	/* Never update access times in fs */
 #define MNT_SYMPERM	0x20000000	/* recognize symlink permission */
Index: fs/msdosfs/msdosfs_vfsops.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /rep/NetBSD-src/cvs/src/sys/fs/msdosfs/msdosfs_vfsops.c,v
retrieving revision 1.24
diff -u -r1.24 msdosfs_vfsops.c
--- fs/msdosfs/msdosfs_vfsops.c	2005/05/29 21:00:29	1.24
+++ fs/msdosfs/msdosfs_vfsops.c	2005/07/21 23:03:12
@@ -266,9 +266,10 @@
 		args.dirmask =3D pmp->pm_dirmask;
 		args.gmtoff =3D pmp->pm_gmtoff;
 		vfs_showexport(mp, &args.export, &pmp->pm_export);
-		return copyout(&args, data, sizeof(args));
+		MOUNT_COPYOUT_DATA(error, mp->mnt_flag, &args, data, sizeof(args));
+		return error;
 	}
-	error =3D copyin(data, &args, sizeof(struct msdosfs_args));
+	MOUNT_COPYIN_DATA(error, mp->mnt_flag, data, &args, sizeof(struct msdosfs=
_args));
 	if (error)
 		return (error);
=20
--- /dev/null	Thu Jul 21 04:12:09 2005
+++ compat/netbsd32/netbsd32_mount.h	Thu Jul 21 23:06:02 2005
@@ -0,0 +1,65 @@
+/*	$NetBSD*	*/
+
+/*
+ *  Copyright (c) 2005 The NetBSD Foundation.
+ *  All rights reserved.
+ *
+ *  This code is derived from software contributed to the NetBSD Foundation
+ *   by Quentin Garnier.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. All advertising materials mentioning features or use of this softwa=
re
+ *     must display the following acknowledgement:
+ *         This product includes software developed by the NetBSD
+ *         Foundation, Inc. and its contributors.
+ *  4. Neither the name of The NetBSD Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUT=
ORS
+ *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LI=
MITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTIC=
ULAR
+ *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUT=
ORS
+ *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINE=
SS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF=
 THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _COMPAT_NETBSD32_NETBSD32_MOUNT_H_
+#define _COMPAT_NETBSD32_NETBSD32_MOUNT_H_
+
+struct netbsd32_export_args {
+	int ex_flags;
+	uid_t ex_root;
+	struct uucred ex_anon;
+	netbsd32_sockaddrp_t ex_addr;
+	int ex_addrlen;
+	netbsd32_sockaddrp_t ex_mask;
+	int ex_masklen;
+	netbsd32_charp ex_indexfile;
+};
+
+struct netbsd32_msdosfs_args {
+	netbsd32_charp fspec;
+	struct netbsd32_export_args export;
+	uid_t uid;
+	gid_t gid;
+	mode_t mask;
+	int flags;
+	int version;
+	mode_t dirmask;
+	int gmtoff;
+};
+
+#endif /* _COMPAT_NETBSD32_NETBSD32_MOUNT_H_ */
--- /dev/null	Thu Jul 21 04:12:09 2005
+++ compat/netbsd32/netbsd32_mount.c	Fri Jul 22 00:55:32 2005
@@ -0,0 +1,251 @@
+/*	$NetBSD*	*/
+
+/*
+ *  Copyright (c) 2005 The NetBSD Foundation.
+ *  All rights reserved.
+ *
+ *  This code is derived from software contributed to the NetBSD Foundation
+ *   by Quentin Garnier.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. All advertising materials mentioning features or use of this softwa=
re
+ *     must display the following acknowledgement:
+ *         This product includes software developed by the NetBSD
+ *         Foundation, Inc. and its contributors.
+ *  4. Neither the name of The NetBSD Foundation nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUT=
ORS
+ *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LI=
MITED
+ *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTIC=
ULAR
+ *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUT=
ORS
+ *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINE=
SS
+ *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF=
 THE
+ *  POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+
+#include <fs/msdosfs/bpb.h>
+#include <fs/msdosfs/msdosfsmount.h>
+
+#include <compat/netbsd32/netbsd32.h>
+#include <compat/netbsd32/netbsd32_syscall.h>
+#include <compat/netbsd32/netbsd32_syscallargs.h>
+#include <compat/netbsd32/netbsd32_conv.h>
+#include <compat/netbsd32/netbsd32_mount.h>
+
+static int	netbsd32_to_msdosfs_args(const void *userdata, void *sysdata);
+static int	netbsd32_from_msdosfs_args(const void *userdata, void *sysdata);
+
+typedef int	(*netbsd32_mount_conv_t)(const void *, void *);
+
+struct netbsd32_mountsw {
+	const char *type;
+	const size_t datasize;
+	netbsd32_mount_conv_t to_native;
+	netbsd32_mount_conv_t from_native;
+};
+
+static const struct netbsd32_mountsw netbsd32_mountsw[] =3D {
+	{ MOUNT_MSDOS,
+	  sizeof(struct msdosfs_args),
+	  netbsd32_to_msdosfs_args,
+	  netbsd32_from_msdosfs_args
+	},
+	{ NULL,
+	  0,
+	  NULL,
+	  NULL
+	}
+};
+
+static int
+netbsd32_mount_lookup(const char *type, const struct netbsd32_mountsw **mc=
onv)
+{
+	char fstypename[MFSNAMELEN];
+	int error;
+
+	error =3D copyinstr(type, fstypename, MFSNAMELEN, NULL);
+	if (error) {
+		/* XXX COMPAT_09 || COMPAT_43 */
+		return error;
+	}
+#ifdef	COMPAT_10
+	/* Accept `ufs' as an alias for `ffs'. */
+	if (!strncmp(fstypename, "ufs", MFSNAMELEN))
+		strncpy(fstypename, "ffs", MFSNAMELEN);
+#endif
+
+	for (*mconv =3D &netbsd32_mountsw[0]; (*mconv)->type !=3D NULL; (*mconv)+=
+)
+		if (!strncmp(fstypename, (*mconv)->type, MFSNAMELEN))
+			return 0;
+	return ENOENT;
+}
+
+static __inline void
+netbsd32_to_export_args(const struct netbsd32_export_args *args32,
+    struct export_args *args)
+{
+	args->ex_flags =3D args32->ex_flags;
+	args->ex_root =3D args32->ex_root;
+	args->ex_anon =3D args32->ex_anon;
+	args->ex_addr =3D NETBSD32PTR64(args32->ex_addr);
+	args->ex_addrlen =3D args32->ex_addrlen;
+	args->ex_mask =3D NETBSD32PTR64(args32->ex_mask);
+	args->ex_masklen =3D args32->ex_masklen;
+	args->ex_indexfile =3D NETBSD32PTR64(args32->ex_indexfile);
+}
+
+static  __inline void
+netbsd32_from_export_args(const struct export_args *args,
+    struct netbsd32_export_args *args32)
+{
+	args32->ex_flags =3D args->ex_flags;
+	args32->ex_root =3D args->ex_root;
+	args32->ex_anon =3D args->ex_anon;
+	args32->ex_addr =3D 0; /* XXX */
+	args32->ex_addrlen =3D args->ex_addrlen;
+	args32->ex_mask =3D 0; /* XXX */
+	args32->ex_masklen =3D args->ex_masklen;
+	args32->ex_indexfile =3D 0; /* XXX */
+}
+
+static int
+netbsd32_to_msdosfs_args(const void *userdata, void *sysdata)
+{
+	struct netbsd32_msdosfs_args args32;
+	struct msdosfs_args *args =3D sysdata;
+	int error;
+
+	error =3D copyin(userdata, &args32, sizeof(args32));
+	if (error)
+		return error;
+
+	args->fspec =3D NETBSD32PTR64(args32.fspec);
+	args->uid =3D args32.uid;
+	args->gid =3D args32.gid;
+	args->mask =3D args32.mask;
+	args->flags =3D args32.flags;
+	args->version =3D args32.version;
+	args->dirmask =3D args32.dirmask;
+	args->gmtoff =3D args32.gmtoff;
+
+	netbsd32_to_export_args(&args32.export, &args->export);
+
+	return 0;
+}
+
+static int
+netbsd32_from_msdosfs_args(const void *sysdata, void *userdata)
+{
+	struct netbsd32_msdosfs_args args32;
+	const struct msdosfs_args *args =3D sysdata;
+
+	args32.fspec =3D 0; /* set to NULL in msdosfs_vfsops.c */
+	args32.uid =3D args->uid;
+	args32.gid =3D args->gid;
+	args32.mask =3D args->mask;
+	args32.flags =3D args->flags;
+	args32.version =3D args->version;
+	args32.dirmask =3D args->dirmask;
+	args32.gmtoff =3D args->gmtoff;
+
+	netbsd32_from_export_args(&args->export, &args32.export);
+
+	return copyout(&args32, userdata, sizeof(args32));
+}
+
+int
+netbsd32_mount(struct lwp *l, void *v, register_t *retval)
+{
+	struct netbsd32_mount_args /* {
+		syscallarg(const netbsd32_charp) type;
+		syscallarg(const netbsd32_charp) path;
+		syscallarg(int) flags;
+		syscallarg(netbsd32_voidp) data;
+	} */ *uap =3D v;
+	struct sys_mount_args ua;
+	void *sysdata =3D NULL;
+	const struct netbsd32_mountsw *mconv;
+	int error;
+
+	NETBSD32TOP_UAP(type, const char);
+	NETBSD32TOP_UAP(path, const char);
+	NETBSD32TO64_UAP(flags);
+	NETBSD32TOP_UAP(data, void); /* by default */
+
+	error =3D netbsd32_mount_lookup(NETBSD32PTR64(SCARG(uap, type)), &mconv);
+	if (error !=3D 0 && error !=3D ENOENT)
+		return error;
+	if (error !=3D ENOENT) {
+		sysdata =3D malloc(mconv->datasize, M_TEMP, M_WAITOK);
+		SCARG(&ua, data) =3D sysdata;
+		SCARG(&ua, flags) |=3D MNT_SYSDATA;
+
+		if (!(SCARG(uap, flags) & MNT_GETARGS)) {
+			error =3D (*mconv->to_native)
+			    (NETBSD32PTR64(SCARG(uap, data)), sysdata);
+			if (error)
+				goto out;
+		}
+	}
+
+	error =3D mount1(l, &ua, retval);
+
+	if (!error && (SCARG(uap, flags) & (MNT_GETARGS | MNT_SYSDATA)) =3D=3D
+	    (MNT_GETARGS | MNT_SYSDATA))
+		error =3D (*mconv->from_native)(sysdata,
+		    NETBSD32PTR64(SCARG(uap, data)));
+
+out:
+	if (sysdata !=3D NULL)
+		free(sysdata, M_TEMP);
+
+	return error;
+}
+
+/*
+MOUNT_FFS	-> 0
+MOUNT_NFS	-> 0
+MOUNT_MFS	-> 0
+MOUNT_MSDOS	-> 0
+MOUNT_LFS	-> 0
+MOUNT_FDESC	-> 1
+MOUNT_PORTAL	-> 0
+MOUNT_NULL	-> 0
+MOUNT_OVERLAY	-> 0
+MOUNT_UMAP	-> 0
+MOUNT_KERNFS	-> 1
+MOUNT_PROCFS	-> 1
+MOUNT_AFS	-> ?
+MOUNT_CD9660	-> 0
+MOUNT_UNION	-> 0
+MOUNT_ADOSFS	-> 0
+MOUNT_EXT2FS	-> 0
+MOUNT_CFS	-> ?
+MOUNT_CODA	-> ?
+MOUNT_FILECORE	-> 0
+MOUNT_NTFS	-> 0
+MOUNT_SMBFS	-> 0
+MOUNT_PTYFS	-> 1
+*/

--r5lq+205vWdkqwtk--

--WR+jf/RUebEcofwt
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (NetBSD)

iQEVAwUBQuAr2tgoQloHrPnoAQJyMwgAs97lqUiR4ctyQMWCT5b/Du93y6Blc55l
hdKKLrXQp3yttDTSPkHB9EJlO4buRJL/PyYYUWDA0f4Ej/8Y3ob2BdYxGX+XkzV1
hyCcXjEp+BMVi7lGeTIfcOFCg/p0qOCxWbRJ1AzVTH/MnJ0yIvcknaZcA5q1uG08
U9GemnsnxD6Sc/XAgqwnx/rJAebAN0UYnd3BhFcFVCy1gfSDmJyVLLTchbQWOrO+
FtA6/Cbm+/JSWlTDsWTeUa5qScdYdql4FqH6nG8JR7u4/i7nM5WyLXbCy3WZA7bI
2lntNr8/nw665Egex5pF4mRH/TYo52FZSYHbZb9pyUnXL20/S8padw==
=N43R
-----END PGP SIGNATURE-----

--WR+jf/RUebEcofwt--