From: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
To: no-reply@sashiko.virtuozzo.com, andrey.zhadchenko@virtuozzo.com
Cc: devel@openvz.org
Subject: Re: [Devel] [PATCH hci-8.1 v6 5/6] dm-qcow2: keep the dirty bit of an image opened dirty
Date: Thu, 22 Oct 2026 15:15:23 +0200 [thread overview]
Message-ID: <6df7b1ef-d7a4-47ab-915b-6a3105b0a3c5@virtuozzo.com> (raw)
In-Reply-To: <010701a16392c2e0-655ce826-ac3f-4483-9e4d-3addcf673c40-000000@eu-central-1.amazonses.com>
>> @@ -676,7 +676,8 @@ int qcow2_set_image_file_features(struct qcow2 *qcow2, bool dirty)
>> if (kernel_sets_dirty_bit) {
>> if (dirty)
>> raw_hdr->incompatible_features |= dirty_mask;
>> - else
>> + else if (!(qcow2->hdr.incompatible_features &
>> + INCOMPATIBLE_FEATURES_DIRTY_BIT))
>> raw_hdr->incompatible_features &= ~dirty_mask;
>> }
> [Severity: Low]
> Can qcow2->hdr.incompatible_features tell the driver's own dirty bit apart
> from one left by a crash? The header is re-parsed from disk on every
> preresume:
>
> qcow2_preresume()
> qcow2_free_md_pages_all(tgt);
> ...
> qcow2_parse_metadata(ti, tgt);
> ...
> qcow2_set_image_file_features(tgt->top, true);
>
> If the kernel's bit is already on disk at parse time, the parsed header
> reports it as dirty-at-open, and every later call with dirty=false skips
> the clear.
>
> One way this happens is a failed clear in postsuspend:
>
> qcow2_postsuspend()
> ret = qcow2_set_image_file_features(qcow2, false);
> if (ret)
> QC_ERR(ti, "Can't set features");
>
> If the qcow2_rw_page_sync() write fails, the error is only logged and the
> bit stays on disk. The next qcow2_preresume() then reads it back as dirty
> at open, and the driver never clears it afterwards. A retried preresume
> without an intervening postsuspend could do the same.
>
> The new "Skip shrinking to used end of dirty image" branch in
> qcow2_truncate_preallocations() from patch 6 tests the same parsed-header
> bit. A falsely dirty image would also lose its tail truncation.
>
> The commit message does not mention this behaviour. Could it be described,
> or could the driver track separately whether the bit was set at open?
If the clear fails, the image stays dirty and gets checked before the next
open. That's safe, so I'll leave it.
> [Severity: Low]
> Does the new condition also leave a clean lower image marked dirty after a
> cancelled backward merge? In dm-qcow2-cmd.c, qcow2_merge_backward_work()
> calls:
>
> ret = qcow2_set_image_file_features(lower, true);
>
> This sets the bit on lower's raw header page and on disk only. lower->hdr
> is not updated.
>
> If a cancel arrives while the merge is in the WAIT_COMPLETION state,
> qcow2_merge_backward_cancel() does only this:
>
> } else if (tgt->backward_merge.state == BACKWARD_MERGE_WAIT_COMPLETION) {
> set_backward_merge_in_process(tgt, *tgt->backward_merge.pqcow2, false);
> tgt->backward_merge.state = BACKWARD_MERGE_STOPPED;
>
> It never clears lower's on-disk dirty bit. On the next resume,
> qcow2_preresume() re-parses every image in the chain, so
> lower->hdr.incompatible_features now contains the kernel's own bit.
>
> A later merge_backward start can then go one of two ways:
>
> - If it fails, the clear in qcow2_merge_backward_work() is skipped:
> ret2 = qcow2_set_image_file_features(lower, false);
>
> - If it completes, lower becomes the top image. The clear in
> qcow2_postsuspend() is skipped for the same reason:
> ret = qcow2_set_image_file_features(qcow2, false);
>
> Before this patch the second case cleared the bit. With this patch the
> image stays marked dirty on disk even though the kernel set the bit. The
> stale on-disk bit after cancel already existed, but it used to be cleared
> at the next postsuspend and is now permanent.
>
> Userspace may then run an unnecessary check, or refuse to open the image.
> The exposure needs kernel_sets_dirty_bit=1, a cancel in WAIT_COMPLETION, and
> a later merge or suspend cycle.
>
> Could the cancel path clear the bit, or could the driver record the open-time
> dirty state separately from the re-parsed header?
Will fix.
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
next prev parent reply other threads:[~2026-10-22 13:16 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 12:17 [Devel] [PATCH hci-8.1 v6 0/6] dm-qcow2: truncate unused tail of image on suspend Alexander Ivanov
2026-10-22 12:17 ` [Devel] [PATCH hci-8.1 v6 1/6] dm-qcow2: add qcow2_md_page_read_sync() helper Alexander Ivanov
2026-10-22 12:22 ` no-reply
2026-10-22 12:17 ` [Devel] [PATCH hci-8.1 v6 2/6] dm-qcow2: drop duplicate prefix from QC_ERR/QC_INFO messages Alexander Ivanov
2026-10-22 12:20 ` no-reply
2026-10-22 12:17 ` [Devel] [PATCH hci-8.1 v6 3/6] dm-qcow2: extend the file in place_r2() before linking the refblock Alexander Ivanov
2026-10-22 12:21 ` no-reply
2026-10-22 12:17 ` [Devel] [PATCH hci-8.1 v6 4/6] dm-qcow2: complete wbd before ending the data qio Alexander Ivanov
2026-10-22 12:23 ` no-reply
2026-10-22 12:17 ` [Devel] [PATCH hci-8.1 v6 5/6] dm-qcow2: keep the dirty bit of an image opened dirty Alexander Ivanov
2026-10-22 12:25 ` no-reply
2026-10-22 13:15 ` Alexander Ivanov [this message]
2026-10-22 12:17 ` [Devel] [PATCH hci-8.1 v6 6/6] dm-qcow2: truncate unused tail of image on suspend Alexander Ivanov
2026-10-22 12:29 ` no-reply
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=6df7b1ef-d7a4-47ab-915b-6a3105b0a3c5@virtuozzo.com \
--to=alexander.ivanov@virtuozzo.com \
--cc=andrey.zhadchenko@virtuozzo.com \
--cc=devel@openvz.org \
--cc=no-reply@sashiko.virtuozzo.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox