git: b1dd06703274 - main - vtblk: Invoke busdma completion callbacks when polling
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 04 Jul 2024 14:27:42 UTC
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=b1dd067032747c12ae237d2f7aeed6d81285c121 commit b1dd067032747c12ae237d2f7aeed6d81285c121 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2024-07-04 14:15:33 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2024-07-04 14:15:33 +0000 vtblk: Invoke busdma completion callbacks when polling vtblk_poll_request() is used for kernel dumps and for fetching the block device's identifier string during device probing. In the latter case, it was not calling bus_dmamap_sync() after completing the I/O, but this is required in general. Thus: - Factor out per-request code from vtblk_queue_completed(). - Use it in vtblk_poll_request() once virtqueue_poll() finishes. - While here, assert that virtqueue_poll() returns the request that we expect. Reported by: KMSAN Fixes: 782105f7c898 ("vtblk: Use busdma") Reviewed by: cperciva, imp Sponsored by: Klara, Inc. Sponsored by: Juniper Networks, Inc. Differential Revision: https://reviews.freebsd.org/D45665 --- sys/dev/virtio/block/virtio_blk.c | 66 +++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c index d7fa903936a1..d3eb3cf97831 100644 --- a/sys/dev/virtio/block/virtio_blk.c +++ b/sys/dev/virtio/block/virtio_blk.c @@ -1177,6 +1177,35 @@ vtblk_request_error(struct vtblk_request *req) return (error); } +static struct bio * +vtblk_queue_complete_one(struct vtblk_softc *sc, struct vtblk_request *req) +{ + struct bio *bp; + + if (sc->vtblk_req_ordered != NULL) { + MPASS(sc->vtblk_req_ordered == req); + sc->vtblk_req_ordered = NULL; + } + + bp = req->vbr_bp; + if (req->vbr_mapp != NULL) { + switch (bp->bio_cmd) { + case BIO_READ: + bus_dmamap_sync(sc->vtblk_dmat, req->vbr_mapp, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->vtblk_dmat, req->vbr_mapp); + break; + case BIO_WRITE: + bus_dmamap_sync(sc->vtblk_dmat, req->vbr_mapp, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->vtblk_dmat, req->vbr_mapp); + break; + } + } + bp->bio_error = vtblk_request_error(req); + return (bp); +} + static void vtblk_queue_completed(struct vtblk_softc *sc, struct bio_queue *queue) { @@ -1184,31 +1213,9 @@ vtblk_queue_completed(struct vtblk_softc *sc, struct bio_queue *queue) struct bio *bp; while ((req = virtqueue_dequeue(sc->vtblk_vq, NULL)) != NULL) { - if (sc->vtblk_req_ordered != NULL) { - MPASS(sc->vtblk_req_ordered == req); - sc->vtblk_req_ordered = NULL; - } + bp = vtblk_queue_complete_one(sc, req); - bp = req->vbr_bp; - if (req->vbr_mapp != NULL) { - switch (bp->bio_cmd) { - case BIO_READ: - bus_dmamap_sync(sc->vtblk_dmat, req->vbr_mapp, - BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->vtblk_dmat, - req->vbr_mapp); - break; - case BIO_WRITE: - bus_dmamap_sync(sc->vtblk_dmat, req->vbr_mapp, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->vtblk_dmat, - req->vbr_mapp); - break; - } - } - bp->bio_error = vtblk_request_error(req); TAILQ_INSERT_TAIL(queue, bp, bio_queue); - vtblk_request_enqueue(sc, req); } } @@ -1412,8 +1419,6 @@ vtblk_ident(struct vtblk_softc *sc) error = vtblk_poll_request(sc, req); VTBLK_UNLOCK(sc); - vtblk_request_enqueue(sc, req); - if (error) { device_printf(sc->vtblk_dev, "error getting device identifier: %d\n", error); @@ -1423,7 +1428,9 @@ vtblk_ident(struct vtblk_softc *sc) static int vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req) { + struct vtblk_request *req1 __diagused; struct virtqueue *vq; + struct bio *bp; int error; vq = sc->vtblk_vq; @@ -1436,13 +1443,18 @@ vtblk_poll_request(struct vtblk_softc *sc, struct vtblk_request *req) return (error); virtqueue_notify(vq); - virtqueue_poll(vq, NULL); + req1 = virtqueue_poll(vq, NULL); + KASSERT(req == req1, + ("%s: polling completed %p not %p", __func__, req1, req)); - error = vtblk_request_error(req); + bp = vtblk_queue_complete_one(sc, req); + error = bp->bio_error; if (error && bootverbose) { device_printf(sc->vtblk_dev, "%s: IO error: %d\n", __func__, error); } + if (req != &sc->vtblk_dump_request) + vtblk_request_enqueue(sc, req); return (error); }