Module Name:    src
Committed By:   christos
Date:           Thu Mar 15 00:48:13 UTC 2018

Modified Files:
        src/sys/compat/netbsd32: netbsd32_netbsd.c
        src/sys/sys: param.h
        src/sys/uvm: uvm_swap.c uvm_swap.h

Log Message:
Untangle the swapctl compat code mess. Welcome to lucky 13.


To generate a diff of this commit:
cvs rdiff -u -r1.214 -r1.215 src/sys/compat/netbsd32/netbsd32_netbsd.c
cvs rdiff -u -r1.557 -r1.558 src/sys/sys/param.h
cvs rdiff -u -r1.175 -r1.176 src/sys/uvm/uvm_swap.c
cvs rdiff -u -r1.22 -r1.23 src/sys/uvm/uvm_swap.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/netbsd32/netbsd32_netbsd.c
diff -u src/sys/compat/netbsd32/netbsd32_netbsd.c:1.214 src/sys/compat/netbsd32/netbsd32_netbsd.c:1.215
--- src/sys/compat/netbsd32/netbsd32_netbsd.c:1.214	Tue Jan  9 15:55:43 2018
+++ src/sys/compat/netbsd32/netbsd32_netbsd.c	Wed Mar 14 20:48:13 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_netbsd.c,v 1.214 2018/01/09 20:55:43 maya Exp $	*/
+/*	$NetBSD: netbsd32_netbsd.c,v 1.215 2018/03/15 00:48:13 christos Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001, 2008 Matthew R. Green
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.214 2018/01/09 20:55:43 maya Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.215 2018/03/15 00:48:13 christos Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ddb.h"
@@ -1718,59 +1718,23 @@ netbsd32___posix_rename(struct lwp *l, c
 	return (sys___posix_rename(l, &ua, retval));
 }
 
-static int
-netbsd32_swapctl_stats(struct lwp *l, struct sys_swapctl_args *uap, register_t *retval)
+static void
+swapent32_cvt(void *p, const struct swapent *se)
 {
-	struct swapent *ksep;
-	struct netbsd32_swapent *usep32;
-	struct netbsd32_swapent se32;
-	int count = SCARG(uap, misc);
-	int i, error = 0;
-	size_t ksep_len;
-
-	if (count < 0)
-		return EINVAL;
-
-	swapsys_lock(RW_WRITER);
-
-	if ((size_t)count > (size_t)uvmexp.nswapdev)
-		count = uvmexp.nswapdev;
-	if (count == 0) {
-		/* No swap device */
-		swapsys_unlock();
-		return 0;
-	}
-
-	ksep_len = sizeof(*ksep) * count;
-	ksep = kmem_alloc(ksep_len, KM_SLEEP);
-	usep32 = (struct netbsd32_swapent *)SCARG(uap, arg);
-
-	uvm_swap_stats(SWAP_STATS, ksep, count, retval);
-	count = *retval;
-
-	swapsys_unlock();
-
-	for (i = 0; i < count; i++) {
-		se32.se_dev = ksep[i].se_dev;
-		se32.se_flags = ksep[i].se_flags;
-		se32.se_nblks = ksep[i].se_nblks;
-		se32.se_inuse = ksep[i].se_inuse;
-		se32.se_priority = ksep[i].se_priority;
-		memcpy(se32.se_path, ksep[i].se_path,
-			sizeof(se32.se_path));
+	struct netbsd32_swapent *se32 = p;
 
-		error = copyout(&se32, usep32 + i, sizeof(se32));
-		if (error)
-			break;
-	}
-
-	kmem_free(ksep, ksep_len);
-
-	return error;
+	se32->se_dev = se->se_dev;
+	se32->se_flags = se->se_flags;
+	se32->se_nblks = se->se_nblks;
+	se32->se_inuse = se->se_inuse;
+	se32->se_priority = se->se_priority;
+	KASSERT(sizeof(se->se_path) <= sizeof(se32->se_path));
+	strcpy(se32->se_path, se->se_path);
 }
 
 int
-netbsd32_swapctl(struct lwp *l, const struct netbsd32_swapctl_args *uap, register_t *retval)
+netbsd32_swapctl(struct lwp *l, const struct netbsd32_swapctl_args *uap,
+    register_t *retval)
 {
 	/* {
 		syscallarg(int) cmd;
@@ -1784,8 +1748,13 @@ netbsd32_swapctl(struct lwp *l, const st
 	NETBSD32TO64_UAP(misc);
 
 	/* SWAP_STATS50 and SWAP_STATS13 structures need no translation */
-	if (SCARG(&ua, cmd) == SWAP_STATS)
-		return netbsd32_swapctl_stats(l, &ua, retval);
+	if (SCARG(&ua, cmd) == SWAP_STATS) {
+		swapsys_lock(RW_READER);
+		int error = uvm_swap_stats(SCARG(&ua, arg), SCARG(&ua, misc),
+		    swapent32_cvt, sizeof(struct netbsd32_swapent), retval);
+		swapsys_unlock();
+		return error;
+	}
 
 	return (sys_swapctl(l, &ua, retval));
 }

Index: src/sys/sys/param.h
diff -u src/sys/sys/param.h:1.557 src/sys/sys/param.h:1.558
--- src/sys/sys/param.h:1.557	Tue Jan  9 14:52:29 2018
+++ src/sys/sys/param.h	Wed Mar 14 20:48:13 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: param.h,v 1.557 2018/01/09 19:52:29 christos Exp $	*/
+/*	$NetBSD: param.h,v 1.558 2018/03/15 00:48:13 christos Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -67,7 +67,7 @@
  *	2.99.9		(299000900)
  */
 
-#define	__NetBSD_Version__	899001200	/* NetBSD 8.99.12 */
+#define	__NetBSD_Version__	899001300	/* NetBSD 8.99.13 */
 
 #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
     (m) * 1000000) + (p) * 100) <= __NetBSD_Version__)

Index: src/sys/uvm/uvm_swap.c
diff -u src/sys/uvm/uvm_swap.c:1.175 src/sys/uvm/uvm_swap.c:1.176
--- src/sys/uvm/uvm_swap.c:1.175	Fri Oct 27 20:37:13 2017
+++ src/sys/uvm/uvm_swap.c	Wed Mar 14 20:48:13 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_swap.c,v 1.175 2017/10/28 00:37:13 pgoyette Exp $	*/
+/*	$NetBSD: uvm_swap.c,v 1.176 2018/03/15 00:48:13 christos Exp $	*/
 
 /*
  * Copyright (c) 1995, 1996, 1997, 2009 Matthew R. Green
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.175 2017/10/28 00:37:13 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.176 2018/03/15 00:48:13 christos Exp $");
 
 #include "opt_uvmhist.h"
 #include "opt_compat_netbsd.h"
@@ -440,6 +440,85 @@ void swapsys_unlock(void)
 	rw_exit(&swap_syscall_lock);
 }
 
+#if defined(COMPAT_13)
+static void
+swapent13_cvt(void *p, const struct swapent *se)
+{
+	struct swapent13 *sep13 = p;
+
+	sep13->se13_dev = se->se_dev;
+	sep13->se13_flags = se->se_flags;
+	sep13->sse13_nblks = se->se_nblks;
+	sep13->se13_inuse = se->se_inuse;
+	sep13->se13_priority = se->se_priority;
+}
+#endif
+
+#if defined(COMPAT_50)
+static void
+swapent50_cvt(void *p, const struct swapent *se)
+{
+	struct swapent50 *sep50 = p;
+
+	sep50->se50_dev = se->se_dev;
+	sep50->se50_flags = se->se_flags;
+	sep50->se50_nblks = se->se_nblks;
+	sep50->se50_inuse = se->se_inuse;
+	sep50->se50_priority = se->se_priority;
+	KASSERT(sizeof(se->se_path) <= sizeof(sep50->se50_path));
+	strcpy(sep50->se50_path, se->se_path);
+}
+#endif
+
+static void
+swapent_cvt(struct swapent *se, const struct swapdev *sdp, int inuse)
+{
+	se->se_dev = sdp->swd_dev;
+	se->se_flags = sdp->swd_flags;
+	se->se_nblks = sdp->swd_nblks;
+	se->se_inuse = inuse;
+	se->se_priority = sdp->swd_priority;
+	KASSERT(sdp->swd_pathlen < sizeof(se->se_path));
+	strcpy(se->se_path, sdp->swd_path);
+}
+
+static size_t
+swapent_size(int cmd)
+{
+	switch (cmd) {
+#if defined(COMPAT_13)
+	case SWAP_STATS13:
+		return sizeof(struct swapent13);
+#endif
+#if defined(COMPAT_50)
+	case SWAP_STATS50:
+	    	return sizeof(struct swapent50);
+#endif
+	case SWAP_STATS:
+		return sizeof(struct swapent);
+	default:
+		return 0;
+	}
+}
+
+static void (*
+swapent_fun(int cmd))(void *, const struct swapent *)
+{
+	switch (cmd) {
+#if defined(COMPAT_13)
+	case SWAP_STATS13:
+		return swapent13_cvt;
+#endif
+#if defined(COMPAT_50)
+	case SWAP_STATS50:
+		return swapent50_cvt;
+#endif
+	case SWAP_STATS:
+	default:
+		return NULL;
+	}
+}
+
 /*
  * sys_swapctl: main entry point for swapctl(2) system call
  * 	[with two helper functions: swap_on and swap_off]
@@ -456,11 +535,10 @@ sys_swapctl(struct lwp *l, const struct 
 	struct nameidata nd;
 	struct swappri *spp;
 	struct swapdev *sdp;
-	struct swapent *sep;
 #define SWAP_PATH_MAX (PATH_MAX + 1)
 	char	*userpath;
 	size_t	len = 0;
-	int	error, misc;
+	int	error;
 	int	priority;
 	UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist);
 
@@ -478,7 +556,6 @@ sys_swapctl(struct lwp *l, const struct 
 		return 0;
 	}
 
-	misc = SCARG(uap, misc);
 	userpath = kmem_alloc(SWAP_PATH_MAX, KM_SLEEP);
 
 	/*
@@ -494,51 +571,25 @@ sys_swapctl(struct lwp *l, const struct 
 	 * to grab the uvm_swap_data_lock because we may fault&sleep during
 	 * copyout() and we don't want to be holding that lock then!
 	 */
-	if (SCARG(uap, cmd) == SWAP_STATS
+	switch (SCARG(uap, cmd)) {
+	case SWAP_STATS:
 #if defined(COMPAT_50)
-	    || SCARG(uap, cmd) == SWAP_STATS50
+	case SWAP_STATS50:
 #endif
 #if defined(COMPAT_13)
-	    || SCARG(uap, cmd) == SWAP_STATS13
-#endif
-	    ) {
-		if (misc < 0) {
-			error = EINVAL;
-			goto out;
-		}
-		if (misc == 0 || uvmexp.nswapdev == 0) {
-			error = 0;
-			goto out;
-		}
-		/* Make sure userland cannot exhaust kernel memory */
-		if ((size_t)misc > (size_t)uvmexp.nswapdev)
-			misc = uvmexp.nswapdev;
-		KASSERT(misc > 0);
-#if defined(COMPAT_13)
-		if (SCARG(uap, cmd) == SWAP_STATS13)
-			len = sizeof(struct swapent13) * misc;
-		else
-#endif
-#if defined(COMPAT_50)
-		if (SCARG(uap, cmd) == SWAP_STATS50)
-			len = sizeof(struct swapent50) * misc;
-		else
+	case SWAP_STATS13:
 #endif
-			len = sizeof(struct swapent) * misc;
-		sep = (struct swapent *)kmem_alloc(len, KM_SLEEP);
-
-		uvm_swap_stats(SCARG(uap, cmd), sep, misc, retval);
-		error = copyout(sep, SCARG(uap, arg), len);
-
-		kmem_free(sep, len);
+		error = uvm_swap_stats(SCARG(uap, arg), SCARG(uap, misc),
+		    swapent_fun(SCARG(uap, cmd)), swapent_size(SCARG(uap, cmd)),
+		    retval);
 		UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0);
 		goto out;
-	}
-	if (SCARG(uap, cmd) == SWAP_GETDUMPDEV) {
-		dev_t	*devp = (dev_t *)SCARG(uap, arg);
-
-		error = copyout(&dumpdev, devp, sizeof(dumpdev));
+	
+	case SWAP_GETDUMPDEV:
+		error = copyout(&dumpdev, SCARG(uap, arg), sizeof(dumpdev));
 		goto out;
+	default:
+		break;
 	}
 
 	/*
@@ -744,12 +795,30 @@ out:
  * is not known at build time. Hence it would not be possible to
  * ensure it would fit in the stackgap in any case.
  */
-void
-uvm_swap_stats(int cmd, struct swapent *sep, int sec, register_t *retval)
+int
+uvm_swap_stats(char *ptr, int misc, 
+    void (*f)(void *, const struct swapent *), size_t len,
+    register_t *retval)
 {
 	struct swappri *spp;
 	struct swapdev *sdp;
+	struct swapent sep;
 	int count = 0;
+	int error;
+
+	KASSERT(len <= sizeof(sep));
+	if (len == 0)
+		return ENOSYS;
+
+	if (misc < 0)
+		return EINVAL;
+
+	if (misc == 0 || uvmexp.nswapdev == 0)
+		return 0;
+
+	/* Make sure userland cannot exhaust kernel memory */
+	if ((size_t)misc > (size_t)uvmexp.nswapdev)
+		misc = uvmexp.nswapdev;
 
 	KASSERT(rw_lock_held(&swap_syscall_lock));
 
@@ -757,64 +826,23 @@ uvm_swap_stats(int cmd, struct swapent *
 		TAILQ_FOREACH(sdp, &spp->spi_swapdev, swd_next) {
 			int inuse;
 
-			if (sec-- <= 0)
+			if (misc-- <= 0)
 				break;
 
-			/*
-			 * backwards compatibility for system call.
-			 * For NetBSD 1.3 and 5.0, we have to use
-			 * the 32 bit dev_t.  For 5.0 and -current
-			 * we have to add the path.
-			 */
 			inuse = btodb((uint64_t)sdp->swd_npginuse <<
 			    PAGE_SHIFT);
 
-#if defined(COMPAT_13) || defined(COMPAT_50)
-			if (cmd == SWAP_STATS) {
-#endif
-				sep->se_dev = sdp->swd_dev;
-				sep->se_flags = sdp->swd_flags;
-				sep->se_nblks = sdp->swd_nblks;
-				sep->se_inuse = inuse;
-				sep->se_priority = sdp->swd_priority;
-				KASSERT(sdp->swd_pathlen <
-				    sizeof(sep->se_path));
-				strcpy(sep->se_path, sdp->swd_path);
-				sep++;
-#if defined(COMPAT_13)
-			} else if (cmd == SWAP_STATS13) {
-				struct swapent13 *sep13 =
-				    (struct swapent13 *)sep;
-
-				sep13->se13_dev = sdp->swd_dev;
-				sep13->se13_flags = sdp->swd_flags;
-				sep13->se13_nblks = sdp->swd_nblks;
-				sep13->se13_inuse = inuse;
-				sep13->se13_priority = sdp->swd_priority;
-				sep = (struct swapent *)(sep13 + 1);
-#endif
-#if defined(COMPAT_50)
-			} else if (cmd == SWAP_STATS50) {
-				struct swapent50 *sep50 =
-				    (struct swapent50 *)sep;
-
-				sep50->se50_dev = sdp->swd_dev;
-				sep50->se50_flags = sdp->swd_flags;
-				sep50->se50_nblks = sdp->swd_nblks;
-				sep50->se50_inuse = inuse;
-				sep50->se50_priority = sdp->swd_priority;
-				KASSERT(sdp->swd_pathlen <
-				    sizeof(sep50->se50_path));
-				strcpy(sep50->se50_path, sdp->swd_path);
-				sep = (struct swapent *)(sep50 + 1);
-#endif
-#if defined(COMPAT_13) || defined(COMPAT_50)
-			}
-#endif
+			swapent_cvt(&sep, sdp, inuse);
+			if (f)
+				(*f)(&sep, &sep);
+			if ((error = copyout(&sep, ptr, len)) != 0)
+				return error;
+			ptr += len;
 			count++;
 		}
 	}
 	*retval = count;
+	return 0;
 }
 
 /*

Index: src/sys/uvm/uvm_swap.h
diff -u src/sys/uvm/uvm_swap.h:1.22 src/sys/uvm/uvm_swap.h:1.23
--- src/sys/uvm/uvm_swap.h:1.22	Thu Jul 30 06:25:49 2015
+++ src/sys/uvm/uvm_swap.h	Wed Mar 14 20:48:13 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_swap.h,v 1.22 2015/07/30 10:25:49 christos Exp $	*/
+/*	$NetBSD: uvm_swap.h,v 1.23 2018/03/15 00:48:13 christos Exp $	*/
 
 /*
  * Copyright (c) 1997 Matthew R. Green
@@ -38,10 +38,12 @@
 #include "opt_vmswap.h"
 #endif
 
-struct swapent;
 struct lwp;
 
 #if defined(VMSWAP)
+
+struct swapent;
+
 int	uvm_swap_get(struct vm_page *, int, int);
 int	uvm_swap_put(int, struct vm_page **, int, int);
 int	uvm_swap_alloc(int *, bool);
@@ -50,12 +52,14 @@ void	uvm_swap_markbad(int, int);
 bool	uvm_swapisfull(void);
 void	swapsys_lock(krw_t);
 void	swapsys_unlock(void);
-void	uvm_swap_stats(int, struct swapent *, int, register_t *);
+int	uvm_swap_stats(char *, int,
+    void (*)(void *, const struct swapent *), size_t, register_t *);
 
 #else /* defined(VMSWAP) */
 #define	uvm_swapisfull()	true
 #define uvm_swap_stats(c, sep, count, retval) { *retval = 0; }
 #endif /* defined(VMSWAP) */
+
 void	uvm_swap_shutdown(struct lwp *);
 
 #endif /* _KERNEL || _MODULE */

Reply via email to