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:
parent
6c2e3b3d83
commit
2debbde786
|
@ -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
|
* Copyright (c) 1995, 1996, 1997 Matthew R. Green
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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 "fs_nfs.h"
|
||||||
#include "opt_uvmhist.h"
|
#include "opt_uvmhist.h"
|
||||||
|
@ -456,7 +456,7 @@ sys_swapctl(p, v, retval)
|
||||||
struct swapent *sep;
|
struct swapent *sep;
|
||||||
char userpath[PATH_MAX + 1];
|
char userpath[PATH_MAX + 1];
|
||||||
size_t len;
|
size_t len;
|
||||||
int count, error, misc;
|
int error, misc;
|
||||||
int priority;
|
int priority;
|
||||||
UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist);
|
UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist);
|
||||||
|
|
||||||
|
@ -494,53 +494,19 @@ sys_swapctl(p, v, retval)
|
||||||
|| SCARG(uap, cmd) == SWAP_OSTATS
|
|| SCARG(uap, cmd) == SWAP_OSTATS
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
sep = (struct swapent *)SCARG(uap, arg);
|
misc = MIN(uvmexp.nswapdev, misc);
|
||||||
count = 0;
|
len = sizeof(struct swapent) * misc;
|
||||||
|
sep = (struct swapent *)malloc(len, M_TEMP, M_WAITOK);
|
||||||
|
|
||||||
LIST_FOREACH(spp, &swap_priority, spi_swappri) {
|
uvm_swap_stats(SCARG(uap, cmd), sep, misc, retval);
|
||||||
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++;
|
|
||||||
#if defined(COMPAT_13)
|
#if defined(COMPAT_13)
|
||||||
if (SCARG(uap, cmd) == SWAP_OSTATS)
|
if (SCARG(uap, cmd) == SWAP_OSTATS)
|
||||||
sep = (struct swapent *)
|
len = sizeof(struct oswapent) * misc;
|
||||||
((struct oswapent *)sep + 1);
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
sep++;
|
error = copyout(sep, (void *)SCARG(uap, arg), len);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
free(sep, M_TEMP);
|
||||||
UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0);
|
UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0);
|
||||||
|
|
||||||
*retval = count;
|
|
||||||
error = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (SCARG(uap, cmd) == SWAP_GETDUMPDEV) {
|
if (SCARG(uap, cmd) == SWAP_GETDUMPDEV) {
|
||||||
|
@ -717,6 +683,66 @@ out:
|
||||||
return (error);
|
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
|
* swap_on: attempt to enable a swapdev for swapping. note that the
|
||||||
* swapdev is already on the global list, but disabled (marked
|
* swapdev is already on the global list, but disabled (marked
|
||||||
|
|
|
@ -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
|
* Copyright (c) 1997 Matthew R. Green
|
||||||
|
@ -37,11 +37,15 @@
|
||||||
|
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
|
|
||||||
|
struct swapent;
|
||||||
|
|
||||||
int uvm_swap_get __P((struct vm_page *, int, int));
|
int uvm_swap_get __P((struct vm_page *, int, int));
|
||||||
int uvm_swap_put __P((int, struct vm_page **, int, int));
|
int uvm_swap_put __P((int, struct vm_page **, int, int));
|
||||||
int uvm_swap_alloc __P((int *, boolean_t));
|
int uvm_swap_alloc __P((int *, boolean_t));
|
||||||
void uvm_swap_free __P((int, int));
|
void uvm_swap_free __P((int, int));
|
||||||
void uvm_swap_markbad __P((int, int));
|
void uvm_swap_markbad __P((int, int));
|
||||||
|
void uvm_swap_stats __P((int, struct swapent *,
|
||||||
|
int, register_t *));
|
||||||
|
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue