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:
Jan Kiszka 2009-11-30 18:21:21 +01:00 committed by Anthony Liguori
parent 13f0b67fd3
commit 4b640365c7

View File

@ -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));