[Devel] [PATCH RHEL9 COMMIT] dm-qcow2: fix qcow2 decompression

Konstantin Khorenko khorenko at virtuozzo.com
Wed Feb 19 20:02:49 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.16
------>
commit be70e9b1c7ec7ad394195f9793cfaf07d9097be7
Author: Alexander Atanasov <alexander.atanasov at virtuozzo.com>
Date:   Wed Feb 19 12:47:31 2025 +0200

    dm-qcow2: fix qcow2 decompression
    
    Two problems - using wrong size type:
    
     - process_compressed_read used blk_status_t for ret which is u8
       so it can not process negative error codes and larger sizes
       properly - fix this by changing it to int
    
     - decompression fails for images with size larger than 2GB
       due to wrong return type of parse_compressed_l2 - the calculations
       are performed in properly in u64 type but on return result is truncated
       Fix this by changing the type to loff_t.
    
    Pasha's note: due to the way pos is calculated it can't be more than long
    long max, so this conversion should not overflow (as offset_bits <= 62).
       entry &= ~L2_COMPRESSED_CLUSTER;     // 63rd bit
       entry &= ~LX_REFCOUNT_EXACTLY_ONE;   // 62nd bit
    
    Fixes: 7f5c7e6dbd9b ("dm-qcow2: Introduce driver to create block devices
    over QCOW2 files")
    
    https://virtuozzo.atlassian.net/browse/VSTOR-98868
    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
---
 drivers/md/dm-qcow2-map.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-qcow2-map.c b/drivers/md/dm-qcow2-map.c
index 54bb8bd713be..ccc8d4484049 100644
--- a/drivers/md/dm-qcow2-map.c
+++ b/drivers/md/dm-qcow2-map.c
@@ -1729,7 +1729,7 @@ static loff_t parse_l1(struct qcow2 *qcow2, struct qcow2_map *map,
 	return ret;
 }
 
-static int parse_compressed_l2(struct qcow2 *qcow2, struct qcow2_map *map,
+static loff_t parse_compressed_l2(struct qcow2 *qcow2, struct qcow2_map *map,
 			       struct qio **qio, bool write, u64 entry)
 {
 	u8 offset_bits = 62 - (qcow2->hdr.cluster_bits - 8);
@@ -3660,7 +3660,7 @@ static void process_compressed_read(struct qcow2 *qcow2, struct list_head *read_
 {
 	struct qcow2_bvec *qvec;
 	struct qio_ext *ext;
-	blk_status_t ret;
+	int ret;
 	void *buf = NULL, *arg;
 	struct qio *qio;
 	bool for_cow;
@@ -3698,7 +3698,7 @@ static void process_compressed_read(struct qcow2 *qcow2, struct list_head *read_
 
 		ret = extract_one_compressed(qcow2, buf, qvec,
 				    ext->zdata_off, qio->ret, arg);
-		if (ret)
+		if (ret <= 0)
 			goto err;
 
 		for_cow = op_is_write(qio->bi_op);


More information about the Devel mailing list