Subject: port-amd64/35956: linux32 statfs
To: None <port-amd64-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: None <ef@math.uni-bonn.de>
List: netbsd-bugs
Date: 03/09/2007 10:30:00
>Number:         35956
>Category:       port-amd64
>Synopsis:       COMPAT_LINUX32 lacks statfs(2)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    port-amd64-maintainer
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Mar 09 10:30:00 +0000 2007
>Originator:     Edgar Fuß
>Release:        NetBSD 4.0_BETA2
>Organization:
Mathematisches Institut der Universität Bonn, Computerabteilung
>Environment:
System: NetBSD jade.math.uni-bonn.de 4.0_BETA2 NetBSD 4.0_BETA2 (WAP05-Server) #2: Thu Mar 8 17:14:41 CET 2007 root@weser.math.uni-bonn.de:/var/tmp/obj-4.0
beta2/sys/arch/amd64/compile/wap05serv amd64
Architecture: x86_64
Machine: amd64
>Description:
	32-Bit Linux emulation does not incorporate the statfs syscall.
	The Tivoli client (dsmc) seems to need it (or statfs64)
	I was asked on port-amd64 to send-pr this.
>How-To-Repeat:
	sys 99
>Fix:
--- sys/compat/linux32/arch/amd64/syscalls.master.orig	2006-09-13 21:55:49.000000000 +0200
+++ sys/compat/linux32/arch/amd64/syscalls.master	2007-03-08 17:03:19.000000000 +0100
@@ -191,7 +191,8 @@
 96	STD	{ int linux32_sys_getpriority(int which, int who); }
 97	STD	{ int linux32_sys_setpriority(int which, int who, int prio); }
 98	UNIMPL	profil
-99	UNIMPL	statfs
+99	STD	{ int linux32_sys_statfs(const netbsd32_charp path, \
+		    linux32_statfsp sp); }
 100	UNIMPL	fstatfs
 101	UNIMPL	ioperm
 102	STD	{ int linux32_sys_socketcall(int what, netbsd32_voidp args); }
--- sys/compat/linux32/files.linux32.orig	2006-09-13 21:55:49.000000000 +0200
+++ sys/compat/linux32/files.linux32	2007-03-08 14:57:12.000000000 +0100
@@ -11,6 +11,7 @@
 file	compat/linux32/common/linux32_exec_elf32.c compat_linux32 & exec_elf32
 file	compat/linux32/common/linux32_fcntl.c	compat_linux32
 file	compat/linux32/common/linux32_ioctl.c	compat_linux32
+file	compat/linux32/common/linux32_misc.c	compat_linux32
 file	compat/linux32/common/linux32_mman.c	compat_linux32
 file	compat/linux32/common/linux32_resource.c	compat_linux32
 file	compat/linux32/common/linux32_sched.c	compat_linux32
--- sys/compat/linux/common/linux_misc.c.orig	2006-11-16 02:32:42.000000000 +0100
+++ sys/compat/linux/common/linux_misc.c	2007-03-08 15:42:01.000000000 +0100
@@ -177,11 +177,10 @@
 #define DPRINTF(a)
 # endif
 
