diff options
author | 2003-06-25 20:52:57 +0000 | |
---|---|---|
committer | 2003-06-25 20:52:57 +0000 | |
commit | f634e4568771738bcb7dba26082c1e6903c2fe36 (patch) | |
tree | 1df485ef2c1d1c4c5fee2759ad993be560980645 | |
parent | Fix getopt string for -D (diff) | |
download | wireguard-openbsd-f634e4568771738bcb7dba26082c1e6903c2fe36.tar.xz wireguard-openbsd-f634e4568771738bcb7dba26082c1e6903c2fe36.zip |
implement new means of manipulating buf queues, bufq.
accessed with BUFQ macros, bufq structs support extensible, potentially
changable algorithms and queue formats. the current default scheme
should support nice priority based queuing, but is missing some vfs_bio.c
support.
only on wd.c for now, other drivers are easy converts.
as a side bonus, this makes the driver code look cleaner.
idea for the name comes from netbsd, but this scheme is incompatible.
thanks to various people for testing.
ok grange@
-rw-r--r-- | sys/dev/ata/wd.c | 32 | ||||
-rw-r--r-- | sys/kern/subr_disk.c | 37 | ||||
-rw-r--r-- | sys/sys/buf.h | 24 |
3 files changed, 73 insertions, 20 deletions
diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index ae13f4e3f2a..374580d65ce 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wd.c,v 1.30 2003/05/20 03:59:35 tedu Exp $ */ +/* $OpenBSD: wd.c,v 1.31 2003/06/25 20:52:57 tedu Exp $ */ /* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */ /* @@ -134,7 +134,7 @@ struct wd_softc { /* General disk infos */ struct device sc_dev; struct disk sc_dk; - struct buf sc_q; + struct bufq_default sc_q; /* IDE disk soft states */ struct ata_bio sc_wdc_bio; /* current transfer */ struct buf *sc_bp; /* buf being transferred */ @@ -273,6 +273,9 @@ wdattach(parent, self, aux) char buf[41], c, *p, *q; WDCDEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE); + wd->sc_q.bufq.bufq_get = bufq_default_get; + wd->sc_q.bufq.bufq_add = bufq_default_add; + wd->openings = aa_link->aa_openings; wd->drvp = aa_link->aa_drv_data; @@ -418,14 +421,12 @@ wddetach(self, flags) int flags; { struct wd_softc *sc = (struct wd_softc *)self; - struct buf *dp, *bp; + struct buf *bp; int s, bmaj, cmaj, mn; /* Remove unprocessed buffers from queue */ s = splbio(); - for (dp = &sc->sc_q; (bp = dp->b_actf) != NULL; ) { - dp->b_actf = bp->b_actf; - + while ((bp = BUFQ_GET(&sc->sc_q)) != NULL) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; biodone(bp); @@ -512,7 +513,7 @@ wdstrategy(bp) goto done; /* Queue transfer on drive, activate drive and controller if idle. */ s = splbio(); - disksort(&wd->sc_q, bp); + BUFQ_ADD(&wd->sc_q, bp); wdstart(wd); splx(s); device_unref(&wd->sc_dev); @@ -537,18 +538,16 @@ wdstart(arg) void *arg; { struct wd_softc *wd = arg; - struct buf *dp, *bp=0; + struct buf *bp = NULL; WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname), DEBUG_XFERS); while (wd->openings > 0) { /* Is there a buf for us ? */ - dp = &wd->sc_q; - if ((bp = dp->b_actf) == NULL) /* yes, an assign */ - return; - dp->b_actf = bp->b_actf; - + if ((bp = BUFQ_GET(&wd->sc_q)) == NULL) + return; + /* * Make the command. First lock the device */ @@ -1112,11 +1111,8 @@ wdsize(dev) goto exit; } - if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP) - size = -1; - else - size = wd->sc_dk.dk_label->d_partitions[part].p_size * - (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); + size = wd->sc_dk.dk_label->d_partitions[part].p_size * + (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE); if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0) size = -1; diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index b26bb3a40b7..cace466e490 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_disk.c,v 1.22 2003/06/02 23:28:06 millert Exp $ */ +/* $OpenBSD: subr_disk.c,v 1.23 2003/06/25 20:52:57 tedu Exp $ */ /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */ /* @@ -525,3 +525,38 @@ dk_mountroot() } return (*mountrootfn)(); } + +void +bufq_default_add(struct bufq *bq, struct buf *bp) +{ + struct bufq_default *bufq = (struct bufq_default *)bq; + struct proc *p = bp->b_proc; + struct buf *head; + + if (p == NULL || p->p_nice < NZERO) + head = &bufq->bufq_head[0]; + else if (p->p_nice == NZERO) + head = &bufq->bufq_head[1]; + else + head = &bufq->bufq_head[2]; + + disksort(head, bp); +} + +struct buf * +bufq_default_get(struct bufq *bq) +{ + struct bufq_default *bufq = (struct bufq_default *)bq; + struct buf *bp, *head; + int i; + + for (i = 0; i < 3; i++) { + head = &bufq->bufq_head[i]; + if ((bp = head->b_actf)) + break; + } + if (bp == NULL) + return (NULL); + head->b_actf = bp->b_actf; + return (bp); +} diff --git a/sys/sys/buf.h b/sys/sys/buf.h index 68fcc52b40c..13030886c85 100644 --- a/sys/sys/buf.h +++ b/sys/sys/buf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: buf.h,v 1.43 2003/06/02 23:28:20 millert Exp $ */ +/* $OpenBSD: buf.h,v 1.44 2003/06/25 20:52:57 tedu Exp $ */ /* $NetBSD: buf.h,v 1.25 1997/04/09 21:12:17 mycroft Exp $ */ /* @@ -101,6 +101,28 @@ struct buf { }; /* + * bufq + * flexible buffer queue routines + */ +struct bufq { + void (*bufq_add)(struct bufq*, struct buf *); + struct buf *(*bufq_get)(struct bufq*); +}; + +struct bufq_default { + struct bufq bufq; + struct buf bufq_head[3]; +}; + +#define BUFQ_ADD(_bufq, _bp) \ + ((struct bufq *)_bufq)->bufq_add((struct bufq *)_bufq, _bp) +#define BUFQ_GET(_bufq) \ + ((struct bufq *)_bufq)->bufq_get((struct bufq *)_bufq) + +void bufq_default_add(struct bufq *, struct buf *); +struct buf *bufq_default_get(struct bufq *); + +/* * For portability with historic industry practice, the cylinder number has * to be maintained in the `b_resid' field. */ |