diff --git a/sys/uvm/uvm_swap.c b/sys/uvm/uvm_swap.c index 77051f0c5cff..d1566a8566b6 100644 --- a/sys/uvm/uvm_swap.c +++ b/sys/uvm/uvm_swap.c @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_swap.c,v 1.60 2002/03/09 07:28:20 thorpej Exp $ */ +/* $NetBSD: uvm_swap.c,v 1.61 2002/03/18 11:43:01 manu Exp $ */ /* * Copyright (c) 1995, 1996, 1997 Matthew R. Green @@ -32,7 +32,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.60 2002/03/09 07:28:20 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_swap.c,v 1.61 2002/03/18 11:43:01 manu Exp $"); #include "fs_nfs.h" #include "opt_uvmhist.h" @@ -456,7 +456,7 @@ sys_swapctl(p, v, retval) struct swapent *sep; char userpath[PATH_MAX + 1]; size_t len; - int count, error, misc; + int error, misc; int priority; UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist); @@ -494,53 +494,19 @@ sys_swapctl(p, v, retval) || SCARG(uap, cmd) == SWAP_OSTATS #endif ) { - sep = (struct swapent *)SCARG(uap, arg); - count = 0; + misc = MIN(uvmexp.nswapdev, misc); + len = sizeof(struct swapent) * misc; + sep = (struct swapent *)malloc(len, M_TEMP, M_WAITOK); - LIST_FOREACH(spp, &swap_priority, spi_swappri) { - for (sdp = CIRCLEQ_FIRST(&spp->spi_swapdev); - sdp != (void *)&spp->spi_swapdev && misc-- > 0; - sdp = CIRCLEQ_NEXT(sdp, swd_next)) { - /* - * backwards compatibility for system call. - * note that we use 'struct oswapent' as an - * overlay into both 'struct swapdev' and - * the userland 'struct swapent', as we - * want to retain backwards compatibility - * with NetBSD 1.3. - */ - sdp->swd_ose.ose_inuse = - btodb((u_int64_t)sdp->swd_npginuse << - PAGE_SHIFT); - error = copyout(&sdp->swd_ose, sep, - sizeof(struct oswapent)); - - /* now copy out the path if necessary */ + uvm_swap_stats(SCARG(uap, cmd), sep, misc, retval); #if defined(COMPAT_13) - if (error == 0 && SCARG(uap, cmd) == SWAP_STATS) -#else - if (error == 0) + if (SCARG(uap, cmd) == SWAP_OSTATS) + len = sizeof(struct oswapent) * misc; #endif - error = copyout(sdp->swd_path, - &sep->se_path, sdp->swd_pathlen); - - if (error) - goto out; - count++; -#if defined(COMPAT_13) - if (SCARG(uap, cmd) == SWAP_OSTATS) - sep = (struct swapent *) - ((struct oswapent *)sep + 1); - else -#endif - sep++; - } - } + error = copyout(sep, (void *)SCARG(uap, arg), len); + free(sep, M_TEMP); UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0); - - *retval = count; - error = 0; goto out; } if (SCARG(uap, cmd) == SWAP_GETDUMPDEV) { @@ -717,6 +683,66 @@ out: return (error); } +/* + * swap_stats: implements swapctl(SWAP_STATS). The function is kept + * away from sys_swapctl() in order to allow COMPAT_* swapctl() + * emulation to use it directly without going through sys_swapctl(). + * The problem with using sys_swapctl() there is that it involves + * copying the swapent array to the stackgap, and this array's size + * 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(cmd, sep, sec, retval) + int cmd; + struct swapent *sep; + int sec; + register_t *retval; +{ + struct swappri *spp; + struct swapdev *sdp; + int count = 0; + + LIST_FOREACH(spp, &swap_priority, spi_swappri) { + for (sdp = CIRCLEQ_FIRST(&spp->spi_swapdev); + sdp != (void *)&spp->spi_swapdev && sec-- > 0; + sdp = CIRCLEQ_NEXT(sdp, swd_next)) { + /* + * backwards compatibility for system call. + * note that we use 'struct oswapent' as an + * overlay into both 'struct swapdev' and + * the userland 'struct swapent', as we + * want to retain backwards compatibility + * with NetBSD 1.3. + */ + sdp->swd_ose.ose_inuse = + btodb((u_int64_t)sdp->swd_npginuse << + PAGE_SHIFT); + (void)memcpy(sep, &sdp->swd_ose, + sizeof(struct oswapent)); + + /* now copy out the path if necessary */ +#if defined(COMPAT_13) + if (cmd == SWAP_STATS) +#endif + (void)memcpy(&sep->se_path, sdp->swd_path, + sdp->swd_pathlen); + + count++; +#if defined(COMPAT_13) + if (cmd == SWAP_OSTATS) + sep = (struct swapent *) + ((struct oswapent *)sep + 1); + else +#endif + sep++; + } + } + + *retval = count; + return; +} + /* * swap_on: attempt to enable a swapdev for swapping. note that the * swapdev is already on the global list, but disabled (marked diff --git a/sys/uvm/uvm_swap.h b/sys/uvm/uvm_swap.h index 87df5efac2a6..cede713459ce 100644 --- a/sys/uvm/uvm_swap.h +++ b/sys/uvm/uvm_swap.h @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_swap.h,v 1.5 2000/01/11 06:57:51 chs Exp $ */ +/* $NetBSD: uvm_swap.h,v 1.6 2002/03/18 11:43:01 manu Exp $ */ /* * Copyright (c) 1997 Matthew R. Green @@ -37,11 +37,15 @@ #ifdef _KERNEL +struct swapent; + int uvm_swap_get __P((struct vm_page *, int, int)); int uvm_swap_put __P((int, struct vm_page **, int, int)); int uvm_swap_alloc __P((int *, boolean_t)); void uvm_swap_free __P((int, int)); void uvm_swap_markbad __P((int, int)); +void uvm_swap_stats __P((int, struct swapent *, + int, register_t *)); #endif /* _KERNEL */