Commit 404980ebb0 for qemu.org
commit 404980ebb0cbbd9c6d89ffb03065e5fc481e695f
Author: Denis V. Lunev <den@openvz.org>
Date: Fri Oct 30 02:06:10 2026 +0100
block/block-copy: replace zero_bitmap_valid with scan_done
zero_bitmap_valid says more than its name: a task created once it is
set skips its own block-status query, the sync=top skipping included,
because the scan has already settled what to copy. And the end of the
scan was announced twice, clearing skip_unallocated and then publishing
zero_bitmap_valid, with an ordering rule in a comment tying the two.
Rename the flag to scan_done, and let block_copy_set_scan_done() clear
skip_unallocated before publishing it, so backup_scan_source() makes one
call and the order is kept in one place. skip_unallocated is left to
mean that a sync=top scan is in progress. No behavior change.
Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Signed-off-by: Denis V. Lunev <den@openvz.org>
CC: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
CC: John Snow <jsnow@redhat.com>
CC: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Message-ID: <20261030010613.1612771-11-den@openvz.org>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
diff --git a/block/backup.c b/block/backup.c
index 60c00fca67..1bf6cbedac 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -254,7 +254,6 @@ static void backup_init_bcs_bitmap(BackupBlockJob *job)
static int coroutine_fn backup_scan_source(BackupBlockJob *s)
{
Job *job = &s->common.job;
- bool top = s->sync_mode == MIRROR_SYNC_MODE_TOP;
int64_t offset, cached_end = 0, count;
int ret = 0;
@@ -279,10 +278,7 @@ static int coroutine_fn backup_scan_source(BackupBlockJob *s)
}
}
- if (top) {
- block_copy_set_skip_unallocated(s->bcs, false);
- }
- block_copy_set_zero_bitmap_valid(s->bcs);
+ block_copy_set_scan_done(s->bcs);
return 0;
}
diff --git a/block/block-copy.c b/block/block-copy.c
index 78cc855b5b..3b7e282e5b 100644
--- a/block/block-copy.c
+++ b/block/block-copy.c
@@ -161,8 +161,12 @@ typedef struct BlockCopyState {
BdrvDirtyBitmap *copy_bitmap;
/* Clusters reading as zero; allocated on demand, frozen once valid. */
HBitmap *zero_bitmap;
- /* Published only after the scan, with skip_unallocated already false. */
- bool zero_bitmap_valid; /* atomic, store-release/load-acquire */
+ /*
+ * Set when the scan is over: zero_bitmap is complete, and for sync=top
+ * copy_bitmap holds no unallocated clusters, so a task needs no
+ * block-status query of its own.
+ */
+ bool scan_done; /* atomic, store-release/load-acquire */
ProgressMeter *progress;
SharedResource *mem;
RateLimit rate_limit;
@@ -214,7 +218,7 @@ block_copy_task_create(BlockCopyState *s, BlockCopyCallState *call_state,
* The scan already knows how this range reads: pick the method here and
* stop the task where the answer changes.
*/
- if (qatomic_load_acquire(&s->zero_bitmap_valid)) {
+ if (qatomic_load_acquire(&s->scan_done)) {
int64_t boundary;
if (hbitmap_get(s->zero_bitmap, offset)) {
@@ -687,7 +691,7 @@ int block_copy_block_status(BlockCopyState *s, int64_t offset, int64_t bytes,
return ret;
}
-/* Only the scan allocates, and it runs before zero_bitmap_valid. */
+/* Only the scan allocates, and it runs before scan_done. */
static HBitmap *block_copy_zero_bitmap(BlockCopyState *s)
{
if (!s->zero_bitmap) {
@@ -845,7 +849,7 @@ block_copy_set_task_method(BlockCopyState *s, BlockCopyTask *task)
int64_t status_bytes;
/* block_copy_task_create() already decided, from zero_bitmap. */
- if (qatomic_load_acquire(&s->zero_bitmap_valid)) {
+ if (qatomic_load_acquire(&s->scan_done)) {
return true;
}
@@ -1179,10 +1183,11 @@ void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip)
qatomic_set(&s->skip_unallocated, skip);
}
-void block_copy_set_zero_bitmap_valid(BlockCopyState *s)
+void block_copy_set_scan_done(BlockCopyState *s)
{
block_copy_zero_bitmap(s);
- qatomic_store_release(&s->zero_bitmap_valid, true);
+ qatomic_set(&s->skip_unallocated, false);
+ qatomic_store_release(&s->scan_done, true);
}
void block_copy_set_speed(BlockCopyState *s, uint64_t speed)
diff --git a/include/block/block-copy.h b/include/block/block-copy.h
index dc51316fcf..e82c96586e 100644
--- a/include/block/block-copy.h
+++ b/include/block/block-copy.h
@@ -102,6 +102,6 @@ void block_copy_call_cancel(BlockCopyCallState *call_state);
BdrvDirtyBitmap *block_copy_dirty_bitmap(BlockCopyState *s);
int64_t block_copy_cluster_size(BlockCopyState *s);
void block_copy_set_skip_unallocated(BlockCopyState *s, bool skip);
-void block_copy_set_zero_bitmap_valid(BlockCopyState *s);
+void block_copy_set_scan_done(BlockCopyState *s);
#endif /* BLOCK_COPY_H */