mirror of https://github.com/xemu-project/xemu.git
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;
|
||||
}
|
||||
|
||||
void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||
const char *id_or_name,
|
||||
Error **errp)
|
||||
int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||
const char *id_or_name,
|
||||
Error **errp)
|
||||
{
|
||||
int ret;
|
||||
Error *local_err = NULL;
|
||||
|
@ -270,6 +270,7 @@ void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
|||
if (ret < 0) {
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdrv_snapshot_list(BlockDriverState *bs,
|
||||
|
@ -356,3 +357,130 @@ int bdrv_snapshot_load_tmp_by_id_or_name(BlockDriverState *bs,
|
|||
|
||||
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 *name,
|
||||
Error **errp);
|
||||
void bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||
const char *id_or_name,
|
||||
Error **errp);
|
||||
int bdrv_snapshot_delete_by_id_or_name(BlockDriverState *bs,
|
||||
const char *id_or_name,
|
||||
Error **errp);
|
||||
int bdrv_snapshot_list(BlockDriverState *bs,
|
||||
QEMUSnapshotInfo **psn_info);
|
||||
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,
|
||||
const char *id_or_name,
|
||||
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
|
||||
|
|
|
@ -1345,7 +1345,7 @@ static void *source_return_path_thread(void *opaque)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (rp && qemu_file_get_error(rp)) {
|
||||
if (qemu_file_get_error(rp)) {
|
||||
trace_source_return_path_thread_bad_end();
|
||||
mark_source_rp_bad(ms);
|
||||
}
|
||||
|
@ -1643,7 +1643,6 @@ static void *migration_thread(void *opaque)
|
|||
if (pending_size && pending_size >= max_size) {
|
||||
/* Still a significant amount to transfer */
|
||||
|
||||
current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||
if (migrate_postcopy_ram() &&
|
||||
s->state != MIGRATION_STATUS_POSTCOPY_ACTIVE &&
|
||||
pend_nonpost <= max_size &&
|
||||
|
|
|
@ -1249,6 +1249,7 @@ static int ram_save_target_page(MigrationState *ms, QEMUFile *f,
|
|||
if (unsentmap) {
|
||||
clear_bit(dirty_ram_abs >> TARGET_PAGE_BITS, unsentmap);
|
||||
}
|
||||
last_sent_block = block;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
|
@ -1905,46 +1905,6 @@ int qemu_loadvm_state(QEMUFile *f)
|
|||
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)
|
||||
{
|
||||
BlockDriverState *bs, *bs1;
|
||||
|
@ -1957,27 +1917,29 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
|||
struct tm tm;
|
||||
const char *name = qdict_get_try_str(qdict, "name");
|
||||
Error *local_err = NULL;
|
||||
AioContext *aio_context;
|
||||
|
||||
/* Verify if there is a device that doesn't support snapshots and is writable */
|
||||
bs = NULL;
|
||||
while ((bs = bdrv_next(bs))) {
|
||||
|
||||
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;
|
||||
}
|
||||
if (!bdrv_all_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();
|
||||
if (!bs) {
|
||||
/* Delete old snapshots of the same name */
|
||||
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");
|
||||
return;
|
||||
}
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
saved_vm_running = runstate_is_running();
|
||||
|
||||
|
@ -1988,6 +1950,8 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
|||
}
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
|
||||
memset(sn, 0, sizeof(*sn));
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Delete old snapshots of the same name */
|
||||
if (name && del_existing_snapshots(mon, name) < 0) {
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
/* save the VM state */
|
||||
f = qemu_fopen_bdrv(bs, 1);
|
||||
if (!f) {
|
||||
|
@ -2030,22 +1989,14 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
|||
goto the_end;
|
||||
}
|
||||
|
||||
/* create the snapshots */
|
||||
|
||||
bs1 = NULL;
|
||||
while ((bs1 = bdrv_next(bs1))) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
ret = bdrv_all_create_snapshot(sn, bs, vm_state_size, &bs);
|
||||
if (ret < 0) {
|
||||
monitor_printf(mon, "Error while creating snapshot on '%s'\n",
|
||||
bdrv_get_device_name(bs));
|
||||
}
|
||||
|
||||
the_end:
|
||||
aio_context_release(aio_context);
|
||||
if (saved_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
|
@ -2084,15 +2035,31 @@ int load_vmstate(const char *name)
|
|||
QEMUSnapshotInfo sn;
|
||||
QEMUFile *f;
|
||||
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) {
|
||||
error_report("No block device supports snapshots");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
aio_context = bdrv_get_aio_context(bs_vm_state);
|
||||
|
||||
/* Don't even try to load empty VM states */
|
||||
aio_context_acquire(aio_context);
|
||||
ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
|
||||
aio_context_release(aio_context);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
} else if (sn.vm_state_size == 0) {
|
||||
|
@ -2101,42 +2068,14 @@ int load_vmstate(const char *name)
|
|||
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. */
|
||||
bdrv_drain_all();
|
||||
|
||||
bs = NULL;
|
||||
while ((bs = bdrv_next(bs))) {
|
||||
if (bdrv_can_snapshot(bs)) {
|
||||
ret = bdrv_snapshot_goto(bs, name);
|
||||
if (ret < 0) {
|
||||
error_report("Error %d while activating snapshot '%s' on '%s'",
|
||||
ret, name, bdrv_get_device_name(bs));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = bdrv_all_goto_snapshot(name, &bs);
|
||||
if (ret < 0) {
|
||||
error_report("Error %d while activating snapshot '%s' on '%s'",
|
||||
ret, name, bdrv_get_device_name(bs));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* restore the VM state */
|
||||
|
@ -2148,9 +2087,12 @@ int load_vmstate(const char *name)
|
|||
|
||||
qemu_system_reset(VMRESET_SILENT);
|
||||
migration_incoming_state_new(f);
|
||||
ret = qemu_loadvm_state(f);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
ret = qemu_loadvm_state(f);
|
||||
qemu_fclose(f);
|
||||
aio_context_release(aio_context);
|
||||
|
||||
migration_incoming_state_destroy();
|
||||
if (ret < 0) {
|
||||
error_report("Error %d while loading VM state", ret);
|
||||
|
@ -2166,43 +2108,34 @@ void hmp_delvm(Monitor *mon, const QDict *qdict)
|
|||
Error *err;
|
||||
const char *name = qdict_get_str(qdict, "name");
|
||||
|
||||
if (!find_vmstate_bs()) {
|
||||
monitor_printf(mon, "No block device supports snapshots\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (bdrv_all_delete_snapshot(name, &bs, &err) < 0) {
|
||||
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)
|
||||
{
|
||||
BlockDriverState *bs, *bs1;
|
||||
QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
|
||||
int nb_sns, i, ret, available;
|
||||
QEMUSnapshotInfo *sn_tab, *sn;
|
||||
int nb_sns, i;
|
||||
int total;
|
||||
int *available_snapshots;
|
||||
AioContext *aio_context;
|
||||
|
||||
bs = find_vmstate_bs();
|
||||
bs = bdrv_all_find_vmstate_bs();
|
||||
if (!bs) {
|
||||
monitor_printf(mon, "No available block device supports snapshots\n");
|
||||
return;
|
||||
}
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
aio_context_acquire(aio_context);
|
||||
nb_sns = bdrv_snapshot_list(bs, &sn_tab);
|
||||
aio_context_release(aio_context);
|
||||
|
||||
if (nb_sns < 0) {
|
||||
monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
|
||||
return;
|
||||
|
@ -2216,21 +2149,7 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict)
|
|||
available_snapshots = g_new0(int, nb_sns);
|
||||
total = 0;
|
||||
for (i = 0; i < nb_sns; i++) {
|
||||
sn = &sn_tab[i];
|
||||
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) {
|
||||
if (bdrv_all_find_snapshot(sn_tab[i].id_str, &bs1) == 0) {
|
||||
available_snapshots[total] = i;
|
||||
total++;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue