Subject: Re: UVM patch: sys_swapctl split
To: enami tsugutomo <enami@sm.sony.co.jp>
From: Emmanuel Dreyfus <manu@netbsd.org>
List: tech-kern
Date: 03/18/2002 09:16:31
> Does old 1.3 binary prepare `sizeof(struct swapent) * misc' bytes
> space? I guess you should copyout up to the length just
> uvm_swap_stats() copied.
True, here is a hopefully last patch that will fix this.
I can't test a 1.3 swapctl binary: 1.3 did not exist on sgimips.
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/18 08:14:23
@@ -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,17 @@
#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
+ if (SCARG(uap, cmd) == SWAP_OSTATS)
+ 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;
}
@@ -716,4 +682,64 @@
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 wase.
+ */
+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 (SCARG(uap, cmd) == SWAP_STATS)
+#endif
+ (void)memcpy(&sep->se_path, sdp->swd_path,
+ sdp->swd_pathlen);
+
+ count++;
+#if defined(COMPAT_13)
+ if (SCARG(uap, cmd) == SWAP_OSTATS)
+ sep = (struct swapent *)
+ ((struct oswapent *)sep + 1);
+ else
+#endif
+ sep++;
+ }
+ }
+
+ *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/18 08:14:23
@@ -38,4 +38,6 @@
#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));
@@ -43,4 +45,6 @@
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 */
--
Emmanuel Dreyfus
manu@netbsd.org