Il 22/06/2013 22:58, Peter Lieven ha scritto: > this patch adds a efficient encoding for zero blocks by > adding a new flag indiciating a block is completly zero. > > additionally bdrv_write_zeros() is used at the destination > to efficiently write these zeroes. if the driver supports > it this avoids blindly allocating all sectors consumed by > zero blocks effectively re-thinning the device. > > Signed-off-by: Peter Lieven <p...@kamp.de>
This is a bit ugly because it doesn't work with drive-mirror. Perhaps we can add a write-zeroes opcode to NBD, too. Paolo > --- > block-migration.c | 29 +++++++++++++++++++++++------ > include/migration/qemu-file.h | 1 + > savevm.c | 2 +- > 3 files changed, 25 insertions(+), 7 deletions(-) > > diff --git a/block-migration.c b/block-migration.c > index 2fd7699..99b3757 100644 > --- a/block-migration.c > +++ b/block-migration.c > @@ -29,6 +29,7 @@ > #define BLK_MIG_FLAG_DEVICE_BLOCK 0x01 > #define BLK_MIG_FLAG_EOS 0x02 > #define BLK_MIG_FLAG_PROGRESS 0x04 > +#define BLK_MIG_FLAG_ZERO_BLOCK 0x08 > > #define MAX_IS_ALLOCATED_SEARCH 65536 > > @@ -114,16 +115,29 @@ static void blk_mig_unlock(void) > static void blk_send(QEMUFile *f, BlkMigBlock * blk) > { > int len; > + int flags = BLK_MIG_FLAG_DEVICE_BLOCK; > + > + if (buffer_is_zero(blk->buf, BLOCK_SIZE)) { > + flags |= BLK_MIG_FLAG_ZERO_BLOCK; > + } > > /* sector number and flags */ > qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS) > - | BLK_MIG_FLAG_DEVICE_BLOCK); > + | flags); > > /* device name */ > len = strlen(blk->bmds->bs->device_name); > qemu_put_byte(f, len); > qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len); > > + /* if a block is zero we need to flush here since the network > + * bandwidth is now a lot higher than the storage device bandwidth. > + * thus if we queue zero blocks we slow down the migration */ > + if (flags & BLK_MIG_FLAG_ZERO_BLOCK) { > + qemu_fflush(f); > + return; > + } > + > qemu_put_buffer(f, blk->buf, BLOCK_SIZE); > } > > @@ -762,12 +776,15 @@ static int block_load(QEMUFile *f, void *opaque, int > version_id) > nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK; > } > > - buf = g_malloc(BLOCK_SIZE); > - > - qemu_get_buffer(f, buf, BLOCK_SIZE); > - ret = bdrv_write(bs, addr, buf, nr_sectors); > + if (flags & BLK_MIG_FLAG_ZERO_BLOCK) { > + ret = bdrv_write_zeroes(bs, addr, nr_sectors); > + } else { > + buf = g_malloc(BLOCK_SIZE); > + qemu_get_buffer(f, buf, BLOCK_SIZE); > + ret = bdrv_write(bs, addr, buf, nr_sectors); > + g_free(buf); > + } > > - g_free(buf); > if (ret < 0) { > return ret; > } > diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h > index 7519464..b73298d 100644 > --- a/include/migration/qemu-file.h > +++ b/include/migration/qemu-file.h > @@ -71,6 +71,7 @@ QEMUFile *qemu_fdopen(int fd, const char *mode); > QEMUFile *qemu_fopen_socket(int fd, const char *mode); > QEMUFile *qemu_popen_cmd(const char *command, const char *mode); > int qemu_get_fd(QEMUFile *f); > +void qemu_fflush(QEMUFile *f); > int qemu_fclose(QEMUFile *f); > int64_t qemu_ftell(QEMUFile *f); > void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); > diff --git a/savevm.c b/savevm.c > index ff5ece6..4d12d92 100644 > --- a/savevm.c > +++ b/savevm.c > @@ -610,7 +610,7 @@ static inline bool qemu_file_is_writable(QEMUFile *f) > * If there is writev_buffer QEMUFileOps it uses it otherwise uses > * put_buffer ops. > */ > -static void qemu_fflush(QEMUFile *f) > +void qemu_fflush(QEMUFile *f) > { > ssize_t ret = 0; > >