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);
}