this diff is largely a mechanical change. firstly, it makes struct bufq a member of the softc for devices that use it, rather than it being a pointer to something that needs to be allocated at attach. since all these devices need a bufq to operate, it makes sense to have it allocated as part of the softc and get bufq_init to just initialise all its fields. it also gets rid of the possibility that you wont be able to allocate teh bufq struct during attach, which is something you dont want to happen.
secondly, it consistently implements a split between wrapper functions and the per discipline implementation of the bufq handlers. it consistently does the locking in the wrappers rather than doing half in the wrappers and the other half in the implementations. it also consistently handles the outstanding bufq bq pointer in the wrappers. this hides most of the implementation inside kern_bufq.c. the only stuff left in buf.h is for the bits each implementation needs to put bufs on their queues. ive tested this extensively on sd(4) and thib has tested this on wd(4). we'd like some wider exposure, especially over suspends and resumes on a variety of machines. i have tried to preserve the locking semantics, but testing would be lovely. ok? dlg Index: dev/ata/wd.c =================================================================== RCS file: /cvs/src/sys/dev/ata/wd.c,v retrieving revision 1.85 diff -u -p -r1.85 wd.c --- dev/ata/wd.c 28 Jun 2010 08:35:46 -0000 1.85 +++ dev/ata/wd.c 25 Aug 2010 12:05:33 -0000 @@ -121,7 +121,7 @@ struct wd_softc { /* General disk infos */ struct device sc_dev; struct disk sc_dk; - struct bufq *sc_bufq; + struct bufq sc_bufq; /* IDE disk soft states */ struct ata_bio sc_wdc_bio; /* current transfer */ @@ -369,7 +369,7 @@ wdattach(struct device *parent, struct d */ wd->sc_dk.dk_driver = &wddkdriver; wd->sc_dk.dk_name = wd->sc_dev.dv_xname; - wd->sc_bufq = bufq_init(BUFQ_DEFAULT); + bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd); if (wd->sc_sdhook == NULL) printf("%s: WARNING: unable to establish shutdown hook\n", @@ -413,7 +413,7 @@ wddetach(struct device *self, int flags) /* Remove unprocessed buffers from queue */ s = splbio(); - while ((bp = BUFQ_DEQUEUE(sc->sc_bufq)) != NULL) { + while ((bp = bufq_dequeue(&sc->sc_bufq)) != NULL) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; biodone(bp); @@ -435,7 +435,7 @@ wddetach(struct device *self, int flags) shutdownhook_disestablish(sc->sc_sdhook); /* Detach disk. */ - bufq_destroy(sc->sc_bufq); + bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return (0); @@ -486,7 +486,7 @@ wdstrategy(struct buf *bp) (wd->sc_flags & (WDF_WLABEL|WDF_LABELLING)) != 0) <= 0) goto done; /* Queue transfer on drive, activate drive and controller if idle. */ - BUFQ_QUEUE(wd->sc_bufq, bp); + bufq_queue(&wd->sc_bufq, bp); s = splbio(); wdstart(wd); splx(s); @@ -518,7 +518,7 @@ wdstart(void *arg) while (wd->openings > 0) { /* Is there a buf for us ? */ - if ((bp = BUFQ_DEQUEUE(wd->sc_bufq)) == NULL) + if ((bp = bufq_dequeue(&wd->sc_bufq)) == NULL) return; /* * Make the command. First lock the device Index: kern/kern_bufq.c =================================================================== RCS file: /cvs/src/sys/kern/kern_bufq.c,v retrieving revision 1.14 diff -u -p -r1.14 kern_bufq.c --- kern/kern_bufq.c 19 Jul 2010 21:39:15 -0000 1.14 +++ kern/kern_bufq.c 25 Aug 2010 12:05:33 -0000 @@ -30,45 +30,70 @@ SLIST_HEAD(, bufq) bufqs = SLIST_HEAD_IN struct mutex bufqs_mtx = MUTEX_INITIALIZER(IPL_NONE); int bufqs_stop; -struct buf *(*bufq_dequeuev[BUFQ_HOWMANY])(struct bufq *, int) = { - bufq_disksort_dequeue, - bufq_fifo_dequeue +struct bufq_impl { + void *(*impl_create)(void); + void (*impl_destroy)(void *); + + void (*impl_queue)(void *, struct buf *); + struct buf *(*impl_dequeue)(void *); + void (*impl_requeue)(void *, struct buf *); + int (*impl_peek)(void *); }; -void (*bufq_queuev[BUFQ_HOWMANY])(struct bufq *, struct buf *) = { + +void *bufq_disksort_create(void); +void bufq_disksort_destroy(void *); +void bufq_disksort_queue(void *, struct buf *); +struct buf *bufq_disksort_dequeue(void *); +void bufq_disksort_requeue(void *, struct buf *); +int bufq_disksort_peek(void *); + +struct bufq_impl bufq_impl_disksort = { + bufq_disksort_create, + bufq_disksort_destroy, bufq_disksort_queue, - bufq_fifo_queue -}; -void (*bufq_requeuev[BUFQ_HOWMANY])(struct bufq *, struct buf *) = { + bufq_disksort_dequeue, bufq_disksort_requeue, - bufq_fifo_requeue + bufq_disksort_peek }; +void *bufq_fifo_create(void); +void bufq_fifo_destroy(void *); +void bufq_fifo_queue(void *, struct buf *); +struct buf *bufq_fifo_dequeue(void *); +void bufq_fifo_requeue(void *, struct buf *); +int bufq_fifo_peek(void *); + +struct bufq_impl bufq_impl_fifo = { + bufq_fifo_create, + bufq_fifo_destroy, + bufq_fifo_queue, + bufq_fifo_dequeue, + bufq_fifo_requeue, + bufq_fifo_peek +}; -struct bufq * -bufq_init(int type) -{ - struct bufq *bq; - int error; +struct bufq_impl *bufq_impls[BUFQ_HOWMANY] = { + &bufq_impl_disksort, + &bufq_impl_fifo +}; - bq = malloc(sizeof(*bq), M_DEVBUF, M_NOWAIT|M_ZERO); - KASSERT(bq != NULL); +int +bufq_init(struct bufq *bq, int type) +{ + if (type > BUFQ_HOWMANY) + panic("bufq_init: type %i unknown", type); mtx_init(&bq->bufq_mtx, IPL_BIO); bq->bufq_type = type; - - switch (type) { - case BUFQ_DISKSORT: - error = bufq_disksort_init(bq); - break; - case BUFQ_FIFO: - error = bufq_fifo_init(bq); - break; - default: - panic("bufq_init: type %i unknown", type); - break; - }; - - KASSERT(error == 0); + bq->bufq_impl = bufq_impls[type]; + bq->bufq_data = bq->bufq_impl->impl_create(); + if (bq->bufq_data == NULL) { + /* + * we should actually return failure so disks attaching after + * boot in low memory situations dont panic the system. + */ + panic("bufq init fail"); + } mtx_enter(&bufqs_mtx); while (bufqs_stop) { @@ -77,7 +102,48 @@ bufq_init(int type) SLIST_INSERT_HEAD(&bufqs, bq, bufq_entries); mtx_leave(&bufqs_mtx); - return (bq); + return (0); +} + +int +bufq_switch(struct bufq *bq, int type) +{ + void *data; + void *odata; + int otype; + struct buf *bp; + int ret; + + mtx_enter(&bq->bufq_mtx); + ret = (bq->bufq_type == type); + mtx_leave(&bq->bufq_mtx); + if (ret) + return (0); + + data = bufq_impls[type]->impl_create(); + if (data == NULL) + return (ENOMEM); + + mtx_enter(&bq->bufq_mtx); + if (bq->bufq_type != type) { /* might have changed during create */ + odata = bq->bufq_data; + otype = bq->bufq_type; + + while ((bp = bufq_impls[otype]->impl_dequeue(odata)) != NULL) + bufq_impls[type]->impl_queue(data, bp); + + bq->bufq_data = data; + bq->bufq_type = type; + bq->bufq_impl = bufq_impls[type]; + } else { + otype = type; + odata = data; + } + mtx_leave(&bq->bufq_mtx); + + bufq_impls[otype]->impl_destroy(odata); + + return (0); } void @@ -85,8 +151,8 @@ bufq_destroy(struct bufq *bq) { bufq_drain(bq); - if (bq->bufq_data != NULL) - free(bq->bufq_data, M_DEVBUF); + bq->bufq_impl->impl_destroy(bq->bufq_data); + bq->bufq_data = NULL; mtx_enter(&bufqs_mtx); while (bufqs_stop) { @@ -94,10 +160,9 @@ bufq_destroy(struct bufq *bq) } SLIST_REMOVE(&bufqs, bq, bufq, bufq_entries); mtx_leave(&bufqs_mtx); - - free(bq, M_DEVBUF); } + void bufq_queue(struct bufq *bq, struct buf *bp) { @@ -105,16 +170,43 @@ bufq_queue(struct bufq *bq, struct buf * while (bq->bufq_stop) { msleep(&bq->bufq_stop, &bq->bufq_mtx, PRIBIO, "bqqueue", 0); } - bufq_queuev[bq->bufq_type](bq, bp); + + bp->b_bq = bq; + bq->bufq_outstanding++; + bq->bufq_impl->impl_queue(bq->bufq_data, bp); + mtx_leave(&bq->bufq_mtx); +} + +struct buf * +bufq_dequeue(struct bufq *bq) +{ + struct buf *bp; + + mtx_enter(&bq->bufq_mtx); + bp = bq->bufq_impl->impl_dequeue(bq->bufq_data); mtx_leave(&bq->bufq_mtx); + + return (bp); } void bufq_requeue(struct bufq *bq, struct buf *bp) { mtx_enter(&bq->bufq_mtx); - bufq_requeuev[bq->bufq_type](bq, bp); + bq->bufq_impl->impl_requeue(bq->bufq_data, bp); + mtx_leave(&bq->bufq_mtx); +} + +int +bufq_peek(struct bufq *bq) +{ + int rv; + + mtx_enter(&bq->bufq_mtx); + rv = bq->bufq_impl->impl_peek(bq->bufq_data); mtx_leave(&bq->bufq_mtx); + + return (rv); } void @@ -123,7 +215,7 @@ bufq_drain(struct bufq *bq) struct buf *bp; int s; - while ((bp = BUFQ_DEQUEUE(bq)) != NULL) { + while ((bp = bufq_dequeue(bq)) != NULL) { bp->b_error = ENXIO; bp->b_flags |= B_ERROR; s = splbio(); @@ -138,7 +230,7 @@ bufq_done(struct bufq *bq, struct buf *b mtx_enter(&bq->bufq_mtx); bq->bufq_outstanding--; KASSERT(bq->bufq_outstanding >= 0); - if (bq->bufq_outstanding == 0) + if (bq->bufq_outstanding == 0 /* XXX and quiesced */) wakeup(&bq->bufq_outstanding); mtx_leave(&bq->bufq_mtx); bp->b_bq = NULL; @@ -152,7 +244,7 @@ bufq_quiesce(void) mtx_enter(&bufqs_mtx); bufqs_stop = 1; mtx_leave(&bufqs_mtx); - SLIST_FOREACH(bq, &bufqs, bufq_entries) { + SLIST_FOREACH(bq, &bufqs, bufq_entries) { /* XXX */ mtx_enter(&bq->bufq_mtx); bq->bufq_stop = 1; while (bq->bufq_outstanding) { @@ -180,24 +272,47 @@ bufq_restart(void) mtx_leave(&bufqs_mtx); } +/* + * disksort implementation. + */ + +void * +bufq_disksort_create(void) +{ + return (malloc(sizeof(struct buf), M_DEVBUF, M_NOWAIT | M_ZERO)); +} + void -bufq_disksort_queue(struct bufq *bq, struct buf *bp) +bufq_disksort_destroy(void *data) { - struct buf *bufq; + free(data, M_DEVBUF); +} - bufq = (struct buf *)bq->bufq_data; +void +bufq_disksort_queue(void *data, struct buf *bp) +{ + disksort((struct buf *)data, bp); +} - bq->bufq_outstanding++; - bp->b_bq = bq; - disksort(bufq, bp); +struct buf * +bufq_disksort_dequeue(void *data) +{ + struct buf *bufq = data; + struct buf *bp; + + bp = bufq->b_actf; + if (bp != NULL) + bufq->b_actf = bp->b_actf; + if (bufq->b_actf == NULL) + bufq->b_actb = &bufq->b_actf; + + return (bp); } void -bufq_disksort_requeue(struct bufq *bq, struct buf *bp) +bufq_disksort_requeue(void *data, struct buf *bp) { - struct buf *bufq; - - bufq = (struct buf *)bq->bufq_data; + struct buf *bufq = data; bp->b_actf = bufq->b_actf; bufq->b_actf = bp; @@ -205,83 +320,71 @@ bufq_disksort_requeue(struct bufq *bq, s bufq->b_actb = &bp->b_actf; } -struct buf * -bufq_disksort_dequeue(struct bufq *bq, int peeking) +int +bufq_disksort_peek(void *data) { - struct buf *bufq, *bp; + struct buf *bufq = data; - mtx_enter(&bq->bufq_mtx); - bufq = (struct buf *)bq->bufq_data; - bp = bufq->b_actf; - if (!peeking) { - if (bp != NULL) - bufq->b_actf = bp->b_actf; - if (bufq->b_actf == NULL) - bufq->b_actb = &bufq->b_actf; - } - mtx_leave(&bq->bufq_mtx); - - return (bp); + return (bufq->b_actf != NULL); } -int -bufq_disksort_init(struct bufq *bq) +/* + * fifo implementation + */ + +void * +bufq_fifo_create(void) { - int error = 0; + struct bufq_fifo_head *head; - bq->bufq_data = malloc(sizeof(struct buf), M_DEVBUF, - M_NOWAIT|M_ZERO); + head = malloc(sizeof(*head), M_DEVBUF, M_NOWAIT | M_ZERO); + if (head == NULL) + return (NULL); - if (bq->bufq_data == NULL) - error = ENOMEM; + SIMPLEQ_INIT(head); - return (error); + return (head); } void -bufq_fifo_queue(struct bufq *bq, struct buf *bp) +bufq_fifo_destroy(void *data) { - struct bufq_fifo_head *head = bq->bufq_data; - - bq->bufq_outstanding++; - bp->b_bq = bq; - SIMPLEQ_INSERT_TAIL(head, bp, b_bufq.bufq_data_fifo.bqf_entries); + free(data, M_DEVBUF); } void -bufq_fifo_requeue(struct bufq *bq, struct buf *bp) +bufq_fifo_queue(void *data, struct buf *bp) { - struct bufq_fifo_head *head = bq->bufq_data; + struct bufq_fifo_head *head = data; - SIMPLEQ_INSERT_HEAD(head, bp, b_bufq.bufq_data_fifo.bqf_entries); + SIMPLEQ_INSERT_TAIL(head, bp, b_bufq.bufq_data_fifo.bqf_entries); } struct buf * -bufq_fifo_dequeue(struct bufq *bq, int peeking) +bufq_fifo_dequeue(void *data) { - struct bufq_fifo_head *head = bq->bufq_data; - struct buf *bp; + struct bufq_fifo_head *head = data; + struct buf *bp; - mtx_enter(&bq->bufq_mtx); bp = SIMPLEQ_FIRST(head); - if (bp != NULL && !peeking) + if (bp != NULL) SIMPLEQ_REMOVE_HEAD(head, b_bufq.bufq_data_fifo.bqf_entries); - mtx_leave(&bq->bufq_mtx); return (bp); } -int -bufq_fifo_init(struct bufq *bq) +void +bufq_fifo_requeue(void *data, struct buf *bp) { - struct bufq_fifo_head *head; + struct bufq_fifo_head *head = data; - head = malloc(sizeof(*head), M_DEVBUF, M_NOWAIT); - if (head == NULL) - return (ENOMEM); + SIMPLEQ_INSERT_HEAD(head, bp, b_bufq.bufq_data_fifo.bqf_entries); +} - SIMPLEQ_INIT(head); - bq->bufq_data = head; +int +bufq_fifo_peek(void *data) +{ + struct bufq_fifo_head *head = data; - return (0); + return (SIMPLEQ_FIRST(head) != NULL); } Index: scsi/cd.c =================================================================== RCS file: /cvs/src/sys/scsi/cd.c,v retrieving revision 1.181 diff -u -p -r1.181 cd.c --- scsi/cd.c 28 Jul 2010 23:47:43 -0000 1.181 +++ scsi/cd.c 25 Aug 2010 12:05:33 -0000 @@ -111,7 +111,7 @@ struct cd_softc { u_int32_t blksize; daddr64_t disksize; /* total number sectors */ } sc_params; - struct bufq *sc_bufq; + struct bufq sc_bufq; struct scsi_xshandler sc_xsh; struct timeout sc_timeout; void *sc_cdpwrhook; /* our power hook */ @@ -219,7 +219,7 @@ cdattach(struct device *parent, struct d */ sc->sc_dk.dk_driver = &cddkdriver; sc->sc_dk.dk_name = sc->sc_dev.dv_xname; - sc->sc_bufq = bufq_init(BUFQ_DEFAULT); + bufq_init(&sc->sc_bufq, BUFQ_DEFAULT); /* * Note if this device is ancient. This is used in cdminphys(). @@ -255,7 +255,7 @@ cdactivate(struct device *self, int act) case DVACT_DEACTIVATE: sc->sc_flags |= CDF_DYING; - bufq_drain(sc->sc_bufq); + bufq_drain(&sc->sc_bufq); break; } return (rv); @@ -268,7 +268,7 @@ cddetach(struct device *self, int flags) struct cd_softc *sc = (struct cd_softc *)self; int bmaj, cmaj, mn; - bufq_drain(sc->sc_bufq); + bufq_drain(&sc->sc_bufq); /* Locate the lowest minor number to be detached. */ mn = DISKMINOR(self->dv_unit, 0); @@ -285,7 +285,7 @@ cddetach(struct device *self, int flags) powerhook_disestablish(sc->sc_cdpwrhook); /* Detach disk. */ - bufq_destroy(sc->sc_bufq); + bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return (0); @@ -530,7 +530,7 @@ cdstrategy(struct buf *bp) goto done; /* Place it in the queue of disk activities for this disk. */ - BUFQ_QUEUE(sc->sc_bufq, bp); + bufq_queue(&sc->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's @@ -596,12 +596,12 @@ cdstart(struct scsi_xfer *xs) * re-opened */ if ((sc_link->flags & SDEV_MEDIA_LOADED) == 0) { - bufq_drain(sc->sc_bufq); + bufq_drain(&sc->sc_bufq); scsi_xs_put(xs); return; } - bp = BUFQ_DEQUEUE(sc->sc_bufq); + bp = bufq_dequeue(&sc->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; @@ -665,7 +665,7 @@ cdstart(struct scsi_xfer *xs) if (ISSET(sc->sc_flags, CDF_WAITING)) CLR(sc->sc_flags, CDF_WAITING); - else if (BUFQ_PEEK(sc->sc_bufq)) + else if (bufq_peek(&sc->sc_bufq)) scsi_xsh_add(&sc->sc_xsh); } @@ -686,7 +686,7 @@ cd_buf_done(struct scsi_xfer *xs) /* The adapter is busy, requeue the buf and try it later. */ disk_unbusy(&sc->sc_dk, bp->b_bcount - xs->resid, bp->b_flags & B_READ); - BUFQ_REQUEUE(sc->sc_bufq, bp); + bufq_requeue(&sc->sc_bufq, bp); scsi_xs_put(xs); SET(sc->sc_flags, CDF_WAITING); timeout_add(&sc->sc_timeout, 1); Index: scsi/sd.c =================================================================== RCS file: /cvs/src/sys/scsi/sd.c,v retrieving revision 1.205 diff -u -p -r1.205 sd.c --- scsi/sd.c 3 Aug 2010 19:37:17 -0000 1.205 +++ scsi/sd.c 25 Aug 2010 12:05:33 -0000 @@ -175,7 +175,7 @@ sdattach(struct device *parent, struct d */ sc->sc_dk.dk_driver = &sddkdriver; sc->sc_dk.dk_name = sc->sc_dev.dv_xname; - sc->sc_bufq = bufq_init(BUFQ_DEFAULT); + bufq_init(&sc->sc_bufq, BUFQ_DEFAULT); if ((sc_link->flags & SDEV_ATAPI) && (sc_link->flags & SDEV_REMOVABLE)) sc_link->quirks |= SDEV_NOSYNCCACHE; @@ -279,7 +279,7 @@ sdactivate(struct device *self, int act) case DVACT_DEACTIVATE: sc->flags |= SDF_DYING; - bufq_drain(sc->sc_bufq); + bufq_drain(&sc->sc_bufq); break; case DVACT_SUSPEND: @@ -309,7 +309,7 @@ sddetach(struct device *self, int flags) struct sd_softc *sc = (struct sd_softc *)self; int bmaj, cmaj, mn; - bufq_drain(sc->sc_bufq); + bufq_drain(&sc->sc_bufq); /* Locate the lowest minor number to be detached. */ mn = DISKMINOR(self->dv_unit, 0); @@ -326,7 +326,7 @@ sddetach(struct device *self, int flags) shutdownhook_disestablish(sc->sc_sdhook); /* Detach disk. */ - bufq_destroy(sc->sc_bufq); + bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); return (0); @@ -581,7 +581,7 @@ sdstrategy(struct buf *bp) goto done; /* Place it in the queue of disk activities for this disk. */ - BUFQ_QUEUE(sc->sc_bufq, bp); + bufq_queue(&sc->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's @@ -683,12 +683,12 @@ sdstart(struct scsi_xfer *xs) return; } if ((link->flags & SDEV_MEDIA_LOADED) == 0) { - bufq_drain(sc->sc_bufq); + bufq_drain(&sc->sc_bufq); scsi_xs_put(xs); return; } - bp = BUFQ_DEQUEUE(sc->sc_bufq); + bp = bufq_dequeue(&sc->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; @@ -739,7 +739,7 @@ sdstart(struct scsi_xfer *xs) /* move onto the next io */ if (ISSET(sc->flags, SDF_WAITING)) CLR(sc->flags, SDF_WAITING); - else if (BUFQ_PEEK(sc->sc_bufq) != NULL) + else if (bufq_peek(&sc->sc_bufq) != NULL) scsi_xsh_add(&sc->sc_xsh); } @@ -760,7 +760,7 @@ sd_buf_done(struct scsi_xfer *xs) /* The adapter is busy, requeue the buf and try it later. */ disk_unbusy(&sc->sc_dk, bp->b_bcount - xs->resid, bp->b_flags & B_READ); - BUFQ_REQUEUE(sc->sc_bufq, bp); + bufq_requeue(&sc->sc_bufq, bp); scsi_xs_put(xs); SET(sc->flags, SDF_WAITING); timeout_add(&sc->sc_timeout, 1); Index: scsi/sdvar.h =================================================================== RCS file: /cvs/src/sys/scsi/sdvar.h,v retrieving revision 1.31 diff -u -p -r1.31 sdvar.h --- scsi/sdvar.h 2 Jun 2010 13:32:13 -0000 1.31 +++ scsi/sdvar.h 25 Aug 2010 12:05:33 -0000 @@ -51,7 +51,7 @@ struct sd_softc { struct device sc_dev; struct disk sc_dk; - struct bufq *sc_bufq; + struct bufq sc_bufq; int flags; #define SDF_LOCKED 0x01 Index: scsi/st.c =================================================================== RCS file: /cvs/src/sys/scsi/st.c,v retrieving revision 1.106 diff -u -p -r1.106 st.c --- scsi/st.c 22 Jul 2010 05:26:34 -0000 1.106 +++ scsi/st.c 25 Aug 2010 12:05:33 -0000 @@ -215,7 +215,7 @@ struct st_softc { #define BLKSIZE_SET_BY_USER 0x04 #define BLKSIZE_SET_BY_QUIRK 0x08 - struct bufq *sc_bufq; + struct bufq sc_bufq; struct timeout sc_timeout; struct scsi_xshandler sc_xsh; }; @@ -331,7 +331,7 @@ stattach(struct device *parent, struct d &st->sc_xsh); /* Set up the buf queue for this device. */ - st->sc_bufq = bufq_init(BUFQ_FIFO); + bufq_init(&st->sc_bufq, BUFQ_FIFO); /* Start up with media position unknown. */ st->media_fileno = -1; @@ -357,7 +357,7 @@ stactivate(struct device *self, int act) case DVACT_DEACTIVATE: st->flags |= ST_DYING; - bufq_drain(st->sc_bufq); + bufq_drain(&st->sc_bufq); break; } @@ -370,7 +370,7 @@ stdetach(struct device *self, int flags) struct st_softc *st = (struct st_softc *)self; int bmaj, cmaj, mn; - bufq_drain(st->sc_bufq); + bufq_drain(&st->sc_bufq); /* Locate the lowest minor number to be detached. */ mn = STUNIT(self->dv_unit); @@ -390,7 +390,7 @@ stdetach(struct device *self, int flags) vdevgone(cmaj, mn, mn + 3, VCHR); } - bufq_destroy(st->sc_bufq); + bufq_destroy(&st->sc_bufq); return (0); } @@ -877,7 +877,7 @@ ststrategy(struct buf *bp) * at the end (a bit silly because we only have on user.. * (but it could fork())) */ - BUFQ_QUEUE(st->sc_bufq, bp); + bufq_queue(&st->sc_bufq, bp); /* * Tell the device to get going on the transfer if it's @@ -922,13 +922,13 @@ ststart(struct scsi_xfer *xs) !(sc_link->flags & SDEV_MEDIA_LOADED)) { /* make sure that one implies the other.. */ sc_link->flags &= ~SDEV_MEDIA_LOADED; - bufq_drain(st->sc_bufq); + bufq_drain(&st->sc_bufq); scsi_xs_put(xs); return; } for (;;) { - bp = BUFQ_DEQUEUE(st->sc_bufq); + bp = bufq_dequeue(&st->sc_bufq); if (bp == NULL) { scsi_xs_put(xs); return; @@ -1041,7 +1041,7 @@ ststart(struct scsi_xfer *xs) */ if (ISSET(st->flags, ST_WAITING)) CLR(st->flags, ST_WAITING); - else if (BUFQ_PEEK(st->sc_bufq)) + else if (bufq_peek(&st->sc_bufq)) scsi_xsh_add(&st->sc_xsh); } @@ -1060,7 +1060,7 @@ st_buf_done(struct scsi_xfer *xs) case XS_NO_CCB: /* The adapter is busy, requeue the buf and try it later. */ - BUFQ_REQUEUE(st->sc_bufq, bp); + bufq_requeue(&st->sc_bufq, bp); scsi_xs_put(xs); SET(st->flags, ST_WAITING); /* dont let ststart xsh_add */ timeout_add(&st->sc_timeout, 1); Index: sys/buf.h =================================================================== RCS file: /cvs/src/sys/sys/buf.h,v retrieving revision 1.70 diff -u -p -r1.70 buf.h --- sys/buf.h 30 Jun 2010 02:26:58 -0000 1.70 +++ sys/buf.h 25 Aug 2010 12:05:33 -0000 @@ -67,6 +67,8 @@ LIST_HEAD(workhead, worklist); #define BUFQ_DEFAULT BUFQ_DISKSORT #define BUFQ_HOWMANY 2 +struct bufq_impl; + struct bufq { SLIST_ENTRY(bufq) bufq_entries; struct mutex bufq_mtx; @@ -74,51 +76,40 @@ struct bufq { u_int bufq_outstanding; int bufq_stop; int bufq_type; + struct bufq_impl *bufq_impl; }; -struct buf *bufq_disksort_dequeue(struct bufq *, int); -void bufq_disksort_queue(struct bufq *, struct buf *); -void bufq_disksort_requeue(struct bufq *, struct buf *); -int bufq_disksort_init(struct bufq *); +int bufq_init(struct bufq *, int); +int bufq_switch(struct bufq *, int); +void bufq_destroy(struct bufq *); + +void bufq_queue(struct bufq *, struct buf *); +struct buf *bufq_dequeue(struct bufq *); +void bufq_requeue(struct bufq *, struct buf *); +int bufq_peek(struct bufq *); +void bufq_drain(struct bufq *); + +void bufq_done(struct bufq *, struct buf *); +void bufq_quiesce(void); +void bufq_restart(void); + +/* disksort */ struct bufq_disksort { struct buf *bqd_actf; struct buf **bqd_actb; }; -struct buf *bufq_fifo_dequeue(struct bufq *, int); -void bufq_fifo_queue(struct bufq *, struct buf *); -void bufq_fifo_requeue(struct bufq *, struct buf *); -int bufq_fifo_init(struct bufq *); +/* fifo */ SIMPLEQ_HEAD(bufq_fifo_head, buf); struct bufq_fifo { SIMPLEQ_ENTRY(buf) bqf_entries; }; +/* bufq link in struct buf */ union bufq_data { struct bufq_disksort bufq_data_disksort; struct bufq_fifo bufq_data_fifo; }; - -extern struct buf *(*bufq_dequeuev[BUFQ_HOWMANY])(struct bufq *, int); -extern void (*bufq_queuev[BUFQ_HOWMANY])(struct bufq *, struct buf *); -extern void (*bufq_requeuev[BUFQ_HOWMANY])(struct bufq *, struct buf *); - -#define BUFQ_QUEUE(_bufq, _bp) bufq_queue(_bufq, _bp) -#define BUFQ_REQUEUE(_bufq, _bp) bufq_requeue(_bufq, _bp) -#define BUFQ_DEQUEUE(_bufq) \ - bufq_dequeuev[(_bufq)->bufq_type](_bufq, 0) -#define BUFQ_PEEK(_bufq) \ - bufq_dequeuev[(_bufq)->bufq_type](_bufq, 1) - -struct bufq *bufq_init(int); -void bufq_queue(struct bufq *, struct buf *); -void bufq_requeue(struct bufq *, struct buf *); -void bufq_destroy(struct bufq *); -void bufq_drain(struct bufq *); -void bufq_done(struct bufq *, struct buf *); -void bufq_quiesce(void); -void bufq_restart(void); - /* * These are currently used only by the soft dependency code, hence