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);
 }

Reply via email to