diff options
author | Pierre Riteau <Pierre.Riteau@irisa.fr> | 2011-01-21 12:42:30 +0100 |
---|---|---|
committer | Kevin Wolf <kwolf@redhat.com> | 2011-01-24 16:41:50 +0100 |
commit | 77358b59f6f3ef571fb2262f5f6216e179d07ecb (patch) | |
tree | ddc2f964d776839caae35f98072e37bab1aad4c2 | |
parent | c743849bee7333c7ef256b7e12e34ed6f907064f (diff) |
Fix block migration when the device size is not a multiple of 1 MB
b02bea3a85cc939f09aa674a3f1e4f36d418c007 added a check on the return
value of bdrv_write and aborts migration when it fails. However, if the
size of the block device to migrate is not a multiple of BLOCK_SIZE
(currently 1 MB), the last bdrv_write will fail with -EIO.
Fixed by calling bdrv_write with the correct size of the last block.
Signed-off-by: Pierre Riteau <Pierre.Riteau@irisa.fr>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
-rw-r--r-- | block-migration.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/block-migration.c b/block-migration.c index 60b9fc0ef0..c9d3e81dbf 100644 --- a/block-migration.c +++ b/block-migration.c @@ -638,8 +638,10 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) int len, flags; char device_name[256]; int64_t addr; - BlockDriverState *bs; + BlockDriverState *bs, *bs_prev = NULL; uint8_t *buf; + int64_t total_sectors = 0; + int nr_sectors; do { addr = qemu_get_be64(f); @@ -661,10 +663,26 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; } + if (bs != bs_prev) { + bs_prev = bs; + total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS; + if (total_sectors <= 0) { + error_report("Error getting length of block device %s\n", + device_name); + return -EINVAL; + } + } + + if (total_sectors - addr < BDRV_SECTORS_PER_DIRTY_CHUNK) { + nr_sectors = total_sectors - addr; + } else { + nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK; + } + buf = qemu_malloc(BLOCK_SIZE); qemu_get_buffer(f, buf, BLOCK_SIZE); - ret = bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK); + ret = bdrv_write(bs, addr, buf, nr_sectors); qemu_free(buf); if (ret < 0) { |