mirror of https://gitee.com/openkylin/qemu.git
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;
|
||||
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,
|
||||
nr_sectors, blk_mig_read_cb, blk);
|
||||
|
@ -449,13 +449,13 @@ static int is_stage2_completed(void)
|
|||
if (block_mig_state.bulk_completed == 1) {
|
||||
|
||||
remaining_dirty = get_remaining_dirty();
|
||||
if (remaining_dirty == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (remaining_dirty == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bwidth = compute_read_bwidth();
|
||||
bwidth = compute_read_bwidth();
|
||||
|
||||
if ((remaining_dirty / bwidth) <=
|
||||
if ((remaining_dirty / bwidth) <=
|
||||
migrate_max_downtime()) {
|
||||
/* finish stage2 because we think that we can finish remaing work
|
||||
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);
|
||||
}
|
||||
|
||||
#define COMMIT_BUF_SECTORS 2048
|
||||
|
||||
/* commit COW file into the raw image */
|
||||
int bdrv_commit(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
int64_t i, total_sectors;
|
||||
int n, j, ro, open_flags;
|
||||
int64_t sector, total_sectors;
|
||||
int n, ro, open_flags;
|
||||
int ret = 0, rw_ret = 0;
|
||||
unsigned char sector[BDRV_SECTOR_SIZE];
|
||||
uint8_t *buf;
|
||||
char filename[1024];
|
||||
BlockDriverState *bs_rw, *bs_ro;
|
||||
|
||||
|
@ -789,22 +791,20 @@ int bdrv_commit(BlockDriverState *bs)
|
|||
}
|
||||
|
||||
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||
for (i = 0; i < total_sectors;) {
|
||||
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;
|
||||
}
|
||||
buf = qemu_malloc(COMMIT_BUF_SECTORS * BDRV_SECTOR_SIZE);
|
||||
|
||||
if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
|
||||
ret = -EIO;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
i += n;
|
||||
for (sector = 0; sector < total_sectors; sector += n) {
|
||||
if (drv->bdrv_is_allocated(bs, sector, COMMIT_BUF_SECTORS, &n)) {
|
||||
|
||||
if (bdrv_read(bs, sector, buf, n) != 0) {
|
||||
ret = -EIO;
|
||||
goto ro_cleanup;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ro_cleanup:
|
||||
qemu_free(buf);
|
||||
|
||||
if (ro) {
|
||||
/* re-open as RO */
|
||||
|
@ -1476,10 +1477,8 @@ int bdrv_has_zero_init(BlockDriverState *bs)
|
|||
{
|
||||
assert(bs->drv);
|
||||
|
||||
if (bs->drv->no_zero_init) {
|
||||
return 0;
|
||||
} else if (bs->file) {
|
||||
return bdrv_has_zero_init(bs->file);
|
||||
if (bs->drv->bdrv_has_zero_init) {
|
||||
return bs->drv->bdrv_has_zero_init(bs);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -2518,7 +2517,7 @@ int bdrv_is_inserted(BlockDriverState *bs)
|
|||
if (!drv)
|
||||
return 0;
|
||||
if (!drv->bdrv_is_inserted)
|
||||
return 1;
|
||||
return !bs->tray_open;
|
||||
ret = drv->bdrv_is_inserted(bs);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2560,10 +2559,11 @@ int bdrv_eject(BlockDriverState *bs, int eject_flag)
|
|||
ret = drv->bdrv_eject(bs, eject_flag);
|
||||
}
|
||||
if (ret == -ENOTSUP) {
|
||||
if (eject_flag)
|
||||
bdrv_close(bs);
|
||||
ret = 0;
|
||||
}
|
||||
if (ret >= 0) {
|
||||
bs->tray_open = eject_flag;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -993,6 +993,11 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int hdev_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_host_device = {
|
||||
.format_name = "host_device",
|
||||
.protocol_name = "host_device",
|
||||
|
@ -1002,7 +1007,7 @@ static BlockDriver bdrv_host_device = {
|
|||
.bdrv_close = raw_close,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.no_zero_init = 1,
|
||||
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||
.bdrv_flush = raw_flush,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
|
@ -1117,7 +1122,7 @@ static BlockDriver bdrv_host_floppy = {
|
|||
.bdrv_close = raw_close,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.no_zero_init = 1,
|
||||
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||
.bdrv_flush = raw_flush,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
|
@ -1217,7 +1222,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||
.bdrv_close = raw_close,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.no_zero_init = 1,
|
||||
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||
.bdrv_flush = raw_flush,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
|
@ -1340,7 +1345,7 @@ static BlockDriver bdrv_host_cdrom = {
|
|||
.bdrv_close = raw_close,
|
||||
.bdrv_create = hdev_create,
|
||||
.create_options = raw_create_options,
|
||||
.no_zero_init = 1,
|
||||
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||
.bdrv_flush = raw_flush,
|
||||
|
||||
.bdrv_aio_readv = raw_aio_readv,
|
||||
|
|
|
@ -394,6 +394,11 @@ static int raw_set_locked(BlockDriverState *bs, int locked)
|
|||
}
|
||||
#endif
|
||||
|
||||
static int hdev_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_host_device = {
|
||||
.format_name = "host_device",
|
||||
.protocol_name = "host_device",
|
||||
|
@ -402,6 +407,7 @@ static BlockDriver bdrv_host_device = {
|
|||
.bdrv_file_open = hdev_open,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_flush = raw_flush,
|
||||
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
|
|
|
@ -237,6 +237,11 @@ static QEMUOptionParameter raw_create_options[] = {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
static int raw_has_zero_init(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_has_zero_init(bs->file);
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_raw = {
|
||||
.format_name = "raw",
|
||||
|
||||
|
@ -264,6 +269,7 @@ static BlockDriver bdrv_raw = {
|
|||
|
||||
.bdrv_create = raw_create,
|
||||
.create_options = raw_create_options,
|
||||
.bdrv_has_zero_init = raw_has_zero_init,
|
||||
};
|
||||
|
||||
static void bdrv_raw_init(void)
|
||||
|
|
|
@ -127,8 +127,11 @@ struct BlockDriver {
|
|||
|
||||
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;
|
||||
};
|
||||
|
@ -141,6 +144,7 @@ struct BlockDriverState {
|
|||
int open_flags; /* flags used to open the file, re-used for re-open */
|
||||
int removable; /* if true, the media can be removed */
|
||||
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 valid_key; /* if true, a valid encryption key has been set */
|
||||
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);
|
||||
#endif
|
||||
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;
|
||||
} else {
|
||||
if (!(bm->status & BM_STATUS_DMAING)) {
|
||||
|
|
|
@ -2274,8 +2274,9 @@ static void do_loadvm(Monitor *mon, const QDict *qdict)
|
|||
|
||||
vm_stop(0);
|
||||
|
||||
if (load_vmstate(name) >= 0 && saved_vm_running)
|
||||
if (load_vmstate(name) == 0 && saved_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
BlockDriverState *bs, *bs1;
|
||||
BlockDriverState *bs, *bs_vm_state;
|
||||
QEMUSnapshotInfo sn;
|
||||
QEMUFile *f;
|
||||
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;
|
||||
while ((bs = bdrv_next(bs))) {
|
||||
|
||||
|
@ -1912,63 +1927,45 @@ int load_vmstate(const char *name)
|
|||
bdrv_get_device_name(bs));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
bs = bdrv_snapshots();
|
||||
if (!bs) {
|
||||
error_report("No block device supports snapshots");
|
||||
return -EINVAL;
|
||||
ret = bdrv_snapshot_find(bs, &sn, name);
|
||||
if (ret < 0) {
|
||||
error_report("Device '%s' does not have the requested snapshot '%s'",
|
||||
bdrv_get_device_name(bs), name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush all IO requests so they don't interfere with the new state. */
|
||||
qemu_aio_flush();
|
||||
|
||||
bs1 = NULL;
|
||||
while ((bs1 = bdrv_next(bs1))) {
|
||||
if (bdrv_can_snapshot(bs1)) {
|
||||
ret = bdrv_snapshot_goto(bs1, name);
|
||||
bs = NULL;
|
||||
while ((bs = bdrv_next(bs))) {
|
||||
if (bdrv_can_snapshot(bs)) {
|
||||
ret = bdrv_snapshot_goto(bs, name);
|
||||
if (ret < 0) {
|
||||
switch(ret) {
|
||||
case -ENOTSUP:
|
||||
error_report("%sSnapshots not supported on device '%s'",
|
||||
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;
|
||||
error_report("Error %d while activating snapshot '%s' on '%s'",
|
||||
ret, name, bdrv_get_device_name(bs));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
f = qemu_fopen_bdrv(bs, 0);
|
||||
f = qemu_fopen_bdrv(bs_vm_state, 0);
|
||||
if (!f) {
|
||||
error_report("Could not open VM state file");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = qemu_loadvm_state(f);
|
||||
|
||||
qemu_fclose(f);
|
||||
if (ret < 0) {
|
||||
error_report("Error %d while loading VM state", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue