All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: no-reply@sashiko.virtuozzo.com
To: "Denis V. Lunev" <den@openvz.org>, svt-core@virtuozzo.com
Cc: den@virtuozzo.com, andrey.drobyshev@virtuozzo.com
Subject: Re: [PATCH hci-8.0 8/9] block/backup: pre-fill zero_bitmap for full/bitmap #VSTOR-134085
Date: Wed, 30 Sep 2026 11:33:04 +0000	[thread overview]
Message-ID: <010701a0f216edca-98549d2a-a526-44b9-8593-2fab29f4ed9d-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20260930111739.3866427-9-den@openvz.org>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] block: block_copy_calculate_zero_bitmap() can return count 0 forever, hanging the scan
- [Low] block/backup: commit message says full/bitmap but only sync=bitmap uses the new scan
--

commit 252a85c484652c4a95f8a77f49b08e8150b81585
Author: Denis V. Lunev <den@openvz.org>

block/backup: pre-fill zero_bitmap for full/bitmap #VSTOR-134085

This commit adds block_copy_calculate_zero_bitmap() and folds the
up-front source scan into a new backup_scan_source(). The scan now
pre-fills zero_bitmap for sync=bitmap as well as sync=top. sync=full
stays on block_copy_reset_unallocated(), and sync=none keeps the
per-task query.

> block/backup: pre-fill zero_bitmap for full/bitmap #VSTOR-134085

This isn't a code bug, but the subject line and body say that both FULL
and BITMAP get the new up-front scan. Two quoted portions of the commit
message read this way:

  "Add block_copy_calculate_zero_bitmap(), driven one query at a time
  from backup_scan_source() ..."
  "FULL and BITMAP know their complete copy_bitmap before copying
  starts"

In the code, sync=full still takes the block_copy_reset_unallocated()
path, and only sync=bitmap calls block_copy_calculate_zero_bitmap(). The
trailing paragraph of the message says so itself: "sync=full already
runs block_copy_reset_unallocated() ... so it stays on that path and only
sync=bitmap moves to block_copy_calculate_zero_bitmap()".

That leaves the message contradicting itself. It also carries the
downstream "hci-8.0:" tag. Could the subject and body be reworded to
match the code?

[Severity: Low]

> diff --git a/block/backup.c b/block/backup.c
> --- a/block/backup.c
> +++ b/block/backup.c

[ ... ]

> +static int coroutine_fn backup_scan_source(BackupBlockJob *s)
>  {
[ ... ]
> +    for (offset = 0; offset < s->len; offset += count) {
> +        if (job_is_cancelled(job)) {
> +            return -ECANCELED;
> +        }
> +
> +        job_pause_point(job);
[ ... ]
> +        bdrv_graph_co_rdlock();
> +        if (skip) {
> +            ret = block_copy_reset_unallocated(s->bcs, offset, &count);
> +        } else {
> +            block_copy_calculate_zero_bitmap(s->bcs, offset, &cached_end,
> +                                             &count);
> +        }
> +        bdrv_graph_co_rdunlock();

> diff --git a/block/block-copy.c b/block/block-copy.c
> --- a/block/block-copy.c
> +++ b/block/block-copy.c

[ ... ]

> +    if (*cached_end < dirty_end) {
> +        int64_t clusters;
> +        int64_t query_offset = MAX(dirty_offset, *cached_end);
> +        int ret = block_copy_is_cluster_allocated(s, query_offset, &clusters);
> +
> +        if (ret >= 0) {
> +            *cached_end = query_offset + clusters * s->cluster_size;
> +        } else {
> +            /* Best-effort: leave this area unmarked; it copies as data. */
> +            *cached_end = dirty_end;
> +        }
> +    }
> +
> +    /* 0 if the query above didn't yet reach dirty_end: try again next call. */
> +    *count = *cached_end >= dirty_end ? dirty_end - offset : 0;
> +}

Can block_copy_calculate_zero_bitmap() return *count == 0 forever for
sync=bitmap?

block_copy_is_cluster_allocated() sets *pnum = DIV_ROUND_UP(total_count,
cluster_size). That is 0 when bdrv_co_block_status_above() returns
count == 0, for example at or beyond the source EOF. The function still
returns ret >= 0 in that case, since it has an explicit "count == 0"
branch.

If that happens, the ret >= 0 branch above sets
  *cached_end = query_offset + 0 * s->cluster_size;
which is still below dirty_end. *count then stays 0.

In backup_scan_source(), "offset += count" does not advance, so the next
iteration repeats the identical query. job_pause_point() and
job_is_cancelled() do not yield unless the job is paused or cancelled.
That would leave the scan spinning without yielding in the job's
AioContext.

I could not confirm that s->len can exceed the real source length, for
example if the source shrinks during the job, so this may be hard to
reach.

The same "offset += count" shape already exists in
block_copy_reset_unallocated() for top/full. However, the sync=bitmap
path through block_copy_calculate_zero_bitmap() is new with this patch.
The later patch "block/block-copy: coalesce write-zeroes tasks" does not
touch this scan.

Would it make sense to force progress, for example by treating
clusters == 0 like the error path (cached_end = dirty_end), or by
clamping clusters to at least 1?

[Severity: Medium]

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20260930111739.3866427-1-den@openvz.org?part=8

  reply	other threads:[~2026-09-30 11:33 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 11:17 [PATCH hci-8.0 0/9] block: cheaper zero handling in backup and commit #VSTOR-134085 Denis V. Lunev
2026-09-30 11:17 ` [PATCH hci-8.0 1/9] block/commit: pass BDRV_WANT_PRECISE to block-status #VSTOR-134085 Denis V. Lunev
2026-09-30 11:20   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 2/9] iotests/040: cover large and fragmented commit runs #VSTOR-134085 Denis V. Lunev
2026-09-30 11:19   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 3/9] block/commit: batch block-status queries #VSTOR-134085 Denis V. Lunev
2026-09-30 11:21   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 4/9] iotests/124: cover backup of zero clusters and holes #VSTOR-134085 Denis V. Lunev
2026-09-30 11:31   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 5/9] block/block-copy: don't reserve memory for zero tasks #VSTOR-134085 Denis V. Lunev
2026-09-30 11:22   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 6/9] block/block-copy: extract block_copy_set_task_method() #VSTOR-134085 Denis V. Lunev
2026-09-30 11:22   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 7/9] block/block-copy: track known-zero source clusters #VSTOR-134085 Denis V. Lunev
2026-09-30 11:30   ` no-reply
2026-09-30 11:17 ` [PATCH hci-8.0 8/9] block/backup: pre-fill zero_bitmap for full/bitmap #VSTOR-134085 Denis V. Lunev
2026-09-30 11:33   ` no-reply [this message]
2026-09-30 11:17 ` [PATCH hci-8.0 9/9] block/block-copy: coalesce write-zeroes tasks #VSTOR-134085 Denis V. Lunev
2026-09-30 11:34   ` no-reply
2026-09-30 12:49 ` [PATCH hci-8.0 0/9] block: cheaper zero handling in backup and commit #VSTOR-134085 Andrey Drobyshev

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=010701a0f216edca-98549d2a-a526-44b9-8593-2fab29f4ed9d-000000@eu-central-1.amazonses.com \
    --to=no-reply@sashiko.virtuozzo.com \
    --cc=andrey.drobyshev@virtuozzo.com \
    --cc=den@openvz.org \
    --cc=den@virtuozzo.com \
    --cc=svt-core@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 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.