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 */