-/* Local linux_misc.c functions: */
-# ifndef __amd64__
-static void bsd_to_linux_statfs __P((const struct statvfs *,
+/* needed by linux32_sys_statfs */
+void bsd_to_linux_statfs __P((const struct statvfs *,
     struct linux_statfs *));
-# endif
+/* Local linux_misc.c functions: */
 static void linux_to_bsd_mmap_args __P((struct sys_mmap_args *,
     const struct linux_sys_mmap_args *));
 static int linux_mmap __P((struct lwp *, struct linux_sys_mmap_args *,
@@ -313,13 +312,12 @@
 	return 0;
 }
 
-# ifndef __amd64__
 /*
  * Convert NetBSD statvfs structure to Linux statfs structure.
  * Linux doesn't have f_flag, and we can't set f_frsize due
  * to glibc statvfs() bug (see below).
  */
-static void
+void
 bsd_to_linux_statfs(bsp, lsp)
 	const struct statvfs *bsp;
 	struct linux_statfs *lsp;
@@ -365,6 +363,7 @@
 	(void)memset(lsp->l_fspare, 0, sizeof(lsp->l_fspare));
 }
 
+# ifndef __amd64__
 /*
  * Implement the fs stat functions. Straightforward.
  */
--- sys/compat/linux32/common/linux32_types.h.orig	2006-11-16 02:32:44.000000000 +0100
+++ sys/compat/linux32/common/linux32_types.h	2007-03-08 16:59:51.000000000 +0100
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux32_types.h,v 1.3 2006/11/16 01:32:44 christos Exp $ */
+/*	$NetBSD: linux32_types.h,v  $ */
 
 /*-
  * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
@@ -42,6 +42,8 @@
 typedef netbsd32_pointer_t linux32_utsnamep;
 typedef netbsd32_pointer_t linux32_stat64p;
 typedef netbsd32_pointer_t linux32_statp;
+typedef netbsd32_pointer_t linux32_statfs64p;
+typedef netbsd32_pointer_t linux32_statfsp;
 typedef netbsd32_pointer_t linux32_sigactionp_t;
 typedef netbsd32_pointer_t linux32_sigsetp_t;
 typedef netbsd32_pointer_t linux32___sysctlp_t;
--- /dev/null	2007-03-08 17:45:23.000000000 +0100
+++ sys/compat/linux32/common/linux32_misc.c	2007-03-08 17:47:22.000000000 +0100
@@ -0,0 +1,144 @@
+/*	$NetBSD: linux32_misc.c,v $	*/
+
+/*-
+ * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank van der Linden and Eric Haszlakiewicz; by Jason R. Thorpe
+ * of the Numerical Aerospace Simulation Facility, NASA Ames Research Center;
+ * by Edgar Fu\ss, Mathematisches Institut der Uni Bonn.
+ *
+ * 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 software
+ *    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 CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * 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 BUSINESS
+ * 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: linux32_misc.c,v $");
+
+#if defined(_KERNEL_OPT)
+#include "opt_ptrace.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/dirent.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/filedesc.h>
+#include <sys/ioctl.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/mman.h>
+#include <sys/mount.h>
+#include <sys/vnode.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <sys/utsname.h>
+#include <sys/unistd.h>
+
+#include <sys/sa.h>
+#include <sys/syscall.h>
+#include <sys/syscallargs.h>
+
+#include <compat/netbsd32/netbsd32.h>
+#include <compat/netbsd32/netbsd32_conv.h>
+#include <compat/netbsd32/netbsd32_syscallargs.h>
+
+#include <compat/linux32/common/linux32_machdep.h>
+#include <compat/linux32/common/linux32_types.h>
+#include <compat/linux32/common/linux32_signal.h>
+#include <compat/linux32/common/linux32_sysctl.h>
+#include <compat/linux32/linux32_syscallargs.h>
+
+#include <compat/linux/common/linux_machdep.h>
+#include <compat/linux/common/linux_types.h>
+#include <compat/linux/common/linux_util.h>
+#include <compat/linux/common/linux_misc.h>
+#include <compat/linux/common/linux_emuldata.h>
+#include <compat/linux/linux_syscallargs.h>
+
+
+extern const struct linux_mnttypes linux_fstypes[];
+extern const int linux_fstypes_cnt;
+
+# ifdef DEBUG_LINUX
+#define DPRINTF(a)	uprintf a
+# else
+#define DPRINTF(a)
+# endif
+
+void bsd_to_linux_statfs __P((const struct statvfs *,
+    struct linux_statfs *));
+
+/*
+ * Implement the fs stat functions. Straightforward.
+ */
+int
+linux32_sys_statfs(l, v, retval)
+	struct lwp *l;
+	void *v;
+	register_t *retval;
+{
+	struct linux32_sys_statfs_args /* {
+		syscallarg(const netbsd32_charp char) path;
+		syscallarg(struct linux_statfs *) sp;
+	} */ *uap = v;
+	struct proc *p = l->l_proc;
+	struct statvfs *btmp, *bsp;
+	struct linux_statfs ltmp;
+	struct sys_statvfs1_args bsa;
+	caddr_t sg;
+	int error;
+
+	sg = stackgap_init(p, 0);
+	bsp = stackgap_alloc(p, &sg, sizeof (struct statvfs));
+
+	NETBSD32TOP(uap, &bsa, path, const char);
+	CHECK_ALT_EXIST(l, &sg, SCARG(&bsa, path));
+
+	SCARG(&bsa, buf) = bsp;
+	SCARG(&bsa, flags) = ST_WAIT;
+
+	if ((error = sys_statvfs1(l, &bsa, retval)))
+		return error;
+
+	btmp = STATVFSBUF_GET();
+	error = copyin(bsp, btmp, sizeof(*btmp));
+	if (error) {
+		goto out;
+	}
+	bsd_to_linux_statfs(btmp, &ltmp);
+	error = copyout(&ltmp, NETBSD32PTR64(SCARG(uap, sp)), sizeof ltmp);
+out:
+	STATVFSBUF_PUT(btmp);
+	return error;
+}