On Sun, Aug 29, 2010 at 10:26:14PM +1000, David Gwynne wrote: > 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?
I like this a lot, and I will do some testing on st and cd at least as soon as I can rebuild the appropriate box. .... Ken > > 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