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