[Devel] [PATCH RHEL9 COMMIT] dm-qcow2: only use inline bvec if iteration is valid

Konstantin Khorenko khorenko at virtuozzo.com
Thu Jan 9 22:17:55 MSK 2025


The commit is pushed to "branch-rh9-5.14.0-427.44.1.vz9.80.x-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh9-5.14.0-427.44.1.vz9.80.3
------>
commit f879e056c4a69cb57e6fe6ae1edc091ebc2982c2
Author: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
Date:   Tue Dec 17 12:34:44 2024 +0200

    dm-qcow2: only use inline bvec if iteration is valid
    
    In some cases qcow2 is passed requests without bvec set and
    zero bi_size - for such requests qcow2 resorts to inline bvecs
    which in that case are invalid.
    
    To address this:
     - Check if bi_size is not zero, and only then use the inline bvecs.
     - Properly count number of segments in a NULL bvec.
     - Add warn on to catch if we have a request with NULL bvec and
       non-zero bi_size.
    
    https://virtuozzo.atlassian.net/browse/PSBM-159903
    Signed-off-by: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
    
    Feature: dm-qcow2: block device over QCOW2 files driver
    
    khorenko@: so after that patch in prepare_one_embedded_qio() we may have
    qio->bi_io_vec = bvec = NULL in case !bvec && !rq->bio->bi_iter.bi_size,
    but such requests (these are control requests, discards for example)
    should not get into __submit_rw_mapped(), thus the WARN_ON() is there.
---
 drivers/md/dm-qcow2-map.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index 112f6dde44af..54bb8bd713be 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -308,6 +308,9 @@ static unsigned int qio_nr_segs(struct qio *qio)
 	struct bvec_iter iter;
 	struct bio_vec bv;
 
+	if (!qio->bi_io_vec)
+		return 0;
+
 	qcow2_for_each_bvec(iter, bv, qio->bi_iter, qio->bi_io_vec)
 		nr_segs++;
 
@@ -1248,6 +1251,7 @@ static void __submit_rw_mapped(struct qcow2 *qcow2, struct qio *qio, u32 nr_segs
 	bvec = __bvec_iter_bvec(qio->bi_io_vec, qio->bi_iter);
 	pos = to_bytes(qio->bi_iter.bi_sector);
 
+	WARN_ON(qio->bi_iter.bi_size && !bvec);
 	iov_iter_bvec(&iter, rw, bvec, nr_segs, qio->bi_iter.bi_size);
 	iter.iov_offset = qio->bi_iter.bi_bvec_done;
 
@@ -3538,7 +3542,7 @@ static void prepare_one_embedded_qio(struct qcow2 *qcow2, struct qio *qio,
 	} else {
 		/* Single bio already provides bvec array */
 		bvec = rq->bio->bi_io_vec;
-		if (!bvec) {
+		if (!bvec && rq->bio->bi_iter.bi_size) {
 			bvec = rq->bio->bi_inline_vecs;
 			if (unlikely(!bvec)) {
 				QC_ERR(qcow2->tgt->ti, "Expecting inline bvec");


More information about the Devel mailing list