All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Markus Armbruster <armbru@redhat.com>
Cc: "Denis V. Lunev" <den@virtuozzo.com>,
	"Denis V. Lunev" <den@openvz.org>,
	qemu-devel@nongnu.org, qemu-block@nongnu.org,
	Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
	Hanna Reitz <hreitz@redhat.com>, Eric Blake <eblake@redhat.com>,
	qemu-stable@nongnu.org
Subject: Re: [PATCH v4 5/5] qcow2: repair a dirty image when it becomes writable
Date: Tue, 6 Oct 2026 12:30:26 +0200	[thread overview]
Message-ID: <asTNwqM03qYY8eUb@redhat.com> (raw)
In-Reply-To: <87fqzzgc13.fsf@pond.sub.org>

Am 27.08.2026 um 11:15 hat Markus Armbruster geschrieben:
> "Denis V. Lunev" <den@virtuozzo.com> writes:
> 
> > On 8/26/26 17:24, Markus Armbruster wrote:
> >> "Denis V. Lunev" <den@virtuozzo.com> writes:
> >>
> >>> On 8/25/26 11:37, Markus Armbruster wrote:
> >>>> "Denis V. Lunev" <den@openvz.org> writes:
> >>>>
> >>>>> From: Denis V. Lunev <den@openvz.org>
> >>>>>
> >>>>> A dirty image must be repaired before anything allocates a cluster in
> >>>>> it. qcow2_do_open() does that, but only for a node that is writable
> >>>>> from the start. A node opened read-only skips it, and nothing revisits
> >>>>> the question once that node becomes writable, which block-commit does
> >>>>> routinely: commit_active_start() and commit_start() reopen the base
> >>>>> read-write for the duration of the job.
> >>>>>
> >>>>> With lazy refcounts the on-disk refcount block then still accounts for
> >>>>> the metadata clusters only, so the allocator restarts at the front of
> >>>>> the image and hands out clusters that L2 entries point at. Two guest
> >>>>> offsets end up sharing one host cluster. Nothing fails, the corrupt bit
> >>>>> stays clear, and a clean close clears the dirty bit, so no later open
> >>>>> repairs the image either. The bit also stays set for the whole writable
> >>>>> session, so a node which is merely writable says nothing.
> >>>>>
> >>>>> Refusing the reopen instead is simpler and keeps it atomic, but it
> >>>>> leaves nowhere to go: the base belongs to a chain the VM has open, so
> >>>>> the qemu-img check -r such an error would ask for cannot take the write
> >>>>> lock it needs. The repair does the trick in most cases anyway.
> >>>>>
> >>>>> Do the repair in qcow2_reopen_commit_post(), the earliest point where
> >>>>> the node is writable. An inactive node is skipped: bdrv_activate() calls
> >>>>> qcow2_do_open() again through qcow2_co_invalidate_cache().
> >>>>>
> >>>>> commit_post cannot reject the reopen, so a failed repair takes the
> >>>>> driver away from the node instead, which is what stops writes from
> >>>>> aliasing live clusters. qcow2_signal_corruption() does that as well,
> >>>>> but it also sends BLOCK_IMAGE_CORRUPTED and sets the corrupt bit,
> >>>>> which qcow2_do_open() honours by refusing every later read-write open.
> >>>>> The image is dirty and unrepaired, not corrupt, and qemu-img check -r
> >>>>> still fixes it, so neither belongs here. Return the error and skip
> >>>>> the bitmaps.
> >>>>>
> >>>>> Signed-off-by: Denis V. Lunev <den@openvz.org>
> >>>>> Reviewed-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
> >>>>> CC: Kevin Wolf <kwolf@redhat.com>
> >>>>> CC: Hanna Reitz <hreitz@redhat.com>
> >>>>> CC: Eric Blake <eblake@redhat.com>
> >>>>> CC: Markus Armbruster <armbru@redhat.com>
> >>>>> CC: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
> >>>>> Cc: qemu-stable@nongnu.org
> >>>> [...]
> >>>>
> >>>>> diff --git a/qapi/block-core.json b/qapi/block-core.json
> >>>>> index 199efc1e00..940249a5e5 100644
> >>>>> --- a/qapi/block-core.json
> >>>>> +++ b/qapi/block-core.json
> >>>>> @@ -1852,6 +1852,9 @@
> >>>>   ##
> >>>>   # @change-backing-file:
> >>>>   #
> >>>>   # Change the backing file in the image file metadata.  This does not
> >>>>   # cause QEMU to reopen the image file to reparse the backing filename
> >>>>   # (it may, however, perform a reopen to change permissions from r/o ->
> >>>>>  # r/w -> r/o, if needed).  The new backing file string is written into
> >>>>>  # the image file metadata, and the QEMU internal strings are updated.
> >>>>>  #
> >>>>> +# A dirty qcow2 image is repaired during that reopen, which blocks
> >>>>> +# other requests and can fail the command.
> >>>>
> >>>> Pardon my ignorance: what makes a qcow2 image dirty?
> >>> usual obvious reasons are SIGKILL to qemu process (f.e. from OOM)
> >>> or node crash.
> >>
> >> So, you have to do some cleaning work before you can use it again, just
> >> like a dirty filesystem.  Correct?
> > Correct. QEMU allows right now to open dirty images in read-only
> > mode and it is OK to be used until we switch to RW. In this
> > case real write to metadata corrupts image.
> 
> Feels... adventurous?

