Skip to content

Commit 323004a

Browse files
plievenstefanhaRH
authored andcommitted
block-migration: efficiently encode zero blocks
this patch adds a efficient encoding for zero blocks by adding a new flag indicating a block is completely zero. additionally bdrv_write_zeros() is used at the destination to efficiently write these zeroes. depending on the implementation this avoids that the destination target gets fully provisioned. Signed-off-by: Peter Lieven <[email protected]> Signed-off-by: Stefan Hajnoczi <[email protected]>
1 parent 8bf9344 commit 323004a

File tree

4 files changed

+43
-7
lines changed

4 files changed

+43
-7
lines changed

block-migration.c

+26-6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#define BLK_MIG_FLAG_DEVICE_BLOCK 0x01
3030
#define BLK_MIG_FLAG_EOS 0x02
3131
#define BLK_MIG_FLAG_PROGRESS 0x04
32+
#define BLK_MIG_FLAG_ZERO_BLOCK 0x08
3233

3334
#define MAX_IS_ALLOCATED_SEARCH 65536
3435

@@ -80,6 +81,7 @@ typedef struct BlkMigState {
8081
int shared_base;
8182
QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
8283
int64_t total_sector_sum;
84+
bool zero_blocks;
8385

8486
/* Protected by lock. */
8587
QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
@@ -114,16 +116,30 @@ static void blk_mig_unlock(void)
114116
static void blk_send(QEMUFile *f, BlkMigBlock * blk)
115117
{
116118
int len;
119+
uint64_t flags = BLK_MIG_FLAG_DEVICE_BLOCK;
120+
121+
if (block_mig_state.zero_blocks &&
122+
buffer_is_zero(blk->buf, BLOCK_SIZE)) {
123+
flags |= BLK_MIG_FLAG_ZERO_BLOCK;
124+
}
117125

118126
/* sector number and flags */
119127
qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS)
120-
| BLK_MIG_FLAG_DEVICE_BLOCK);
128+
| flags);
121129

122130
/* device name */
123131
len = strlen(blk->bmds->bs->device_name);
124132
qemu_put_byte(f, len);
125133
qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
126134

135+
/* if a block is zero we need to flush here since the network
136+
* bandwidth is now a lot higher than the storage device bandwidth.
137+
* thus if we queue zero blocks we slow down the migration */
138+
if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
139+
qemu_fflush(f);
140+
return;
141+
}
142+
127143
qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
128144
}
129145

@@ -344,6 +360,7 @@ static void init_blk_migration(QEMUFile *f)
344360
block_mig_state.total_sector_sum = 0;
345361
block_mig_state.prev_progress = -1;
346362
block_mig_state.bulk_completed = 0;
363+
block_mig_state.zero_blocks = migrate_zero_blocks();
347364

348365
bdrv_iterate(init_blk_migration_it, NULL);
349366
}
@@ -762,12 +779,15 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
762779
nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
763780
}
764781

765-
buf = g_malloc(BLOCK_SIZE);
766-
767-
qemu_get_buffer(f, buf, BLOCK_SIZE);
768-
ret = bdrv_write(bs, addr, buf, nr_sectors);
782+
if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
783+
ret = bdrv_write_zeroes(bs, addr, nr_sectors);
784+
} else {
785+
buf = g_malloc(BLOCK_SIZE);
786+
qemu_get_buffer(f, buf, BLOCK_SIZE);
787+
ret = bdrv_write(bs, addr, buf, nr_sectors);
788+
g_free(buf);
789+
}
769790

770-
g_free(buf);
771791
if (ret < 0) {
772792
return ret;
773793
}

include/migration/migration.h

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ void migrate_add_blocker(Error *reason);
124124
void migrate_del_blocker(Error *reason);
125125

126126
bool migrate_rdma_pin_all(void);
127+
bool migrate_zero_blocks(void);
127128

128129
bool migrate_auto_converge(void);
129130

migration.c

+9
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,15 @@ bool migrate_auto_converge(void)
493493
return s->enabled_capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
494494
}
495495

496+
bool migrate_zero_blocks(void)
497+
{
498+
MigrationState *s;
499+
500+
s = migrate_get_current();
501+
502+
return s->enabled_capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
503+
}
504+
496505
int migrate_use_xbzrle(void)
497506
{
498507
MigrationState *s;

qapi-schema.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -613,10 +613,16 @@
613613
# Disabled by default. Experimental: may (or may not) be renamed after
614614
# further testing is complete. (since 1.6)
615615
#
616+
# @zero-blocks: During storage migration encode blocks of zeroes efficiently. This
617+
# essentially saves 1MB of zeroes per block on the wire. Enabling requires
618+
# source and target VM to support this feature. To enable it is sufficient
619+
# to enable the capability on the source VM. The feature is disabled by
620+
# default. (since 1.6)
621+
#
616622
# Since: 1.2
617623
##
618624
{ 'enum': 'MigrationCapability',
619-
'data': ['xbzrle', 'x-rdma-pin-all', 'auto-converge'] }
625+
'data': ['xbzrle', 'x-rdma-pin-all', 'auto-converge', 'zero-blocks'] }
620626

621627
##
622628
# @MigrationCapabilityStatus

0 commit comments

Comments
 (0)