> Date: Sun, 5 Sep 2010 14:07:03 +0000
> From: Thordur I Bjornsson <[email protected]>
>
> 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.
Hmm, bufq means that things are quiesced; is that what we want here?
> 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);
> }