Merge remote branch 'kwolf/for-anthony' into staging
This commit is contained in:
commit
f040236cd5
@ -346,7 +346,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
|
|||||||
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
|
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
|
||||||
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
|
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
|
||||||
|
|
||||||
blk->time = qemu_get_clock_ns(rt_clock);
|
blk->time = qemu_get_clock_ns(rt_clock);
|
||||||
|
|
||||||
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
|
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
|
||||||
nr_sectors, blk_mig_read_cb, blk);
|
nr_sectors, blk_mig_read_cb, blk);
|
||||||
@ -449,13 +449,13 @@ static int is_stage2_completed(void)
|
|||||||
if (block_mig_state.bulk_completed == 1) {
|
if (block_mig_state.bulk_completed == 1) {
|
||||||
|
|
||||||
remaining_dirty = get_remaining_dirty();
|
remaining_dirty = get_remaining_dirty();
|
||||||
if (remaining_dirty == 0) {
|
if (remaining_dirty == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bwidth = compute_read_bwidth();
|
bwidth = compute_read_bwidth();
|
||||||
|
|
||||||
if ((remaining_dirty / bwidth) <=
|
if ((remaining_dirty / bwidth) <=
|
||||||
migrate_max_downtime()) {
|
migrate_max_downtime()) {
|
||||||
/* finish stage2 because we think that we can finish remaing work
|
/* finish stage2 because we think that we can finish remaing work
|
||||||
below max_downtime */
|
below max_downtime */
|
||||||
|
50
block.c
50
block.c
@ -739,14 +739,16 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
|
|||||||
return bs->drv->bdrv_check(bs, res);
|
return bs->drv->bdrv_check(bs, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define COMMIT_BUF_SECTORS 2048
|
||||||
|
|
||||||
/* commit COW file into the raw image */
|
/* commit COW file into the raw image */
|
||||||
int bdrv_commit(BlockDriverState *bs)
|
int bdrv_commit(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
int64_t i, total_sectors;
|
int64_t sector, total_sectors;
|
||||||
int n, j, ro, open_flags;
|
int n, ro, open_flags;
|
||||||
int ret = 0, rw_ret = 0;
|
int ret = 0, rw_ret = 0;
|
||||||
unsigned char sector[BDRV_SECTOR_SIZE];
|
uint8_t *buf;
|
||||||
char filename[1024];
|
char filename[1024];
|
||||||
BlockDriverState *bs_rw, *bs_ro;
|
BlockDriverState *bs_rw, *bs_ro;
|
||||||
|
|
||||||
@ -789,22 +791,20 @@ int bdrv_commit(BlockDriverState *bs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||||
for (i = 0; i < total_sectors;) {
|
buf = qemu_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
||||||
if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
|
|
||||||
for(j = 0; j < n; j++) {
|
|
||||||
if (bdrv_read(bs, i, sector, 1) != 0) {
|
|
||||||
ret = -EIO;
|
|
||||||
goto ro_cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
|
for (sector = 0; sector < total_sectors; sector += n) {
|
||||||
ret = -EIO;
|
if (drv->bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
|
||||||
goto ro_cleanup;
|
|
||||||
}
|
if (bdrv_read(bs, sector, buf, n) != 0) {
|
||||||
i++;
|
ret = -EIO;
|
||||||
}
|
goto ro_cleanup;
|
||||||
} else {
|
}
|
||||||
i += n;
|
|
||||||
|
if (bdrv_write(bs->backing_hd, sector, buf, n) != 0) {
|
||||||
|
ret = -EIO;
|
||||||
|
goto ro_cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,6 +821,7 @@ int bdrv_commit(BlockDriverState *bs)
|
|||||||
bdrv_flush(bs->backing_hd);
|
bdrv_flush(bs->backing_hd);
|
||||||
|
|
||||||
ro_cleanup:
|
ro_cleanup:
|
||||||
|
qemu_free(buf);
|
||||||
|
|
||||||
if (ro) {
|
if (ro) {
|
||||||
/* re-open as RO */
|
/* re-open as RO */
|
||||||
@ -1476,10 +1477,8 @@ int bdrv_has_zero_init(BlockDriverState *bs)
|
|||||||
{
|
{
|
||||||
assert(bs->drv);
|
assert(bs->drv);
|
||||||
|
|
||||||
if (bs->drv->no_zero_init) {
|
if (bs->drv->bdrv_has_zero_init) {
|
||||||
return 0;
|
return bs->drv->bdrv_has_zero_init(bs);
|
||||||
} else if (bs->file) {
|
|
||||||
return bdrv_has_zero_init(bs->file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -2518,7 +2517,7 @@ int bdrv_is_inserted(BlockDriverState *bs)
|
|||||||
if (!drv)
|
if (!drv)
|
||||||
return 0;
|
return 0;
|
||||||
if (!drv->bdrv_is_inserted)
|
if (!drv->bdrv_is_inserted)
|
||||||
return 1;
|
return !bs->tray_open;
|
||||||
ret = drv->bdrv_is_inserted(bs);
|
ret = drv->bdrv_is_inserted(bs);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2560,10 +2559,11 @@ int bdrv_eject(BlockDriverState *bs, int eject_flag)
|
|||||||
ret = drv->bdrv_eject(bs, eject_flag);
|
ret = drv->bdrv_eject(bs, eject_flag);
|
||||||
}
|
}
|
||||||
if (ret == -ENOTSUP) {
|
if (ret == -ENOTSUP) {
|
||||||
if (eject_flag)
|
|
||||||
bdrv_close(bs);
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
if (ret >= 0) {
|
||||||
|
bs->tray_open = eject_flag;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -993,6 +993,11 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdev_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_host_device = {
|
static BlockDriver bdrv_host_device = {
|
||||||
.format_name = "host_device",
|
.format_name = "host_device",
|
||||||
.protocol_name = "host_device",
|
.protocol_name = "host_device",
|
||||||
@ -1002,7 +1007,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
@ -1117,7 +1122,7 @@ static BlockDriver bdrv_host_floppy = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
@ -1217,7 +1222,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
@ -1340,7 +1345,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
.no_zero_init = 1,
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
|
@ -394,6 +394,11 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int hdev_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_host_device = {
|
static BlockDriver bdrv_host_device = {
|
||||||
.format_name = "host_device",
|
.format_name = "host_device",
|
||||||
.protocol_name = "host_device",
|
.protocol_name = "host_device",
|
||||||
@ -402,6 +407,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.bdrv_file_open = hdev_open,
|
.bdrv_file_open = hdev_open,
|
||||||
.bdrv_close = raw_close,
|
.bdrv_close = raw_close,
|
||||||
.bdrv_flush = raw_flush,
|
.bdrv_flush = raw_flush,
|
||||||
|
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||||
|
|
||||||
.bdrv_read = raw_read,
|
.bdrv_read = raw_read,
|
||||||
.bdrv_write = raw_write,
|
.bdrv_write = raw_write,
|
||||||
|
@ -237,6 +237,11 @@ static QEMUOptionParameter raw_create_options[] = {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int raw_has_zero_init(BlockDriverState *bs)
|
||||||
|
{
|
||||||
|
return bdrv_has_zero_init(bs->file);
|
||||||
|
}
|
||||||
|
|
||||||
static BlockDriver bdrv_raw = {
|
static BlockDriver bdrv_raw = {
|
||||||
.format_name = "raw",
|
.format_name = "raw",
|
||||||
|
|
||||||
@ -264,6 +269,7 @@ static BlockDriver bdrv_raw = {
|
|||||||
|
|
||||||
.bdrv_create = raw_create,
|
.bdrv_create = raw_create,
|
||||||
.create_options = raw_create_options,
|
.create_options = raw_create_options,
|
||||||
|
.bdrv_has_zero_init = raw_has_zero_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bdrv_raw_init(void)
|
static void bdrv_raw_init(void)
|
||||||
|
@ -127,8 +127,11 @@ struct BlockDriver {
|
|||||||
|
|
||||||
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
void (*bdrv_debug_event)(BlockDriverState *bs, BlkDebugEvent event);
|
||||||
|
|
||||||
/* Set if newly created images are not guaranteed to contain only zeros */
|
/*
|
||||||
int no_zero_init;
|
* Returns 1 if newly created images are guaranteed to contain only
|
||||||
|
* zeros, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int (*bdrv_has_zero_init)(BlockDriverState *bs);
|
||||||
|
|
||||||
QLIST_ENTRY(BlockDriver) list;
|
QLIST_ENTRY(BlockDriver) list;
|
||||||
};
|
};
|
||||||
@ -141,6 +144,7 @@ struct BlockDriverState {
|
|||||||
int open_flags; /* flags used to open the file, re-used for re-open */
|
int open_flags; /* flags used to open the file, re-used for re-open */
|
||||||
int removable; /* if true, the media can be removed */
|
int removable; /* if true, the media can be removed */
|
||||||
int locked; /* if true, the media cannot temporarily be ejected */
|
int locked; /* if true, the media cannot temporarily be ejected */
|
||||||
|
int tray_open; /* if true, the virtual tray is open */
|
||||||
int encrypted; /* if true, the media is encrypted */
|
int encrypted; /* if true, the media is encrypted */
|
||||||
int valid_key; /* if true, a valid encryption key has been set */
|
int valid_key; /* if true, a valid encryption key has been set */
|
||||||
int sg; /* if true, the device is a /dev/sg* */
|
int sg; /* if true, the device is a /dev/sg* */
|
||||||
|
23
hw/ide/pci.c
23
hw/ide/pci.c
@ -40,8 +40,27 @@ void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
|
|||||||
printf("%s: 0x%08x\n", __func__, val);
|
printf("%s: 0x%08x\n", __func__, val);
|
||||||
#endif
|
#endif
|
||||||
if (!(val & BM_CMD_START)) {
|
if (!(val & BM_CMD_START)) {
|
||||||
/* XXX: do it better */
|
/*
|
||||||
ide_dma_cancel(bm);
|
* We can't cancel Scatter Gather DMA in the middle of the
|
||||||
|
* operation or a partial (not full) DMA transfer would reach
|
||||||
|
* the storage so we wait for completion instead (we beahve
|
||||||
|
* like if the DMA was completed by the time the guest trying
|
||||||
|
* to cancel dma with bmdma_cmd_writeb with BM_CMD_START not
|
||||||
|
* set).
|
||||||
|
*
|
||||||
|
* In the future we'll be able to safely cancel the I/O if the
|
||||||
|
* whole DMA operation will be submitted to disk with a single
|
||||||
|
* aio operation with preadv/pwritev.
|
||||||
|
*/
|
||||||
|
if (bm->aiocb) {
|
||||||
|
qemu_aio_flush();
|
||||||
|
#ifdef DEBUG_IDE
|
||||||
|
if (bm->aiocb)
|
||||||
|
printf("ide_dma_cancel: aiocb still pending");
|
||||||
|
if (bm->status & BM_STATUS_DMAING)
|
||||||
|
printf("ide_dma_cancel: BM_STATUS_DMAING still pending");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
bm->cmd = val & 0x09;
|
bm->cmd = val & 0x09;
|
||||||
} else {
|
} else {
|
||||||
if (!(bm->status & BM_STATUS_DMAING)) {
|
if (!(bm->status & BM_STATUS_DMAING)) {
|
||||||
|
@ -2274,8 +2274,9 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
|
|||||||
|
|
||||||
vm_stop(0);
|
vm_stop(0);
|
||||||
|
|
||||||
if (load_vmstate(name) >= 0 && saved_vm_running)
|
if (load_vmstate(name) == 0 && saved_vm_running) {
|
||||||
vm_start();
|
vm_start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int monitor_get_fd(Monitor *mon, const char *fdname)
|
int monitor_get_fd(Monitor *mon, const char *fdname)
|
||||||
|
71
savevm.c
71
savevm.c
@ -1894,12 +1894,27 @@ void do_savevm(Monitor *mon, const QDict *qdict)
|
|||||||
|
|
||||||
int load_vmstate(const char *name)
|
int load_vmstate(const char *name)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs, *bs1;
|
BlockDriverState *bs, *bs_vm_state;
|
||||||
QEMUSnapshotInfo sn;
|
QEMUSnapshotInfo sn;
|
||||||
QEMUFile *f;
|
QEMUFile *f;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Verify if there is a device that doesn't support snapshots and is writable */
|
bs_vm_state = bdrv_snapshots();
|
||||||
|
if (!bs_vm_state) {
|
||||||
|
error_report("No block device supports snapshots");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't even try to load empty VM states */
|
||||||
|
ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
} else if (sn.vm_state_size == 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify if there is any device that doesn't support snapshots and is
|
||||||
|
writable and check if the requested snapshot is available too. */
|
||||||
bs = NULL;
|
bs = NULL;
|
||||||
while ((bs = bdrv_next(bs))) {
|
while ((bs = bdrv_next(bs))) {
|
||||||
|
|
||||||
@ -1912,63 +1927,45 @@ int load_vmstate(const char *name)
|
|||||||
bdrv_get_device_name(bs));
|
bdrv_get_device_name(bs));
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bs = bdrv_snapshots();
|
ret = bdrv_snapshot_find(bs, &sn, name);
|
||||||
if (!bs) {
|
if (ret < 0) {
|
||||||
error_report("No block device supports snapshots");
|
error_report("Device '%s' does not have the requested snapshot '%s'",
|
||||||
return -EINVAL;
|
bdrv_get_device_name(bs), name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush all IO requests so they don't interfere with the new state. */
|
/* Flush all IO requests so they don't interfere with the new state. */
|
||||||
qemu_aio_flush();
|
qemu_aio_flush();
|
||||||
|
|
||||||
bs1 = NULL;
|
bs = NULL;
|
||||||
while ((bs1 = bdrv_next(bs1))) {
|
while ((bs = bdrv_next(bs))) {
|
||||||
if (bdrv_can_snapshot(bs1)) {
|
if (bdrv_can_snapshot(bs)) {
|
||||||
ret = bdrv_snapshot_goto(bs1, name);
|
ret = bdrv_snapshot_goto(bs, name);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
switch(ret) {
|
error_report("Error %d while activating snapshot '%s' on '%s'",
|
||||||
case -ENOTSUP:
|
ret, name, bdrv_get_device_name(bs));
|
||||||
error_report("%sSnapshots not supported on device '%s'",
|
return ret;
|
||||||
bs != bs1 ? "Warning: " : "",
|
|
||||||
bdrv_get_device_name(bs1));
|
|
||||||
break;
|
|
||||||
case -ENOENT:
|
|
||||||
error_report("%sCould not find snapshot '%s' on device '%s'",
|
|
||||||
bs != bs1 ? "Warning: " : "",
|
|
||||||
name, bdrv_get_device_name(bs1));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error_report("%sError %d while activating snapshot on '%s'",
|
|
||||||
bs != bs1 ? "Warning: " : "",
|
|
||||||
ret, bdrv_get_device_name(bs1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* fatal on snapshot block device */
|
|
||||||
if (bs == bs1)
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't even try to load empty VM states */
|
|
||||||
ret = bdrv_snapshot_find(bs, &sn, name);
|
|
||||||
if ((ret >= 0) && (sn.vm_state_size == 0))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* restore the VM state */
|
/* restore the VM state */
|
||||||
f = qemu_fopen_bdrv(bs, 0);
|
f = qemu_fopen_bdrv(bs_vm_state, 0);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
error_report("Could not open VM state file");
|
error_report("Could not open VM state file");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemu_loadvm_state(f);
|
ret = qemu_loadvm_state(f);
|
||||||
|
|
||||||
qemu_fclose(f);
|
qemu_fclose(f);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("Error %d while loading VM state", ret);
|
error_report("Error %d while loading VM state", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user