All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Alberto Garcia <berto@igalia.com>
Cc: qemu-devel@nongnu.org, qemu-block@nongnu.org,
	Hanna Czenczek <hreitz@redhat.com>,
	Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Subject: Re: [PATCH] qemu-img rebase: don't exceed IO_BUF_SIZE in one operation
Date: Fri, 7 Nov 2025 13:31:25 +0100	[thread overview]
Message-ID: <aQ3mnR1RJiaPau6A@redhat.com> (raw)
In-Reply-To: <20251107091834.383781-1-berto@igalia.com>

Am 07.11.2025 um 10:18 hat Alberto Garcia geschrieben:
> During a rebase operation data is copied from the backing chain into
> the target image using a loop, and each iteration looks for a
> contiguous region of allocated data of at most IO_BUF_SIZE (2 MB).
> 
> Once that region is found, and in order to avoid partial writes, its
> boundaries are extended so they are aligned to the (sub)clusters of
> the target image (see commit 12df580b).
> 
> This operation can however result in a region that exceeds the maximum
> allowed IO_BUF_SIZE, crashing qemu-img.
> 
> This can be easily reproduced when the source image has a smaller
> cluster size than the target image:
> 
> base <- int <- active
> 
> $ qemu-img create -f qcow2 base.qcow2 4M
> $ qemu-img create -f qcow2 -F qcow2 -b base.qcow2 -o cluster_size=1M int.qcow2
> $ qemu-img create -f qcow2 -F qcow2 -b int.qcow2  -o cluster_size=2M active.qcow2
> $ qemu-io -c "write -P 0xff 1M 2M" int.qcow2
> $ qemu-img rebase -F qcow2 -b base.qcow2 active.qcow2
> qemu-img: qemu-img.c:4102: img_rebase: Assertion `written + pnum <= IO_BUF_SIZE' failed.
> Aborted
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3174
> Fixes: 12df580b3b7f ("qemu-img: rebase: avoid unnecessary COW operations")
> Signed-off-by: Alberto Garcia <berto@igalia.com>
> ---
>  qemu-img.c                 |  2 +-
>  tests/qemu-iotests/024     | 46 ++++++++++++++++++++++++++++++++++++++
>  tests/qemu-iotests/024.out | 27 ++++++++++++++++++++++
>  3 files changed, 74 insertions(+), 1 deletion(-)
> 
> diff --git a/qemu-img.c b/qemu-img.c
> index a7791896c1..454da88c73 100644
> --- a/qemu-img.c
> +++ b/qemu-img.c
> @@ -4081,7 +4081,7 @@ static int img_rebase(const img_cmd_t *ccmd, int argc, char **argv)
>              n += offset - QEMU_ALIGN_DOWN(offset, write_align);
>              offset = QEMU_ALIGN_DOWN(offset, write_align);
>              n += QEMU_ALIGN_UP(offset + n, write_align) - (offset + n);
> -            n = MIN(n, size - offset);
> +            n = MIN(n, MIN(size - offset, IO_BUF_SIZE));
>              assert(!bdrv_is_allocated(unfiltered_bs, offset, n, &n_alloc) &&
>                     n_alloc == n);

The fix itself looks ok.

> +$QEMU_IMG rebase -b "$BASE_NEW" -F $IMGFMT "$OVERLAY"
> +
> +echo "Verifying the data"
> +echo
> +
> +$QEMU_IO "$OVERLAY" -c "read -P 0x00  0 1M" | _filter_qemu_io
> +$QEMU_IO "$OVERLAY" -c "read -P 0xff 1M 2M" | _filter_qemu_io
> +$QEMU_IO "$OVERLAY" -c "read -P 0x00 2M 1M" | _filter_qemu_io

Here you mean 3M instead of 2M...

> +Verifying the data
> +
> +read 1048576/1048576 bytes at offset 0
> +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> +read 2097152/2097152 bytes at offset 1048576
> +2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> +Pattern verification failed at offset 2097152, 1048576 bytes

...which then fixes this failure.

> +read 1048576/1048576 bytes at offset 2097152
> +1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> +Offset          Length          File
> +0               0x400000        TEST_DIR/subdir/t.IMGFMT
> +
>  *** done

Thanks, I've fixed it up as below and applied the patch to my block
branch.

Kevin

diff --git a/tests/qemu-iotests/024 b/tests/qemu-iotests/024
index b59d825b42..021169b4a1 100755
--- a/tests/qemu-iotests/024
+++ b/tests/qemu-iotests/024
@@ -357,7 +357,7 @@ echo

 $QEMU_IO "$OVERLAY" -c "read -P 0x00  0 1M" | _filter_qemu_io
 $QEMU_IO "$OVERLAY" -c "read -P 0xff 1M 2M" | _filter_qemu_io
-$QEMU_IO "$OVERLAY" -c "read -P 0x00 2M 1M" | _filter_qemu_io
+$QEMU_IO "$OVERLAY" -c "read -P 0x00 3M 1M" | _filter_qemu_io

 $QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map

diff --git a/tests/qemu-iotests/024.out b/tests/qemu-iotests/024.out
index cc18ee0290..1b7522ba71 100644
--- a/tests/qemu-iotests/024.out
+++ b/tests/qemu-iotests/024.out
@@ -264,8 +264,7 @@ read 1048576/1048576 bytes at offset 0
 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 read 2097152/2097152 bytes at offset 1048576
 2 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
-Pattern verification failed at offset 2097152, 1048576 bytes
-read 1048576/1048576 bytes at offset 2097152
+read 1048576/1048576 bytes at offset 3145728
 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 Offset          Length          File
 0               0x400000        TEST_DIR/subdir/t.IMGFMT



  reply	other threads:[~2025-11-07 12:32 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-07  9:18 [PATCH] qemu-img rebase: don't exceed IO_BUF_SIZE in one operation Alberto Garcia
2025-11-07 12:31 ` Kevin Wolf [this message]
2025-11-07 12:33   ` Kevin Wolf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aQ3mnR1RJiaPau6A@redhat.com \
    --to=kwolf@redhat.com \
    --cc=andrey.drobyshev@virtuozzo.com \
    --cc=berto@igalia.com \
    --cc=hreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.