Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Use a buffer queue. Primary advantage here is robus...



details:   https://anonhg.NetBSD.org/src/rev/9a8cf7c88185
branches:  trunk
changeset: 547395:9a8cf7c88185
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat May 17 21:42:08 2003 +0000

description:
Use a buffer queue.  Primary advantage here is robustness in the face
of temporary resource shortages.

diffstat:

 sys/dev/ccd.c    |  132 +++++++++++++++++++++++++++++++-----------------------
 sys/dev/ccdvar.h |    4 +-
 2 files changed, 79 insertions(+), 57 deletions(-)

diffs (244 lines):

diff -r a0fbf8dbabcd -r 9a8cf7c88185 sys/dev/ccd.c
--- a/sys/dev/ccd.c     Sat May 17 21:28:53 2003 +0000
+++ b/sys/dev/ccd.c     Sat May 17 21:42:08 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ccd.c,v 1.87 2003/05/17 16:11:52 thorpej Exp $ */
+/*     $NetBSD: ccd.c,v 1.88 2003/05/17 21:42:08 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 1999 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.87 2003/05/17 16:11:52 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.88 2003/05/17 21:42:08 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -152,7 +152,7 @@
 /* called by biodone() at interrupt time */
 void   ccdiodone __P((struct buf *));
 
-static void ccdstart __P((struct ccd_softc *, struct buf *));
+static void ccdstart __P((struct ccd_softc *));
 static void ccdinterleave __P((struct ccd_softc *));
 static void ccdintr __P((struct ccd_softc *, struct buf *));
 static int ccdinit __P((struct ccd_softc *, char **, struct vnode **,
@@ -626,6 +626,7 @@
 {
        int unit = ccdunit(bp->b_dev);
        struct ccd_softc *cs = &ccd_softc[unit];
+       daddr_t blkno;
        int s;
        int wlabel;
        struct disklabel *lp;
@@ -652,36 +653,39 @@
 
        /*
         * Do bounds checking and adjust transfer.  If there's an
-        * error, the bounds check will flag that for us.
+        * error, the bounds check will flag that for us.  Convert
+        * the partition relative block number to an absolute.
         */
+       blkno = bp->b_blkno;
        wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
-       if (DISKPART(bp->b_dev) != RAW_PART)
+       if (DISKPART(bp->b_dev) != RAW_PART) {
                if (bounds_check_with_label(&cs->sc_dkdev, bp, wlabel) <= 0)
                        goto done;
-
-       bp->b_resid = bp->b_bcount;
+               blkno += lp->d_partitions[DISKPART(bp->b_dev)].p_offset;
+       }
+       bp->b_rawblkno = blkno;
 
-       /*
-        * "Start" the unit.
-        */
+       /* Place it in the queue and start I/O on the unit. */
        s = splbio();
-       ccdstart(cs, bp);
+       BUFQ_PUT(&cs->sc_bufq, bp);
+       ccdstart(cs);
        splx(s);
        return;
-done:
+
+ done:
+       bp->b_resid = bp->b_bcount;
        biodone(bp);
 }
 
 static void
-ccdstart(cs, bp)
+ccdstart(cs)
        struct ccd_softc *cs;
-       struct buf *bp;
 {
        long bcount, rcount;
+       struct buf *bp;
        struct ccdbuf *cbp;
        caddr_t addr;
        daddr_t bn;
-       struct partition *pp;
        SIMPLEQ_HEAD(, ccdbuf) cbufq;
 
 #ifdef DEBUG
@@ -689,51 +693,52 @@
                printf("ccdstart(%p, %p)\n", cs, bp);
 #endif
 
-       /* Instrumentation. */
-       disk_busy(&cs->sc_dkdev);
+       /* See if there is work for us to do. */
+       while ((bp = BUFQ_PEEK(&cs->sc_bufq)) != NULL) {
+               /* Instrumentation. */
+               disk_busy(&cs->sc_dkdev);
 
-       /*
-        * Translate the partition-relative block number to an absolute.
-        */
-       bn = bp->b_blkno;
-       if (DISKPART(bp->b_dev) != RAW_PART) {
-               pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)];
-               bn += pp->p_offset;
-       }
+               bp->b_resid = bp->b_bcount;
+               bn = bp->b_rawblkno;
 
-       /*
-        * Allocate the component buffers.
-        */
-       SIMPLEQ_INIT(&cbufq);
-       addr = bp->b_data;
-       for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
-               cbp = ccdbuffer(cs, bp, bn, addr, bcount);
-               if (cbp == NULL) {
-                       /* Free the already allocated component buffers. */
-                       while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
-                               SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
-                               CCD_PUTBUF(cbp);
+               /* Allocate the component buffers. */
+               SIMPLEQ_INIT(&cbufq);
+               addr = bp->b_data;
+               for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
+                       cbp = ccdbuffer(cs, bp, bn, addr, bcount);
+                       if (cbp == NULL) {
+                               /*
+                                * Can't allocate a component buffer; just
+                                * defer the job until later.
+                                *
+                                * XXX We might consider a watchdog timer
+                                * XXX to make sure we are kicked into action,
+                                * XXX or consider a low-water mark for our
+                                * XXX component buffer pool.
+                                */
+                               while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
+                                       SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
+                                       CCD_PUTBUF(cbp);
+                               }
+                               disk_unbusy(&cs->sc_dkdev, 0, 0);
+                               return;
                        }
+                       SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
+                       rcount = cbp->cb_buf.b_bcount;
+                       bn += btodb(rcount);
+                       addr += rcount;
+               }
 
-                       /* Notify the upper layer we are out of memory. */
-                       bp->b_error = ENOMEM;
-                       bp->b_flags |= B_ERROR;
-                       biodone(bp);
-                       disk_unbusy(&cs->sc_dkdev, 0, 0);
-                       return;
+               /* Transfer all set up, remove job from the queue. */
+               (void) BUFQ_GET(&cs->sc_bufq);
+
+               /* Now fire off the requests. */
+               while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
+                       SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
+                       if ((cbp->cb_buf.b_flags & B_READ) == 0)
+                               cbp->cb_buf.b_vp->v_numoutput++;
+                       VOP_STRATEGY(&cbp->cb_buf);
                }
-               SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
-               rcount = cbp->cb_buf.b_bcount;
-               bn += btodb(rcount);
-               addr += rcount;
-       }
-
-       /* Now fire off the requests. */
-       while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
-               SIMPLEQ_REMOVE_HEAD(&cbufq, cb_q);
-               if ((cbp->cb_buf.b_flags & B_READ) == 0)
-                       cbp->cb_buf.b_vp->v_numoutput++;
-               VOP_STRATEGY(&cbp->cb_buf);
        }
 }
 
@@ -980,8 +985,9 @@
        struct proc *p;
 {
        int unit = ccdunit(dev);
-       int i, j, lookedup = 0, error;
+       int s, i, j, lookedup = 0, error;
        int part, pmask;
+       struct buf *bp;
        struct ccd_softc *cs;
        struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
        char **cpp;
@@ -1124,6 +1130,8 @@
                ccio->ccio_unit = unit;
                ccio->ccio_size = cs->sc_size;
 
+               bufq_alloc(&cs->sc_bufq, BUFQ_FCFS);
+
                /* Attach the disk. */
                disk_attach(&cs->sc_dkdev);
 
@@ -1146,6 +1154,18 @@
                        goto out;
                }
 
+               /* Kill off any queued buffers. */
+               s = splbio();
+               while ((bp = BUFQ_GET(&cs->sc_bufq)) != NULL) {
+                       bp->b_error = EIO;
+                       bp->b_flags |= B_ERROR;
+                       bp->b_resid = bp->b_bcount;
+                       biodone(bp);
+               }
+               splx(s);
+
+               bufq_free(&cs->sc_bufq);
+
                /*
                 * Free ccd_softc information and clear entry.
                 */
diff -r a0fbf8dbabcd -r 9a8cf7c88185 sys/dev/ccdvar.h
--- a/sys/dev/ccdvar.h  Sat May 17 21:28:53 2003 +0000
+++ b/sys/dev/ccdvar.h  Sat May 17 21:42:08 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ccdvar.h,v 1.21 2003/05/17 16:11:52 thorpej Exp $      */
+/*     $NetBSD: ccdvar.h,v 1.22 2003/05/17 21:42:08 thorpej Exp $      */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 1999 The NetBSD Foundation, Inc.
@@ -78,6 +78,7 @@
  *     @(#)cdvar.h     8.1 (Berkeley) 6/10/93
  */
 
+#include <sys/buf.h>
 #include <sys/lock.h>
 #include <sys/queue.h>
 
@@ -174,6 +175,7 @@
        char             sc_xname[8];           /* XXX external name */
        struct disk      sc_dkdev;              /* generic disk device info */
        struct lock      sc_lock;               /* lock on this structure */
+       struct bufq_state sc_bufq;              /* buffer queue */
 };
 
 /* sc_flags */



Home | Main Index | Thread Index | Old Index