block migration: Add error handling/propagation
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
13f0b67fd3
commit
4b640365c7
@ -151,16 +151,12 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds, int is_async)
|
|||||||
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
|
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
|
||||||
nr_sectors, blk_mig_read_cb, blk);
|
nr_sectors, blk_mig_read_cb, blk);
|
||||||
if (!blk->aiocb) {
|
if (!blk->aiocb) {
|
||||||
printf("Error reading sector %" PRId64 "\n", cur_sector);
|
goto error;
|
||||||
qemu_free(blk->buf);
|
|
||||||
qemu_free(blk);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
block_mig_state.submitted++;
|
block_mig_state.submitted++;
|
||||||
} else {
|
} else {
|
||||||
if (bdrv_read(bs, cur_sector, blk->buf, nr_sectors) < 0) {
|
if (bdrv_read(bs, cur_sector, blk->buf, nr_sectors) < 0) {
|
||||||
printf("Error reading sector %" PRId64 "\n", cur_sector);
|
goto error;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
blk_send(f, blk);
|
blk_send(f, blk);
|
||||||
|
|
||||||
@ -172,6 +168,13 @@ static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds, int is_async)
|
|||||||
bmds->cur_sector = cur_sector + nr_sectors;
|
bmds->cur_sector = cur_sector + nr_sectors;
|
||||||
|
|
||||||
return (bmds->cur_sector >= total_sectors);
|
return (bmds->cur_sector >= total_sectors);
|
||||||
|
|
||||||
|
error:
|
||||||
|
printf("Error reading sector %" PRId64 "\n", cur_sector);
|
||||||
|
qemu_file_set_error(f);
|
||||||
|
qemu_free(blk->buf);
|
||||||
|
qemu_free(blk);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_dirty_tracking(int enable)
|
static void set_dirty_tracking(int enable)
|
||||||
@ -247,7 +250,9 @@ static void blk_mig_save_dirty_blocks(QEMUFile *f)
|
|||||||
if (bdrv_read(bmds->bs, sector, blk.buf,
|
if (bdrv_read(bmds->bs, sector, blk.buf,
|
||||||
BDRV_SECTORS_PER_DIRTY_CHUNK) < 0) {
|
BDRV_SECTORS_PER_DIRTY_CHUNK) < 0) {
|
||||||
printf("Error reading sector %" PRId64 "\n", sector);
|
printf("Error reading sector %" PRId64 "\n", sector);
|
||||||
/* FIXME: add error handling */
|
qemu_file_set_error(f);
|
||||||
|
qemu_free(blk.buf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
blk.bmds = bmds;
|
blk.bmds = bmds;
|
||||||
blk.sector = sector;
|
blk.sector = sector;
|
||||||
@ -275,6 +280,10 @@ static void flush_blks(QEMUFile* f)
|
|||||||
if (qemu_file_rate_limit(f)) {
|
if (qemu_file_rate_limit(f)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (blk->ret < 0) {
|
||||||
|
qemu_file_set_error(f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
blk_send(f, blk);
|
blk_send(f, blk);
|
||||||
|
|
||||||
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
|
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
|
||||||
@ -328,6 +337,11 @@ static int block_save_live(QEMUFile *f, int stage, void *opaque)
|
|||||||
|
|
||||||
flush_blks(f);
|
flush_blks(f);
|
||||||
|
|
||||||
|
if (qemu_file_has_error(f)) {
|
||||||
|
set_dirty_tracking(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* control the rate of transfer */
|
/* control the rate of transfer */
|
||||||
while ((block_mig_state.submitted +
|
while ((block_mig_state.submitted +
|
||||||
block_mig_state.read_done) * BLOCK_SIZE <
|
block_mig_state.read_done) * BLOCK_SIZE <
|
||||||
@ -340,6 +354,11 @@ static int block_save_live(QEMUFile *f, int stage, void *opaque)
|
|||||||
|
|
||||||
flush_blks(f);
|
flush_blks(f);
|
||||||
|
|
||||||
|
if (qemu_file_has_error(f)) {
|
||||||
|
set_dirty_tracking(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (stage == 3) {
|
if (stage == 3) {
|
||||||
while (blk_mig_save_bulked_block(f, 0) != 0) {
|
while (blk_mig_save_bulked_block(f, 0) != 0) {
|
||||||
/* empty */
|
/* empty */
|
||||||
@ -350,6 +369,10 @@ static int block_save_live(QEMUFile *f, int stage, void *opaque)
|
|||||||
/* stop track dirty blocks */
|
/* stop track dirty blocks */
|
||||||
set_dirty_tracking(0);
|
set_dirty_tracking(0);
|
||||||
|
|
||||||
|
if (qemu_file_has_error(f)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
printf("\nBlock migration completed\n");
|
printf("\nBlock migration completed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,26 +398,28 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
|||||||
if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
|
if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
|
||||||
/* get device name */
|
/* get device name */
|
||||||
len = qemu_get_byte(f);
|
len = qemu_get_byte(f);
|
||||||
|
|
||||||
qemu_get_buffer(f, (uint8_t *)device_name, len);
|
qemu_get_buffer(f, (uint8_t *)device_name, len);
|
||||||
device_name[len] = '\0';
|
device_name[len] = '\0';
|
||||||
|
|
||||||
bs = bdrv_find(device_name);
|
bs = bdrv_find(device_name);
|
||||||
|
if (!bs) {
|
||||||
|
fprintf(stderr, "Error unknown block device %s\n",
|
||||||
|
device_name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
buf = qemu_malloc(BLOCK_SIZE);
|
buf = qemu_malloc(BLOCK_SIZE);
|
||||||
|
|
||||||
qemu_get_buffer(f, buf, BLOCK_SIZE);
|
qemu_get_buffer(f, buf, BLOCK_SIZE);
|
||||||
if (bs != NULL) {
|
bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
|
||||||
bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
|
|
||||||
} else {
|
|
||||||
printf("Error unknown block device %s\n", device_name);
|
|
||||||
/* FIXME: add error handling */
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_free(buf);
|
qemu_free(buf);
|
||||||
} else if (!(flags & BLK_MIG_FLAG_EOS)) {
|
} else if (!(flags & BLK_MIG_FLAG_EOS)) {
|
||||||
printf("Unknown flags\n");
|
fprintf(stderr, "Unknown flags\n");
|
||||||
/* FIXME: add error handling */
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (qemu_file_has_error(f)) {
|
||||||
|
return -EIO;
|
||||||
}
|
}
|
||||||
} while (!(flags & BLK_MIG_FLAG_EOS));
|
} while (!(flags & BLK_MIG_FLAG_EOS));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user