Subject: UVM patch: sys_swapctl split
To: None <tech-kern@netbsd.org>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-kern
Date: 03/17/2002 19:27:19
After the recent dicsussions on the stackgap problem with swapctl(SWAP_STATS)
emulation for IRIX, I come to the following patch. I've got a few questions at
the end...
Index: uvm_swap.c
===================================================================
RCS file: /cvsroot/syssrc/sys/uvm/uvm_swap.c,v
retrieving revision 1.60
diff -U2 -r1.60 uvm_swap.c
--- uvm_swap.c 2002/03/09 07:28:20 1.60
+++ uvm_swap.c 2002/03/17 18:21:32
@@ -457,5 +457,5 @@
char userpath[PATH_MAX + 1];
size_t len;
- int count, error, misc;
+ int error, misc;
int priority;
UVMHIST_FUNC("sys_swapctl"); UVMHIST_CALLED(pdhist);
@@ -495,51 +495,11 @@
#endif
) {
- sep = (struct swapent *)SCARG(uap, arg);
- count = 0;
+ 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));
+ uvm_swap_stats(SCARG(uap, cmd), (void *)sep, misc, retval);
+ error = copyout(sep, (void *)SCARG(uap, arg), len);
+ free(sep, M_TEMP);
- /* 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 (SCARG(uap, cmd) == SWAP_OSTATS)
- sep = (struct swapent *)
- ((struct oswapent *)sep + 1);
- else
-#endif
- sep++;
- }
- }
-
- UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0);
-
- *retval = count;
- error = 0;
goto out;
}
@@ -716,4 +676,65 @@
UVMHIST_LOG(pdhist, "<- done! error=%d", error, 0, 0, 0);
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;
+ void *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 (SCARG(uap, cmd) == SWAP_STATS)
+#endif
+ (void)memcpy(&((struct swapent *)sep)->se_path,
+ sdp->swd_path, sdp->swd_pathlen);
+
+ count++;
+#if defined(COMPAT_13)
+ if (SCARG(uap, cmd) == SWAP_OSTATS)
+ sep = (void *)((struct oswapent *)sep + 1);
+ else
+#endif
+ ((struct swapent *)sep)++;
+ }
+ }
+
+ UVMHIST_LOG(pdhist, "<- done SWAP_STATS", 0, 0, 0, 0);
+
+ *retval = count;
+ return;
}
Index: uvm_swap.h
===================================================================
RCS file: /cvsroot/syssrc/sys/uvm/uvm_swap.h,v
retrieving revision 1.5
diff -U2 -r1.5 uvm_swap.h
--- uvm_swap.h 2000/01/11 06:57:51 1.5
+++ uvm_swap.h 2002/03/17 18:21:33
@@ -43,4 +43,5 @@
void uvm_swap_free __P((int, int));
void uvm_swap_markbad __P((int, int));
+void uvm_swap_stats __P((int, void *, int, register_t *));
#endif /* _KERNEL */
There is one problem I have not been able to address yet: I started with
void uvm_swap_stats __P((int, struct swapent *, int, register_t *));
but this makes an error at build time:
cat ../../../../arch/mips/mips/genassym.cf | sh ../../../../kern/genassym.sh
cc -EB -G 0 -mno-abicalls -mno-half-pic -ffreestanding -g -DDEBUG_IRIX -O2
-Werror -Wall -Wno-main -Wpointer-arith -Wmissing-prototypes -Wstrict-prototypes
-Wno-uninitialized -Dsgimips -I. -I../../../../arch -I../../../.. -nostdinc
-DMIPS3_ENABLE_CLOCK_INTR -DSCSI_DELAY="5" -DMIPS3 -DPARANOIADIAG -DDEBUG
-DDIAGNOSTIC -DMAXUSERS=32 -D_KERNEL -D_KERNEL_OPT > assym.h.tmp && mv -f
assym.h.tmp assym.h
cc1: warnings being treated as errors
In file included from ../../../../uvm/uvm.h:65,
from /tmp/332.c:11:
../../../../uvm/uvm_swap.h:45: warning: `struct swapent' declared inside
parameter list
../../../../uvm/uvm_swap.h:45: warning: its scope is only this definition or
declaration,
../../../../uvm/uvm_swap.h:45: warning: which is probably not what you want.
I had two solutions: adding an #include "sys/swap.h" in uvm/uvm_swap.h or
changing arg #2 type to void * in uvm_swap_stats() prototype. What is the
prefered way?
Also: should I UVMHIST_LOG the entry to uvm_swap_stats?
--
Emmanuel Dreyfus
manu@netbsd.org