On Fri, Sep 03, 2010 at 09:11:39AM +0000, Thordur I Bjornsson wrote:
> Hi gang,
Gabriel Kihlman spotted a small problem, swd_active was not
being incremented.
Here's an updated diff.
Index: sys/buf.h
===================================================================
RCS file: /home/cvs/src/sys/sys/buf.h,v
retrieving revision 1.72
diff -u -p -r1.72 buf.h
--- sys/buf.h 2 Sep 2010 07:05:39 -0000 1.72
+++ sys/buf.h 5 Sep 2010 14:00:49 -0000
@@ -42,6 +42,7 @@
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/mutex.h>
+#include <sys/workq.h>
#define NOLIST ((struct buf *)0x87654321)
@@ -105,10 +106,18 @@ struct bufq_fifo {
SIMPLEQ_ENTRY(buf) bqf_entries;
};
+/* Abuse bufq_fifo, for swapping to regular files. */
+struct bufq_swapreg {
+ SIMPLEQ_ENTRY(buf) bqf_entries;
+ struct workq_task bqf_wqtask;
+
+};
+
/* bufq link in struct buf */
union bufq_data {
struct bufq_disksort bufq_data_disksort;
struct bufq_fifo bufq_data_fifo;
+ struct bufq_swapreg bufq_swapreg;
};
/*
Index: uvm/uvm_swap.c
===================================================================
RCS file: /home/cvs/src/sys/uvm/uvm_swap.c,v
retrieving revision 1.94
diff -u -p -r1.94 uvm_swap.c
--- uvm/uvm_swap.c 3 Jul 2010 20:28:51 -0000 1.94
+++ uvm/uvm_swap.c 5 Sep 2010 14:03:17 -0000
@@ -138,7 +138,8 @@ struct swapdev {
int swd_bsize; /* blocksize (bytes) */
int swd_maxactive; /* max active i/o reqs */
- struct buf swd_tab; /* buffer list */
+ int swd_active; /* # of active i/o reqs */
+ struct bufq swd_bufq;
struct ucred *swd_cred; /* cred for file access */
#ifdef UVM_SWAP_ENCRYPT
#define SWD_KEY_SHIFT 7 /* One key per 0.5 MByte */
@@ -241,7 +242,8 @@ static int swap_on(struct proc *, struct
static int swap_off(struct proc *, struct swapdev *);
static void sw_reg_strategy(struct swapdev *, struct buf *, int);
-static void sw_reg_iodone(struct buf *);
+void sw_reg_iodone(struct buf *);
+void sw_reg_iodone_internal(void *, void *);
static void sw_reg_start(struct swapdev *);
static int uvm_swap_io(struct vm_page **, int, int, int);
@@ -968,6 +970,7 @@ swap_on(struct proc *p, struct swapdev *
else
#endif /* defined(NFSCLIENT) */
sdp->swd_maxactive = 8; /* XXX */
+ bufq_init(&sdp->swd_bufq, BUFQ_FIFO);
break;
default:
@@ -1372,10 +1375,9 @@ sw_reg_strategy(struct swapdev *sdp, str
nbp->vb_xfer = vnx; /* patch it back in to vnx */
- /*
- * Just sort by block number
- */
+ /* XXX: In case the underlying bufq is disksort: */
nbp->vb_buf.b_cylinder = nbp->vb_buf.b_blkno;
+
s = splbio();
if (vnx->vx_error != 0) {
putvndbuf(nbp);
@@ -1386,8 +1388,8 @@ sw_reg_strategy(struct swapdev *sdp, str
/* assoc new buffer with underlying vnode */
bgetvp(vp, &nbp->vb_buf);
- /* sort it in and start I/O if we are not over our limit */
- disksort(&sdp->swd_tab, &nbp->vb_buf);
+ /* start I/O if we are not over our limit */
+ bufq_queue(&sdp->swd_bufq, &nbp->vb_buf);
sw_reg_start(sdp);
splx(s);
@@ -1413,29 +1415,25 @@ out: /* Arrive here at splbio */
splx(s);
}
-/*
- * sw_reg_start: start an I/O request on the requested swapdev
- *
- * => reqs are sorted by disksort (above)
- */
+/* sw_reg_start: start an I/O request on the requested swapdev. */
static void
sw_reg_start(struct swapdev *sdp)
{
struct buf *bp;
UVMHIST_FUNC("sw_reg_start"); UVMHIST_CALLED(pdhist);
- /* recursion control */
+ /* XXX: recursion control */
if ((sdp->swd_flags & SWF_BUSY) != 0)
return;
sdp->swd_flags |= SWF_BUSY;
- while (sdp->swd_tab.b_active < sdp->swd_maxactive) {
- bp = sdp->swd_tab.b_actf;
+ while (sdp->swd_active < sdp->swd_maxactive) {
+ bp = bufq_dequeue(&sdp->swd_bufq);
if (bp == NULL)
break;
- sdp->swd_tab.b_actf = bp->b_actf;
- sdp->swd_tab.b_active++;
+
+ sdp->swd_active++;
UVMHIST_LOG(pdhist,
"sw_reg_start: bp %p vp %p blkno 0x%lx cnt 0x%lx",
@@ -1452,15 +1450,31 @@ sw_reg_start(struct swapdev *sdp)
* sw_reg_iodone: one of our i/o's has completed and needs post-i/o cleanup
*
* => note that we can recover the vndbuf struct by casting the buf ptr
+ *
+ * XXX:
+ * We only put this onto a workq here, because of the maxactive game since
+ * it basically requires us to call back into VOP_STRATEGY() (where we must
+ * be able to sleep) via sw_reg_start().
*/
-static void
+void
sw_reg_iodone(struct buf *bp)
{
- struct vndbuf *vbp = (struct vndbuf *) bp;
+ struct bufq_swapreg *bq;
+
+ bq = (struct bufq_swapreg *)&bp->b_bufq;
+
+ workq_queue_task(NULL, &bq->bqf_wqtask, 0,
+ (workq_fn)sw_reg_iodone_internal, bp, NULL);
+}
+
+void
+sw_reg_iodone_internal(void *arg0, void *unused)
+{
+ struct vndbuf *vbp = (struct vndbuf *)arg0;
struct vndxfer *vnx = vbp->vb_xfer;
struct buf *pbp = vnx->vx_bp; /* parent buffer */
struct swapdev *sdp = vnx->vx_sdp;
- int resid;
+ int resid, s;
UVMHIST_FUNC("sw_reg_iodone"); UVMHIST_CALLED(pdhist);
UVMHIST_LOG(pdhist, " vbp=%p vp=%p blkno=0x%lx addr=%p",
@@ -1468,7 +1482,7 @@ sw_reg_iodone(struct buf *bp)
UVMHIST_LOG(pdhist, " cnt=%lx resid=%lx",
vbp->vb_buf.b_bcount, vbp->vb_buf.b_resid, 0, 0);
- splassert(IPL_BIO);
+ s = splbio();
resid = vbp->vb_buf.b_bcount - vbp->vb_buf.b_resid;
pbp->b_resid -= resid;
@@ -1519,8 +1533,9 @@ sw_reg_iodone(struct buf *bp)
/*
* done! start next swapdev I/O if one is pending
*/
- sdp->swd_tab.b_active--;
+ sdp->swd_active--;
sw_reg_start(sdp);
+ splx(s);
}