migration/next for 20151119
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJWTa+zAAoJEPSH7xhYctcjImIQAM3Jzy8BikDV7DnQeOjzkd6l UCqVH5CPegUwiQvwx8qjVzc/xANg79zzLUwc3wxjC6v725dLHuVNZk7PyNNWl3jQ fHEvtgA0m2a4kSpJ4VcHgh/Rs93qKMvxc/hmjUn2R5JftfLj6zHLQOrjNncXmURc BmRY8lBOFe12nizTyK4yFMesC7Zfru9XYA/NRduX1TUYxaSHz3s/yUw+hTfv6+Po HYYOa/5yhFDCtik3475FDwQiRcCRdXqniMFT8E3Med0qgGrUcy9+8uODxw7O4F40 AV25b7kyE3BdOoCBSL6cKGhpwfwgvuAYvV6Dcf6pXt/LMEWL6s6+Xcv8LPRkTFTV O8uXXcH8LY9WSHw5SyBOZSO1Ecv+tQ7eJxv6MyzMcbHU46C0zByq5uiWEWdaHBor u4msuJYaqT0YKn6Oni2FHtzMsiqBBxr+QyvpR9GXKDAOXDNEMa81s8KHp9Wt9r7M FUePhEs7rfTSnwh1ib0QAkNZDHUDrRmh3gF1O01RnkFTw02nrhsMBopRZwNO0roX j50BlocQNJf897lXS39QWicYXPaybEunZqchAfQ1tMIB7xptCQmMTDIlJbd5RlQm B7UEVd5alyBqwtdzuAqH9RmRou0+3qUR43pduJzA6wNGcp7PTwtlWx87oDFfhS6u f/7Rvf8ZWpRUNFBZuyzk =Xyfj -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20151119' into staging migration/next for 20151119 # gpg: Signature made Thu 19 Nov 2015 11:17:07 GMT using RSA key ID 5872D723 # gpg: Good signature from "Juan Quintela <quintela@redhat.com>" # gpg: aka "Juan Quintela <quintela@trasno.org>" * remotes/juanquintela/tags/migration/20151119: migration: normalize locking in migration/savevm.c migration: implement bdrv_all_find_vmstate_bs helper migration: reorder processing in hmp_savevm snapshot: create bdrv_all_create_snapshot helper migration: drop find_vmstate_bs check in hmp_delvm snapshot: create bdrv_all_find_snapshot helper migration: factor our snapshottability check in load_vmstate snapshot: create bdrv_all_goto_snapshot helper snapshot: create bdrv_all_delete_snapshot helper snapshot: return error code from bdrv_snapshot_delete_by_id_or_name snapshot: create helper to test that block drivers supports snapshots Unneeded NULL check migration: Dead assignment of current_time Set last_sent_block Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
80fda8f609
134
block/snapshot.c
134
block/snapshot.c
|
@ -253,9 +253,9 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||||
const char *id_or_name,
|
const char *id_or_name,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
@ -270,6 +270,7 @@ void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_snapshot_list(BlockDriverState *bs,
|
int bdrv_snapshot_list(BlockDriverState *bs,
|
||||||
|
@ -356,3 +357,130 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Group operations. All block drivers are involved.
|
||||||
|
* These functions will properly handle dataplane (take aio_context_acquire
|
||||||
|
* when appropriate for appropriate block drivers) */
|
||||||
|
|
||||||
|
bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs)
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
|
||||||
|
while (ok && (bs = bdrv_next(bs))) {
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
if (bdrv_is_inserted(bs) && !bdrv_is_read_only(bs)) {
|
||||||
|
ok = bdrv_can_snapshot(bs);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
*first_bad_bs = bs;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
|
||||||
|
Error **err)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
QEMUSnapshotInfo sn1, *snapshot = &sn1;
|
||||||
|
|
||||||
|
while (ret == 0 && (bs = bdrv_next(bs))) {
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
if (bdrv_can_snapshot(bs) &&
|
||||||
|
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
|
||||||
|
ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
*first_bad_bs = bs;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bad_bs)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
|
||||||
|
while (err == 0 && (bs = bdrv_next(bs))) {
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
if (bdrv_can_snapshot(bs)) {
|
||||||
|
err = bdrv_snapshot_goto(bs, name);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
*first_bad_bs = bs;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs)
|
||||||
|
{
|
||||||
|
QEMUSnapshotInfo sn;
|
||||||
|
int err = 0;
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
|
||||||
|
while (err == 0 && (bs = bdrv_next(bs))) {
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
if (bdrv_can_snapshot(bs)) {
|
||||||
|
err = bdrv_snapshot_find(bs, &sn, name);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
*first_bad_bs = bs;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
|
||||||
|
BlockDriverState *vm_state_bs,
|
||||||
|
uint64_t vm_state_size,
|
||||||
|
BlockDriverState **first_bad_bs)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
|
||||||
|
while (err == 0 && (bs = bdrv_next(bs))) {
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
if (bs == vm_state_bs) {
|
||||||
|
sn->vm_state_size = vm_state_size;
|
||||||
|
err = bdrv_snapshot_create(bs, sn);
|
||||||
|
} else if (bdrv_can_snapshot(bs)) {
|
||||||
|
sn->vm_state_size = 0;
|
||||||
|
err = bdrv_snapshot_create(bs, sn);
|
||||||
|
}
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
*first_bad_bs = bs;
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDriverState *bdrv_all_find_vmstate_bs(void)
|
||||||
|
{
|
||||||
|
bool not_found = true;
|
||||||
|
BlockDriverState *bs = NULL;
|
||||||
|
|
||||||
|
while (not_found && (bs = bdrv_next(bs))) {
|
||||||
|
AioContext *ctx = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(ctx);
|
||||||
|
not_found = !bdrv_can_snapshot(bs);
|
||||||
|
aio_context_release(ctx);
|
||||||
|
}
|
||||||
|
return bs;
|
||||||
|
}
|
||||||
|
|
|
@ -63,9 +63,9 @@ int bdrv_snapshot_delete(BlockDriverState *bs,
|
||||||
const char *snapshot_id,
|
const char *snapshot_id,
|
||||||
const char *name,
|
const char *name,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||||
const char *id_or_name,
|
const char *id_or_name,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
int bdrv_snapshot_list(BlockDriverState *bs,
|
int bdrv_snapshot_list(BlockDriverState *bs,
|
||||||
QEMUSnapshotInfo **psn_info);
|
QEMUSnapshotInfo **psn_info);
|
||||||
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
|
int bdrv_snapshot_load_tmp(BlockDriverState *bs,
|
||||||
|
@ -75,4 +75,22 @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
|
||||||
int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
|
int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
|
||||||
const char *id_or_name,
|
const char *id_or_name,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
|
|
||||||
|
/* Group operations. All block drivers are involved.
|
||||||
|
* These functions will properly handle dataplane (take aio_context_acquire
|
||||||
|
* when appropriate for appropriate block drivers */
|
||||||
|
|
||||||
|
bool bdrv_all_can_snapshot(BlockDriverState **first_bad_bs);
|
||||||
|
int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bsd_bs,
|
||||||
|
Error **err);
|
||||||
|
int bdrv_all_goto_snapshot(const char *name, BlockDriverState **first_bsd_bs);
|
||||||
|
int bdrv_all_find_snapshot(const char *name, BlockDriverState **first_bad_bs);
|
||||||
|
int bdrv_all_create_snapshot(QEMUSnapshotInfo *sn,
|
||||||
|
BlockDriverState *vm_state_bs,
|
||||||
|
uint64_t vm_state_size,
|
||||||
|
BlockDriverState **first_bad_bs);
|
||||||
|
|
||||||
|
BlockDriverState *bdrv_all_find_vmstate_bs(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1345,7 +1345,7 @@ static void *source_return_path_thread(void *opaque)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rp && qemu_file_get_error(rp)) {
|
if (qemu_file_get_error(rp)) {
|
||||||
trace_source_return_path_thread_bad_end();
|
trace_source_return_path_thread_bad_end();
|
||||||
mark_source_rp_bad(ms);
|
mark_source_rp_bad(ms);
|
||||||
}
|
}
|
||||||
|
@ -1643,7 +1643,6 @@ static void *migration_thread(void *opaque)
|
||||||
if (pending_size && pending_size >= max_size) {
|
if (pending_size && pending_size >= max_size) {
|
||||||
/* Still a significant amount to transfer */
|
/* Still a significant amount to transfer */
|
||||||
|
|
||||||
current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
|
||||||
if (migrate_postcopy_ram() &&
|
if (migrate_postcopy_ram() &&
|
||||||
s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE &&
|
s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE &&
|
||||||
pend_nonpost <= max_size &&
|
pend_nonpost <= max_size &&
|
||||||
|
|
|
@ -1249,6 +1249,7 @@ static int ram_save_target_page(MigrationState *ms, QEMUFile *f,
|
||||||
if (unsentmap) {
|
if (unsentmap) {
|
||||||
clear_bit(dirty_ram_abs >> TARGET_PAGE_BITS, unsentmap);
|
clear_bit(dirty_ram_abs >> TARGET_PAGE_BITS, unsentmap);
|
||||||
}
|
}
|
||||||
|
last_sent_block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -1905,46 +1905,6 @@ int qemu_loadvm_state(QEMUFile *f)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BlockDriverState *find_vmstate_bs(void)
|
|
||||||
{
|
|
||||||
BlockDriverState *bs = NULL;
|
|
||||||
while ((bs = bdrv_next(bs))) {
|
|
||||||
if (bdrv_can_snapshot(bs)) {
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deletes snapshots of a given name in all opened images.
|
|
||||||
*/
|
|
||||||
static int del_existing_snapshots(Monitor *mon, const char *name)
|
|
||||||
{
|
|
||||||
BlockDriverState *bs;
|
|
||||||
QEMUSnapshotInfo sn1, *snapshot = &sn1;
|
|
||||||
Error *err = NULL;
|
|
||||||
|
|
||||||
bs = NULL;
|
|
||||||
while ((bs = bdrv_next(bs))) {
|
|
||||||
if (bdrv_can_snapshot(bs) &&
|
|
||||||
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
|
|
||||||
bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
|
|
||||||
if (err) {
|
|
||||||
monitor_printf(mon,
|
|
||||||
"Error while deleting snapshot on device '%s':"
|
|
||||||
" %s\n",
|
|
||||||
bdrv_get_device_name(bs),
|
|
||||||
error_get_pretty(err));
|
|
||||||
error_free(err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hmp_savevm(Monitor *mon, const QDict *qdict)
|
void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs, *bs1;
|
BlockDriverState *bs, *bs1;
|
||||||
|
@ -1957,27 +1917,29 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
const char *name = qdict_get_try_str(qdict, "name");
|
const char *name = qdict_get_try_str(qdict, "name");
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
AioContext *aio_context;
|
||||||
|
|
||||||
/* Verify if there is a device that doesn't support snapshots and is writable */
|
if (!bdrv_all_can_snapshot(&bs)) {
|
||||||
bs = NULL;
|
monitor_printf(mon, "Device '%s' is writable but does not "
|
||||||
while ((bs = bdrv_next(bs))) {
|
"support snapshots.\n", bdrv_get_device_name(bs));
|
||||||
|
return;
|
||||||
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bdrv_can_snapshot(bs)) {
|
|
||||||
monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n",
|
|
||||||
bdrv_get_device_name(bs));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = find_vmstate_bs();
|
/* Delete old snapshots of the same name */
|
||||||
if (!bs) {
|
if (name && bdrv_all_delete_snapshot(name, &bs1, &local_err) < 0) {
|
||||||
|
monitor_printf(mon,
|
||||||
|
"Error while deleting snapshot on device '%s': %s\n",
|
||||||
|
bdrv_get_device_name(bs1), error_get_pretty(local_err));
|
||||||
|
error_free(local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bs = bdrv_all_find_vmstate_bs();
|
||||||
|
if (bs == NULL) {
|
||||||
monitor_printf(mon, "No block device can accept snapshots\n");
|
monitor_printf(mon, "No block device can accept snapshots\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
saved_vm_running = runstate_is_running();
|
saved_vm_running = runstate_is_running();
|
||||||
|
|
||||||
|
@ -1988,6 +1950,8 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||||
}
|
}
|
||||||
vm_stop(RUN_STATE_SAVE_VM);
|
vm_stop(RUN_STATE_SAVE_VM);
|
||||||
|
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
|
||||||
memset(sn, 0, sizeof(*sn));
|
memset(sn, 0, sizeof(*sn));
|
||||||
|
|
||||||
/* fill auxiliary fields */
|
/* fill auxiliary fields */
|
||||||
|
@ -2010,11 +1974,6 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||||
strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
|
strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete old snapshots of the same name */
|
|
||||||
if (name && del_existing_snapshots(mon, name) < 0) {
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the VM state */
|
/* save the VM state */
|
||||||
f = qemu_fopen_bdrv(bs, 1);
|
f = qemu_fopen_bdrv(bs, 1);
|
||||||
if (!f) {
|
if (!f) {
|
||||||
|
@ -2030,22 +1989,14 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create the snapshots */
|
ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs);
|
||||||
|
if (ret < 0) {
|
||||||
bs1 = NULL;
|
monitor_printf(mon, "Error while creating snapshot on '%s'\n",
|
||||||
while ((bs1 = bdrv_next(bs1))) {
|
bdrv_get_device_name(bs));
|
||||||
if (bdrv_can_snapshot(bs1)) {
|
|
||||||
/* Write VM state size only to the image that contains the state */
|
|
||||||
sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
|
|
||||||
ret = bdrv_snapshot_create(bs1, sn);
|
|
||||||
if (ret < 0) {
|
|
||||||
monitor_printf(mon, "Error while creating snapshot on '%s'\n",
|
|
||||||
bdrv_get_device_name(bs1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
the_end:
|
the_end:
|
||||||
|
aio_context_release(aio_context);
|
||||||
if (saved_vm_running) {
|
if (saved_vm_running) {
|
||||||
vm_start();
|
vm_start();
|
||||||
}
|
}
|
||||||
|
@ -2084,15 +2035,31 @@ int load_vmstate(const char *name)
|
||||||
QEMUSnapshotInfo sn;
|
QEMUSnapshotInfo sn;
|
||||||
QEMUFile *f;
|
QEMUFile *f;
|
||||||
int ret;
|
int ret;
|
||||||
|
AioContext *aio_context;
|
||||||
|
|
||||||
bs_vm_state = find_vmstate_bs();
|
if (!bdrv_all_can_snapshot(&bs)) {
|
||||||
|
error_report("Device '%s' is writable but does not support snapshots.",
|
||||||
|
bdrv_get_device_name(bs));
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
ret = bdrv_all_find_snapshot(name, &bs);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("Device '%s' does not have the requested snapshot '%s'",
|
||||||
|
bdrv_get_device_name(bs), name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bs_vm_state = bdrv_all_find_vmstate_bs();
|
||||||
if (!bs_vm_state) {
|
if (!bs_vm_state) {
|
||||||
error_report("No block device supports snapshots");
|
error_report("No block device supports snapshots");
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
aio_context = bdrv_get_aio_context(bs_vm_state);
|
||||||
|
|
||||||
/* Don't even try to load empty VM states */
|
/* Don't even try to load empty VM states */
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
|
ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
|
||||||
|
aio_context_release(aio_context);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
} else if (sn.vm_state_size == 0) {
|
} else if (sn.vm_state_size == 0) {
|
||||||
|
@ -2101,42 +2068,14 @@ int load_vmstate(const char *name)
|
||||||
return -EINVAL;
|
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))) {
|
|
||||||
|
|
||||||
if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bdrv_can_snapshot(bs)) {
|
|
||||||
error_report("Device '%s' is writable but does not support snapshots.",
|
|
||||||
bdrv_get_device_name(bs));
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
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. */
|
/* Flush all IO requests so they don't interfere with the new state. */
|
||||||
bdrv_drain_all();
|
bdrv_drain_all();
|
||||||
|
|
||||||
bs = NULL;
|
ret = bdrv_all_goto_snapshot(name, &bs);
|
||||||
while ((bs = bdrv_next(bs))) {
|
if (ret < 0) {
|
||||||
if (bdrv_can_snapshot(bs)) {
|
error_report("Error %d while activating snapshot '%s' on '%s'",
|
||||||
ret = bdrv_snapshot_goto(bs, name);
|
ret, name, bdrv_get_device_name(bs));
|
||||||
if (ret < 0) {
|
return ret;
|
||||||
error_report("Error %d while activating snapshot '%s' on '%s'",
|
|
||||||
ret, name, bdrv_get_device_name(bs));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore the VM state */
|
/* restore the VM state */
|
||||||
|
@ -2148,9 +2087,12 @@ int load_vmstate(const char *name)
|
||||||
|
|
||||||
qemu_system_reset(VMRESET_SILENT);
|
qemu_system_reset(VMRESET_SILENT);
|
||||||
migration_incoming_state_new(f);
|
migration_incoming_state_new(f);
|
||||||
ret = qemu_loadvm_state(f);
|
|
||||||
|
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
|
ret = qemu_loadvm_state(f);
|
||||||
qemu_fclose(f);
|
qemu_fclose(f);
|
||||||
|
aio_context_release(aio_context);
|
||||||
|
|
||||||
migration_incoming_state_destroy();
|
migration_incoming_state_destroy();
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("Error %d while loading VM state", ret);
|
error_report("Error %d while loading VM state", ret);
|
||||||
|
@ -2166,43 +2108,34 @@ void hmp_delvm(Monitor *mon, const QDict *qdict)
|
||||||
Error *err;
|
Error *err;
|
||||||
const char *name = qdict_get_str(qdict, "name");
|
const char *name = qdict_get_str(qdict, "name");
|
||||||
|
|
||||||
if (!find_vmstate_bs()) {
|
if (bdrv_all_delete_snapshot(name, &bs, &err) < 0) {
|
||||||
monitor_printf(mon, "No block device supports snapshots\n");
|
monitor_printf(mon,
|
||||||
return;
|
"Error while deleting snapshot on device '%s': %s\n",
|
||||||
}
|
bdrv_get_device_name(bs), error_get_pretty(err));
|
||||||
|
error_free(err);
|
||||||
bs = NULL;
|
|
||||||
while ((bs = bdrv_next(bs))) {
|
|
||||||
if (bdrv_can_snapshot(bs)) {
|
|
||||||
err = NULL;
|
|
||||||
bdrv_snapshot_delete_by_id_or_name(bs, name, &err);
|
|
||||||
if (err) {
|
|
||||||
monitor_printf(mon,
|
|
||||||
"Error while deleting snapshot on device '%s':"
|
|
||||||
" %s\n",
|
|
||||||
bdrv_get_device_name(bs),
|
|
||||||
error_get_pretty(err));
|
|
||||||
error_free(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
||||||
{
|
{
|
||||||
BlockDriverState *bs, *bs1;
|
BlockDriverState *bs, *bs1;
|
||||||
QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
|
QEMUSnapshotInfo *sn_tab, *sn;
|
||||||
int nb_sns, i, ret, available;
|
int nb_sns, i;
|
||||||
int total;
|
int total;
|
||||||
int *available_snapshots;
|
int *available_snapshots;
|
||||||
|
AioContext *aio_context;
|
||||||
|
|
||||||
bs = find_vmstate_bs();
|
bs = bdrv_all_find_vmstate_bs();
|
||||||
if (!bs) {
|
if (!bs) {
|
||||||
monitor_printf(mon, "No available block device supports snapshots\n");
|
monitor_printf(mon, "No available block device supports snapshots\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
aio_context = bdrv_get_aio_context(bs);
|
||||||
|
|
||||||
|
aio_context_acquire(aio_context);
|
||||||
nb_sns = bdrv_snapshot_list(bs, &sn_tab);
|
nb_sns = bdrv_snapshot_list(bs, &sn_tab);
|
||||||
|
aio_context_release(aio_context);
|
||||||
|
|
||||||
if (nb_sns < 0) {
|
if (nb_sns < 0) {
|
||||||
monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
|
monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
|
||||||
return;
|
return;
|
||||||
|
@ -2216,21 +2149,7 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
||||||
available_snapshots = g_new0(int, nb_sns);
|
available_snapshots = g_new0(int, nb_sns);
|
||||||
total = 0;
|
total = 0;
|
||||||
for (i = 0; i < nb_sns; i++) {
|
for (i = 0; i < nb_sns; i++) {
|
||||||
sn = &sn_tab[i];
|
if (bdrv_all_find_snapshot(sn_tab[i].id_str, &bs1) == 0) {
|
||||||
available = 1;
|
|
||||||
bs1 = NULL;
|
|
||||||
|
|
||||||
while ((bs1 = bdrv_next(bs1))) {
|
|
||||||
if (bdrv_can_snapshot(bs1) && bs1 != bs) {
|
|
||||||
ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str);
|
|
||||||
if (ret < 0) {
|
|
||||||
available = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (available) {
|
|
||||||
available_snapshots[total] = i;
|
available_snapshots[total] = i;
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue