Source-Changes-HG archive

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

[src/trunk]: src/sys Implement a new device buffer queue interface.



details:   https://anonhg.NetBSD.org/src/rev/7f56dc2c6af7
branches:  trunk
changeset: 534101:7f56dc2c6af7
user:      hannken <hannken%NetBSD.org@localhost>
date:      Tue Jul 16 18:03:17 2002 +0000

description:
Implement a new device buffer queue interface.
One basic struct, a function to setup a queue with a specific strategy and
three macros to put buf's into the queue, get and remove the next buf or
get the next buf without removal.

The BUFQ_XXX interface will be removed in the future.
The B_ORDERED flag is not longer supported.

Approved by: Jason R. Thorpe <thorpej%wasabisystems.com@localhost>

diffstat:

 sys/dev/ata/wd.c       |   16 +-
 sys/dev/scsipi/sd.c    |   14 +-
 sys/dev/scsipi/sdvar.h |    4 +-
 sys/kern/subr_disk.c   |  345 ++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/sys/buf.h          |   44 ++++++-
 5 files changed, 401 insertions(+), 22 deletions(-)

diffs (truncated from 583 to 300 lines):

diff -r 0c88c54a129f -r 7f56dc2c6af7 sys/dev/ata/wd.c
--- a/sys/dev/ata/wd.c  Tue Jul 16 16:40:55 2002 +0000
+++ b/sys/dev/ata/wd.c  Tue Jul 16 18:03:17 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: wd.c,v 1.222 2002/06/28 16:50:30 yamt Exp $ */
+/*     $NetBSD: wd.c,v 1.223 2002/07/16 18:03:17 hannken Exp $ */
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.  All rights reserved.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.222 2002/06/28 16:50:30 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.223 2002/07/16 18:03:17 hannken Exp $");
 
 #ifndef WDCDEBUG
 #define WDCDEBUG
@@ -134,7 +134,7 @@
        /* General disk infos */
        struct device sc_dev;
        struct disk sc_dk;
-       struct buf_queue sc_q;
+       struct bufq_state sc_q;
        struct callout sc_restart_ch;
        /* IDE disk soft states */
        struct ata_bio sc_wdc_bio; /* current transfer */
@@ -267,7 +267,7 @@
        WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
 
        callout_init(&wd->sc_restart_ch);
-       BUFQ_INIT(&wd->sc_q);
+       bufq_init(&wd->sc_q, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
 
        wd->atabus = adev->adev_bustype;
        wd->openings = adev->adev_openings;
@@ -411,8 +411,7 @@
        s = splbio();
 
        /* Kill off any queued buffers. */ 
-       while ((bp = BUFQ_FIRST(&sc->sc_q)) != NULL) {
-               BUFQ_REMOVE(&sc->sc_q, bp);
+       while ((bp = BUFQ_GET(&sc->sc_q)) != NULL) {
                bp->b_error = EIO;
                bp->b_flags |= B_ERROR; 
                bp->b_resid = bp->b_bcount;
@@ -502,7 +501,7 @@
 
        /* Queue transfer on drive, activate drive and controller if idle. */
        s = splbio();
-       disksort_blkno(&wd->sc_q, bp);
+       BUFQ_PUT(&wd->sc_q, bp);
        wdstart(wd);
        splx(s);
        return;
@@ -529,9 +528,8 @@
        while (wd->openings > 0) {
 
                /* Is there a buf for us ? */
-               if ((bp = BUFQ_FIRST(&wd->sc_q)) == NULL)
+               if ((bp = BUFQ_GET(&wd->sc_q)) == NULL)
                        return;
-               BUFQ_REMOVE(&wd->sc_q, bp);
        
                /* 
                 * Make the command. First lock the device
diff -r 0c88c54a129f -r 7f56dc2c6af7 sys/dev/scsipi/sd.c
--- a/sys/dev/scsipi/sd.c       Tue Jul 16 16:40:55 2002 +0000
+++ b/sys/dev/scsipi/sd.c       Tue Jul 16 18:03:17 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sd.c,v 1.183 2002/05/15 13:01:27 bouyer Exp $  */
+/*     $NetBSD: sd.c,v 1.184 2002/07/16 18:03:18 hannken Exp $ */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.183 2002/05/15 13:01:27 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sd.c,v 1.184 2002/07/16 18:03:18 hannken Exp $");
 
 #include "opt_scsi.h"
 #include "rnd.h"
@@ -134,7 +134,7 @@
 
        SC_DEBUG(periph, SCSIPI_DB2, ("sdattach: "));
 
-       BUFQ_INIT(&sd->buf_queue);
+       bufq_init(&sd->buf_queue, BUFQ_DISKSORT|BUFQ_SORT_RAWBLOCK);
 
        /*
         * Store information needed to contact our base driver
@@ -269,8 +269,7 @@
        s = splbio();
 
        /* Kill off any queued buffers. */
-       while ((bp = BUFQ_FIRST(&sd->buf_queue)) != NULL) {
-               BUFQ_REMOVE(&sd->buf_queue, bp);
+       while ((bp = BUFQ_GET(&sd->buf_queue)) != NULL) {
                bp->b_error = EIO;
                bp->b_flags |= B_ERROR;
                bp->b_resid = bp->b_bcount;
@@ -644,7 +643,7 @@
         * XXX Only do disksort() if the current operating mode does not
         * XXX include tagged queueing.
         */
-       disksort_blkno(&sd->buf_queue, bp);
+       BUFQ_PUT(&sd->buf_queue, bp);
 
        /*
         * Tell the device to get going on the transfer if it's
@@ -714,9 +713,8 @@
                /*
                 * See if there is a buf with work for us to do..
                 */
-               if ((bp = BUFQ_FIRST(&sd->buf_queue)) == NULL)
+               if ((bp = BUFQ_GET(&sd->buf_queue)) == NULL)
                        return;
-               BUFQ_REMOVE(&sd->buf_queue, bp);
 
                /*
                 * If the device has become invalid, abort all the
diff -r 0c88c54a129f -r 7f56dc2c6af7 sys/dev/scsipi/sdvar.h
--- a/sys/dev/scsipi/sdvar.h    Tue Jul 16 16:40:55 2002 +0000
+++ b/sys/dev/scsipi/sdvar.h    Tue Jul 16 18:03:17 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdvar.h,v 1.16 2002/01/09 04:12:12 thorpej Exp $       */
+/*     $NetBSD: sdvar.h,v 1.17 2002/07/16 18:03:18 hannken Exp $       */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -93,7 +93,7 @@
                u_long  rot_rate;       /* rotational rate, in RPM */
        } params;
 
-       struct buf_queue buf_queue;
+       struct bufq_state buf_queue;
        u_int8_t type;
        char name[16]; /* product name, for default disklabel */
        const struct sd_ops *sc_ops;    /* our bus-dependent ops vector */
diff -r 0c88c54a129f -r 7f56dc2c6af7 sys/kern/subr_disk.c
--- a/sys/kern/subr_disk.c      Tue Jul 16 16:40:55 2002 +0000
+++ b/sys/kern/subr_disk.c      Tue Jul 16 18:03:17 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: subr_disk.c,v 1.38 2002/06/28 16:37:21 yamt Exp $      */
+/*     $NetBSD: subr_disk.c,v 1.39 2002/07/16 18:03:19 hannken Exp $   */
 
 /*-
  * Copyright (c) 1996, 1997, 1999, 2000 The NetBSD Foundation, Inc.
@@ -78,7 +78,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_disk.c,v 1.38 2002/06/28 16:37:21 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_disk.c,v 1.39 2002/07/16 18:03:19 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -98,6 +98,8 @@
 struct simplelock disklist_slock = SIMPLELOCK_INITIALIZER;
 
 /*
+ * XXX This interface will be removed in the near future!
+ *
  * Seek sort for disks.  We depend on the driver which calls us using b_resid
  * as the current cylinder number.
  *
@@ -305,6 +307,10 @@
 }
 
 /*
+ * XXX End of to be removed interface!
+ */
+
+/*
  * Compute checksum for disk label.
  */
 u_int
@@ -637,3 +643,338 @@
        simple_unlock(&disklist_slock);
        return (error);
 }
+
+
+struct bufq_fcfs {
+       TAILQ_HEAD(, buf) bq_head;      /* actual list of buffers */
+};
+
+struct bufq_disksort {
+       TAILQ_HEAD(, buf) bq_head;      /* actual list of buffers */
+};
+
+#define PRIO_READ_BURST                48
+#define PRIO_WRITE_REQ         16
+
+struct bufq_prio {
+       TAILQ_HEAD(, buf) bq_read, bq_write; /* actual list of buffers */
+       struct buf *bq_write_next;      /* next request in bq_write */
+       int bq_read_burst;              /* # of consecutive reads */
+};
+
+
+/*
+ * Check if two buf's are in ascending order.
+ */
+static __inline int
+buf_inorder(struct buf *bp, struct buf *bq, int sortby)
+{
+       int r;
+
+       if (bp == NULL || bq == NULL)
+               return(bq == NULL);
+
+       if (sortby == BUFQ_SORT_CYLINDER)
+               r = bp->b_cylinder - bq->b_cylinder;
+       else
+               r = 0;
+
+       if (r == 0)
+               r = bp->b_rawblkno - bq->b_rawblkno;
+
+       return(r <= 0);
+}
+
+
+/*
+ * First-come first-served sort for disks.
+ *
+ * Requests are appended to the queue without any reordering.
+ */
+static void
+bufq_fcfs_put(struct bufq_state *bufq, struct buf *bp)
+{
+       struct bufq_fcfs *fcfs = bufq->bq_private;
+
+       TAILQ_INSERT_TAIL(&fcfs->bq_head, bp, b_actq);
+}
+
+static struct buf *
+bufq_fcfs_get(struct bufq_state *bufq, int remove)
+{
+       struct bufq_fcfs *fcfs = bufq->bq_private;
+       struct buf *bp;
+
+       bp = TAILQ_FIRST(&fcfs->bq_head);
+
+       if (bp != NULL && remove)
+               TAILQ_REMOVE(&fcfs->bq_head, bp, b_actq);
+
+       return(bp);
+}
+
+
+/*
+ * Seek sort for disks.
+ *
+ * There are actually two queues, sorted in ascendening order.  The first
+ * queue holds those requests which are positioned after the current block;
+ * the second holds requests which came in after their position was passed.
+ * Thus we implement a one-way scan, retracting after reaching the end of
+ * the drive to the first request on the second queue, at which time it
+ * becomes the first queue.
+ *
+ * A one-way scan is natural because of the way UNIX read-ahead blocks are
+ * allocated.
+ */
+static void
+bufq_disksort_put(struct bufq_state *bufq, struct buf *bp)
+{
+       struct bufq_disksort *disksort = bufq->bq_private;
+       struct buf *bq, *nbq;
+       int sortby;
+
+       sortby = bufq->bq_flags & BUFQ_SORT_MASK;
+
+       bq = TAILQ_FIRST(&disksort->bq_head);
+
+       /*
+        * If the queue is empty it's easy; we just go on the end.
+        */
+       if (bq == NULL) {
+               TAILQ_INSERT_TAIL(&disksort->bq_head, bp, b_actq);
+               return;
+       }
+
+       /*
+        * If we lie before the currently active request, then we
+        * must locate the second request list and add ourselves to it.
+        */
+       if (buf_inorder(bp, bq, sortby)) {
+               while ((nbq = TAILQ_NEXT(bq, b_actq)) != NULL) {
+                       /*
+                        * Check for an ``inversion'' in the normally ascending
+                        * block numbers, indicating the start of the second
+                        * request list.
+                        */
+                       if (buf_inorder(nbq, bq, sortby)) {
+                               /*
+                                * Search the second request list for the first



Home | Main Index | Thread Index | Old Index