Move swapctl(SWAP_STATS) implementation to a separate function called

uvm_swap_stats(). This is done 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.
This commit is contained in:
manu 2002-03-18 11:43:01 +00:00
parent 6c2e3b3d83
commit 2debbde786
2 changed files with 76 additions and 46 deletions

View File

@ -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 <sys/cdefs.h>
__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 */
#if defined(COMPAT_13)
if (error == 0 && SCARG(uap, cmd) == SWAP_STATS)
#else
if (error == 0)
#endif
error = copyout(sdp->swd_path,
&sep->se_path, sdp->swd_pathlen);
if (error)
goto out;
count++;
uvm_swap_stats(SCARG(uap, cmd), sep, misc, retval);
#if defined(COMPAT_13)
if (SCARG(uap, cmd) == SWAP_OSTATS)
sep = (struct swapent *)
((struct oswapent *)sep + 1);
else
len = sizeof(struct oswapent) * misc;
#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

View File

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