git: 75549de770df - main - vtblk: Fix dumping

From: Colin Percival <cperciva_at_FreeBSD.org>
Date: Thu, 03 Nov 2022 07:52:47 UTC
The branch main has been updated by cperciva:

URL: https://cgit.FreeBSD.org/src/commit/?id=75549de770df470b024c92ff093009c6987b40fd

commit 75549de770df470b024c92ff093009c6987b40fd
Author:     Colin Percival <cperciva@FreeBSD.org>
AuthorDate: 2022-11-03 01:55:12 +0000
Commit:     Colin Percival <cperciva@FreeBSD.org>
CommitDate: 2022-11-03 07:52:43 +0000

    vtblk: Fix dumping
    
    Now that vtblk uses busdma, it keeps important information inside its
    request structures.  The functions used for kernel dumps synthesize
    their own request structures rather than using structures initialized
    with the necessary bits for busdma.
    
    Add busdma-bypass paths.  Since dumping writes contiguous blocks of
    physical memory, vtblk doesn't need busdma in that case.
    
    Reported by:    glebius
    Tested by:      glebius
    Differential Revision:  https://reviews.freebsd.org/D37243
---
 sys/dev/virtio/block/virtio_blk.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c
index b3b3a6dd1aed..41229bb6da2c 100644
--- a/sys/dev/virtio/block/virtio_blk.c
+++ b/sys/dev/virtio/block/virtio_blk.c
@@ -992,9 +992,12 @@ vtblk_request_execute(struct vtblk_request *req, int flags)
 
 	/*
 	 * Call via bus_dmamap_load_bio or directly depending on whether we
-	 * have a buffer we need to map.
+	 * have a buffer we need to map.  If we don't have a busdma map,
+	 * try to perform the I/O directly and hope that it works (this will
+	 * happen when dumping).
 	 */
-	if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
+	if ((req->vbr_mapp != NULL) &&
+	    (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE)) {
 		error = bus_dmamap_load_bio(sc->vtblk_dmat, req->vbr_mapp,
 		    req->vbr_bp, vtblk_request_execute_cb, req, flags);
 		if (error == EINPROGRESS) {
@@ -1080,6 +1083,15 @@ vtblk_request_execute_cb(void * callback_arg, bus_dma_segment_t * segs,
 			}
 		}
 
+		/* Special handling for dump, which bypasses busdma. */
+		if (req->vbr_mapp == NULL) {
+			error = sglist_append_bio(sg, bp);
+			if (error || sg->sg_nseg == sg->sg_maxseg) {
+				panic("%s: bio %p data buffer too big %d",
+				    __func__, bp, error);
+			}
+		}
+
 		/* BIO_READ means the host writes into our buffer. */
 		if (bp->bio_cmd == BIO_READ)
 			writable = sg->sg_nseg - 1;
@@ -1130,7 +1142,7 @@ vtblk_request_execute_cb(void * callback_arg, bus_dma_segment_t * segs,
 		virtqueue_notify(vq);
 
 out:
-	if (error)
+	if (error && (req->vbr_mapp != NULL))
 		bus_dmamap_unload(sc->vtblk_dmat, req->vbr_mapp);
 out1:
 	if (error && req->vbr_requeue_on_error)
@@ -1505,6 +1517,7 @@ vtblk_dump_write(struct vtblk_softc *sc, void *virtual, off_t offset,
 	struct vtblk_request *req;
 
 	req = &sc->vtblk_dump_request;
+	req->vbr_sc = sc;
 	req->vbr_ack = -1;
 	req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT);
 	req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1);
@@ -1527,6 +1540,7 @@ vtblk_dump_flush(struct vtblk_softc *sc)
 	struct vtblk_request *req;
 
 	req = &sc->vtblk_dump_request;
+	req->vbr_sc = sc;
 	req->vbr_ack = -1;
 	req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH);
 	req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1);