Not really. This one is fairly harmless.

The dirty flag is generally set in the context of lazy refcounts, i.e.
the image will have refcounts that are inconsistent with the mappings.
The user explicitly asked for this and the mapping is authoritative in
this case. Repairing simply means updating the refcounts to match the
mapping again so that the next cluster allocation can work correctly.

If the image is accessed read-only, you obviously can't repair the image
because that would mean writing to the refcount blocks, but also you
really don't care about refcounts at all when you're only reading from
the image. Refcounts are only important for cluster allocation.

There is another flag QCOW2_INCOMPAT_CORRUPT that actually is a bit
adventurous to open even read-only because it means that something is
seriously wrong with the image. We still allow it, and I think the
reasoning for that was that it can be the difference between "all data
lost" and "okay, some parts of the image are broken, but we can at least
copy out those gigabytes of data that are still accessible".

Kevin



  parent reply	other threads:[~2026-10-07  8:46 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-24 13:37 [PATCH v4 0/5] qcow2: silent corruption when a dirty image becomes writable Denis V. Lunev
2026-08-24 13:37 ` [PATCH v4 1/5] qcow2: do not clear the dirty bit when reopening a read-only node Denis V. Lunev
2026-10-06 10:01   ` Kevin Wolf
2026-08-24 13:37 ` [PATCH v4 2/5] block: reject a reopen of an unusable node instead of crashing Denis V. Lunev
2026-10-06 10:02   ` Kevin Wolf
2026-08-24 13:37 ` [PATCH v4 3/5] block: let bdrv_reopen_commit_post() report a failure Denis V. Lunev
2026-10-06 12:12   ` Kevin Wolf
2026-08-24 13:37 ` [PATCH v4 4/5] block: remember the flags a reopen starts from Denis V. Lunev
2026-08-24 13:37 ` [PATCH v4 5/5] qcow2: repair a dirty image when it becomes writable Denis V. Lunev
2026-08-25  9:37   ` Markus Armbruster
2026-08-26 13:49     ` Denis V. Lunev
2026-08-26 15:24       ` Markus Armbruster
2026-08-26 16:37         ` Denis V. Lunev
2026-08-27  9:15           ` Markus Armbruster
2026-08-27 16:06             ` Denis V. Lunev
2026-08-31 12:31               ` Markus Armbruster
2026-08-31 19:01                 ` Denis V. Lunev
2026-08-31 22:03                   ` Denis V. Lunev
2026-10-06 10:30             ` Kevin Wolf [this message]
2026-09-21 19:40 ` [PATCH v4 0/5] qcow2: silent corruption when a dirty image " Denis V. Lunev
2026-10-05  8:57 ` Denis V. Lunev

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=asTNwqM03qYY8eUb@redhat.com \
    --to=kwolf@redhat.com \
    --cc=andrey.drobyshev@virtuozzo.com \
    --cc=armbru@redhat.com \
    --cc=den@openvz.org \
    --cc=den@virtuozzo.com \
    --cc=eblake@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@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.