Merge remote-tracking branch 'qmp/queue/qmp' into staging

* qmp/queue/qmp:
  qapi: Convert migrate
  Purge migration of (almost) everything to do with monitors
  Error: Introduce error_copy()
  QError: Introduce new errors for the migration command
This commit is contained in:
Anthony Liguori 2012-03-19 08:51:06 -05:00
commit 5c20f4e54a
17 changed files with 205 additions and 132 deletions

View File

@ -260,7 +260,7 @@ static void sort_ram_list(void)
g_free(blocks);
}
int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
int ram_save_live(QEMUFile *f, int stage, void *opaque)
{
ram_addr_t addr;
uint64_t bytes_transferred_last;

View File

@ -18,7 +18,6 @@
#include "hw/hw.h"
#include "qemu-queue.h"
#include "qemu-timer.h"
#include "monitor.h"
#include "block-migration.h"
#include "migration.h"
#include "blockdev.h"
@ -204,8 +203,7 @@ static void blk_mig_read_cb(void *opaque, int ret)
assert(block_mig_state.submitted >= 0);
}
static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
BlkMigDevState *bmds)
static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
{
int64_t total_sectors = bmds->total_sectors;
int64_t cur_sector = bmds->cur_sector;
@ -272,7 +270,6 @@ static void set_dirty_tracking(int enable)
static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
{
Monitor *mon = opaque;
BlkMigDevState *bmds;
int64_t sectors;
@ -295,19 +292,17 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
block_mig_state.total_sector_sum += sectors;
if (bmds->shared_base) {
monitor_printf(mon, "Start migration for %s with shared base "
"image\n",
bs->device_name);
DPRINTF("Start migration for %s with shared base image\n",
bs->device_name);
} else {
monitor_printf(mon, "Start full migration for %s\n",
bs->device_name);
DPRINTF("Start full migration for %s\n", bs->device_name);
}
QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
}
}
static void init_blk_migration(Monitor *mon, QEMUFile *f)
static void init_blk_migration(QEMUFile *f)
{
block_mig_state.submitted = 0;
block_mig_state.read_done = 0;
@ -318,10 +313,10 @@ static void init_blk_migration(Monitor *mon, QEMUFile *f)
block_mig_state.total_time = 0;
block_mig_state.reads = 0;
bdrv_iterate(init_blk_migration_it, mon);
bdrv_iterate(init_blk_migration_it, NULL);
}
static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
static int blk_mig_save_bulked_block(QEMUFile *f)
{
int64_t completed_sector_sum = 0;
BlkMigDevState *bmds;
@ -330,7 +325,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
if (bmds->bulk_completed == 0) {
if (mig_save_device_bulk(mon, f, bmds) == 1) {
if (mig_save_device_bulk(f, bmds) == 1) {
/* completed bulk section for this device */
bmds->bulk_completed = 1;
}
@ -352,8 +347,7 @@ static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
block_mig_state.prev_progress = progress;
qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
| BLK_MIG_FLAG_PROGRESS);
monitor_printf(mon, "Completed %d %%\r", progress);
monitor_flush(mon);
DPRINTF("Completed %d %%\r", progress);
}
return ret;
@ -368,8 +362,8 @@ static void blk_mig_reset_dirty_cursor(void)
}
}
static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
BlkMigDevState *bmds, int is_async)
static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
int is_async)
{
BlkMigBlock *blk;
int64_t total_sectors = bmds->total_sectors;
@ -428,20 +422,20 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
return (bmds->cur_dirty >= bmds->total_sectors);
error:
monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector);
DPRINTF("Error reading sector %" PRId64 "\n", sector);
qemu_file_set_error(f, ret);
g_free(blk->buf);
g_free(blk);
return 0;
}
static int blk_mig_save_dirty_block(Monitor *mon, QEMUFile *f, int is_async)
static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
{
BlkMigDevState *bmds;
int ret = 0;
QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
if (mig_save_device_dirty(mon, f, bmds, is_async) == 0) {
if (mig_save_device_dirty(f, bmds, is_async) == 0) {
ret = 1;
break;
}
@ -520,7 +514,7 @@ static int is_stage2_completed(void)
return 0;
}
static void blk_mig_cleanup(Monitor *mon)
static void blk_mig_cleanup(void)
{
BlkMigDevState *bmds;
BlkMigBlock *blk;
@ -540,11 +534,9 @@ static void blk_mig_cleanup(Monitor *mon)
g_free(blk->buf);
g_free(blk);
}
monitor_printf(mon, "\n");
}
static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
static int block_save_live(QEMUFile *f, int stage, void *opaque)
{
int ret;
@ -552,7 +544,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
stage, block_mig_state.submitted, block_mig_state.transferred);
if (stage < 0) {
blk_mig_cleanup(mon);
blk_mig_cleanup();
return 0;
}
@ -563,7 +555,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
}
if (stage == 1) {
init_blk_migration(mon, f);
init_blk_migration(f);
/* start track dirty blocks */
set_dirty_tracking(1);
@ -573,7 +565,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
ret = qemu_file_get_error(f);
if (ret) {
blk_mig_cleanup(mon);
blk_mig_cleanup();
return ret;
}
@ -586,12 +578,12 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
qemu_file_get_rate_limit(f)) {
if (block_mig_state.bulk_completed == 0) {
/* first finish the bulk phase */
if (blk_mig_save_bulked_block(mon, f) == 0) {
if (blk_mig_save_bulked_block(f) == 0) {
/* finished saving bulk on all devices */
block_mig_state.bulk_completed = 1;
}
} else {
if (blk_mig_save_dirty_block(mon, f, 1) == 0) {
if (blk_mig_save_dirty_block(f, 1) == 0) {
/* no more dirty blocks */
break;
}
@ -602,7 +594,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
ret = qemu_file_get_error(f);
if (ret) {
blk_mig_cleanup(mon);
blk_mig_cleanup();
return ret;
}
}
@ -612,8 +604,8 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
all async read completed */
assert(block_mig_state.submitted == 0);
while (blk_mig_save_dirty_block(mon, f, 0) != 0);
blk_mig_cleanup(mon);
while (blk_mig_save_dirty_block(f, 0) != 0);
blk_mig_cleanup();
/* report completion */
qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
@ -623,7 +615,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
return ret;
}
monitor_printf(mon, "Block migration completed\n");
DPRINTF("Block migration completed\n");
}
qemu_put_be64(f, BLK_MIG_FLAG_EOS);

13
error.c
View File

@ -43,6 +43,19 @@ void error_set(Error **errp, const char *fmt, ...)
*errp = err;
}
Error *error_copy(const Error *err)
{
Error *err_new;
err_new = g_malloc0(sizeof(*err));
err_new->msg = g_strdup(err->msg);
err_new->fmt = err->fmt;
err_new->obj = err->obj;
QINCREF(err_new->obj);
return err_new;
}
bool error_is_set(Error **errp)
{
return (errp && *errp);

View File

@ -34,6 +34,11 @@ void error_set(Error **err, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
*/
bool error_is_set(Error **err);
/**
* Returns an exact copy of the error passed as an argument.
*/
Error *error_copy(const Error *err);
/**
* Get a human readable representation of an error object.
*/

View File

@ -806,8 +806,7 @@ ETEXI
" full copy of disk\n\t\t\t -i for migration without "
"shared storage with incremental copy of disk "
"(base image shared between src and destination)",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_migrate,
.mhandler.cmd = hmp_migrate,
},

74
hmp.c
View File

@ -14,6 +14,7 @@
*/
#include "hmp.h"
#include "qemu-timer.h"
#include "qmp-commands.h"
static void hmp_handle_error(Monitor *mon, Error **errp)
@ -860,3 +861,76 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &error);
}
typedef struct MigrationStatus
{
QEMUTimer *timer;
Monitor *mon;
bool is_block_migration;
} MigrationStatus;
static void hmp_migrate_status_cb(void *opaque)
{
MigrationStatus *status = opaque;
MigrationInfo *info;
info = qmp_query_migrate(NULL);
if (!info->has_status || strcmp(info->status, "active") == 0) {
if (info->has_disk) {
int progress;
if (info->disk->remaining) {
progress = info->disk->transferred * 100 / info->disk->total;
} else {
progress = 100;
}
monitor_printf(status->mon, "Completed %d %%\r", progress);
monitor_flush(status->mon);
}
qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock) + 1000);
} else {
if (status->is_block_migration) {
monitor_printf(status->mon, "\n");
}
monitor_resume(status->mon);
qemu_del_timer(status->timer);
g_free(status);
}
qapi_free_MigrationInfo(info);
}
void hmp_migrate(Monitor *mon, const QDict *qdict)
{
int detach = qdict_get_try_bool(qdict, "detach", 0);
int blk = qdict_get_try_bool(qdict, "blk", 0);
int inc = qdict_get_try_bool(qdict, "inc", 0);
const char *uri = qdict_get_str(qdict, "uri");
Error *err = NULL;
qmp_migrate(uri, !!blk, blk, !!inc, inc, false, false, &err);
if (err) {
monitor_printf(mon, "migrate: %s\n", error_get_pretty(err));
error_free(err);
return;
}
if (!detach) {
MigrationStatus *status;
if (monitor_suspend(mon) < 0) {
monitor_printf(mon, "terminal does not allow synchronous "
"migration, continuing detached\n");
return;
}
status = g_malloc0(sizeof(*status));
status->mon = mon;
status->is_block_migration = blk || inc;
status->timer = qemu_new_timer_ms(rt_clock, hmp_migrate_status_cb,
status);
qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock));
}
}

1
hmp.h
View File

@ -59,5 +59,6 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
void hmp_block_stream(Monitor *mon, const QDict *qdict);
void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
void hmp_migrate(Monitor *mon, const QDict *qdict);
#endif

View File

@ -75,7 +75,7 @@ static int fd_close(MigrationState *s)
int fd_start_outgoing_migration(MigrationState *s, const char *fdname)
{
s->fd = monitor_get_fd(s->mon, fdname);
s->fd = monitor_get_fd(cur_mon, fdname);
if (s->fd == -1) {
DPRINTF("fd_migration: invalid file descriptor identifier\n");
goto err_after_get_fd;

View File

@ -158,16 +158,6 @@ MigrationInfo *qmp_query_migrate(Error **errp)
/* shared migration helpers */
static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
{
if (monitor_suspend(mon) == 0) {
DPRINTF("suspending monitor\n");
} else {
monitor_printf(mon, "terminal does not allow synchronous "
"migration, continuing detached\n");
}
}
static int migrate_fd_cleanup(MigrationState *s)
{
int ret = 0;
@ -178,10 +168,6 @@ static int migrate_fd_cleanup(MigrationState *s)
DPRINTF("closing file\n");
ret = qemu_fclose(s->file);
s->file = NULL;
} else {
if (s->mon) {
monitor_resume(s->mon);
}
}
if (s->fd != -1) {
@ -258,7 +244,7 @@ static void migrate_fd_put_ready(void *opaque)
}
DPRINTF("iterate\n");
ret = qemu_savevm_state_iterate(s->mon, s->file);
ret = qemu_savevm_state_iterate(s->file);
if (ret < 0) {
migrate_fd_error(s);
} else if (ret == 1) {
@ -267,7 +253,7 @@ static void migrate_fd_put_ready(void *opaque)
DPRINTF("done iterating\n");
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
if (qemu_savevm_state_complete(s->file) < 0) {
migrate_fd_error(s);
} else {
migrate_fd_completed(s);
@ -289,7 +275,7 @@ static void migrate_fd_cancel(MigrationState *s)
s->state = MIG_STATE_CANCELLED;
notifier_list_notify(&migration_state_notifiers, s);
qemu_savevm_state_cancel(s->mon, s->file);
qemu_savevm_state_cancel(s->file);
migrate_fd_cleanup(s);
}
@ -321,9 +307,6 @@ static int migrate_fd_close(void *opaque)
{
MigrationState *s = opaque;
if (s->mon) {
monitor_resume(s->mon);
}
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
return s->close(s);
}
@ -367,7 +350,7 @@ void migrate_fd_connect(MigrationState *s)
migrate_fd_close);
DPRINTF("beginning savevm\n");
ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
ret = qemu_savevm_state_begin(s->file, s->blk, s->shared);
if (ret < 0) {
DPRINTF("failed, %d\n", ret);
migrate_fd_error(s);
@ -376,7 +359,7 @@ void migrate_fd_connect(MigrationState *s)
migrate_fd_put_ready(s);
}
static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
static MigrationState *migrate_init(int blk, int inc)
{
MigrationState *s = migrate_get_current();
int64_t bandwidth_limit = s->bandwidth_limit;
@ -386,18 +369,9 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
s->blk = blk;
s->shared = inc;
/* s->mon is used for two things:
- pass fd in fd migration
- suspend/resume monitor for not detached migration
*/
s->mon = mon;
s->bandwidth_limit = bandwidth_limit;
s->state = MIG_STATE_SETUP;
if (!detach) {
migrate_fd_monitor_suspend(s, mon);
}
return s;
}
@ -413,32 +387,29 @@ void migrate_del_blocker(Error *reason)
migration_blockers = g_slist_remove(migration_blockers, reason);
}
int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
void qmp_migrate(const char *uri, bool has_blk, bool blk,
bool has_inc, bool inc, bool has_detach, bool detach,
Error **errp)
{
MigrationState *s = migrate_get_current();
const char *p;
int detach = qdict_get_try_bool(qdict, "detach", 0);
int blk = qdict_get_try_bool(qdict, "blk", 0);
int inc = qdict_get_try_bool(qdict, "inc", 0);
const char *uri = qdict_get_str(qdict, "uri");
int ret;
if (s->state == MIG_STATE_ACTIVE) {
monitor_printf(mon, "migration already in progress\n");
return -1;
error_set(errp, QERR_MIGRATION_ACTIVE);
return;
}
if (qemu_savevm_state_blocked(mon)) {
return -1;
if (qemu_savevm_state_blocked(errp)) {
return;
}
if (migration_blockers) {
Error *err = migration_blockers->data;
qerror_report_err(err);
return -1;
*errp = error_copy(migration_blockers->data);
return;
}
s = migrate_init(mon, detach, blk, inc);
s = migrate_init(blk, inc);
if (strstart(uri, "tcp:", &p)) {
ret = tcp_start_outgoing_migration(s, p);
@ -451,21 +422,18 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
ret = fd_start_outgoing_migration(s, p);
#endif
} else {
monitor_printf(mon, "unknown migration protocol: %s\n", uri);
ret = -EINVAL;
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
return;
}
if (ret < 0) {
monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
return ret;
}
if (detach) {
s->mon = NULL;
DPRINTF("migration failed: %s\n", strerror(-ret));
/* FIXME: we should return meaningful errors */
error_set(errp, QERR_UNDEFINED_ERROR);
return;
}
notifier_list_notify(&migration_state_notifiers, s);
return 0;
}
void qmp_migrate_cancel(Error **errp)

View File

@ -26,7 +26,6 @@ struct MigrationState
int64_t bandwidth_limit;
QEMUFile *file;
int fd;
Monitor *mon;
int state;
int (*get_error)(MigrationState *s);
int (*close)(MigrationState *s);
@ -40,8 +39,6 @@ void process_incoming_migration(QEMUFile *f);
int qemu_start_incoming_migration(const char *uri);
int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
uint64_t migrate_max_downtime(void);
void do_info_migrate_print(Monitor *mon, const QObject *data);
@ -78,7 +75,7 @@ uint64_t ram_bytes_remaining(void);
uint64_t ram_bytes_transferred(void);
uint64_t ram_bytes_total(void);
int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
int ram_save_live(QEMUFile *f, int stage, void *opaque);
int ram_load(QEMUFile *f, void *opaque, int version_id);
/**

View File

@ -1663,3 +1663,24 @@
{ 'command': 'qom-list-types',
'data': { '*implements': 'str', '*abstract': 'bool' },
'returns': [ 'ObjectTypeInfo' ] }
##
# @migrate
#
# Migrates the current running guest to another Virtual Machine.
#
# @uri: the Uniform Resource Identifier of the destination VM
#
# @blk: #optional do block migration (full disk copy)
#
# @inc: #optional incremental disk copy migration
#
# @detach: this argument exists only for compatibility reasons and
# is ignored by QEMU
#
# Returns: nothing on success
#
# Since: 0.14.0
##
{ 'command': 'migrate',
'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }

View File

@ -192,6 +192,14 @@ static const QErrorStringTable qerror_table[] = {
.error_fmt = QERR_KVM_MISSING_CAP,
.desc = "Using KVM without %(capability), %(feature) unavailable",
},
{
.error_fmt = QERR_MIGRATION_ACTIVE,
.desc = "There's a migration process in progress",
},
{
.error_fmt = QERR_MIGRATION_NOT_SUPPORTED,
.desc = "State blocked by non-migratable device '%(device)'",
},
{
.error_fmt = QERR_MIGRATION_EXPECTED,
.desc = "An incoming migration is expected before this command can be executed",

View File

@ -166,6 +166,12 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_KVM_MISSING_CAP \
"{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
#define QERR_MIGRATION_ACTIVE \
"{ 'class': 'MigrationActive', 'data': {} }"
#define QERR_MIGRATION_NOT_SUPPORTED \
"{ 'class': 'MigrationNotSupported', 'data': {'device': %s} }"
#define QERR_MIGRATION_EXPECTED \
"{ 'class': 'MigrationExpected', 'data': {} }"

View File

@ -446,14 +446,7 @@ EQMP
{
.name = "migrate",
.args_type = "detach:-d,blk:-b,inc:-i,uri:s",
.params = "[-d] [-b] [-i] uri",
.help = "migrate to URI (using -d to not wait for completion)"
"\n\t\t\t -b for migration without shared storage with"
" full copy of disk\n\t\t\t -i for migration without "
"shared storage with incremental copy of disk "
"(base image shared between src and destination)",
.user_print = monitor_user_noop,
.mhandler.cmd_new = do_migrate,
.mhandler.cmd_new = qmp_marshal_input_migrate,
},
SQMP

View File

@ -1540,22 +1540,20 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
#define QEMU_VM_SECTION_FULL 0x04
#define QEMU_VM_SUBSECTION 0x05
bool qemu_savevm_state_blocked(Monitor *mon)
bool qemu_savevm_state_blocked(Error **errp)
{
SaveStateEntry *se;
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
if (se->no_migrate) {
monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
se->idstr);
error_set(errp, QERR_MIGRATION_NOT_SUPPORTED, se->idstr);
return true;
}
}
return false;
}
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
int shared)
int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared)
{
SaveStateEntry *se;
int ret;
@ -1588,15 +1586,15 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
ret = se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
if (ret < 0) {
qemu_savevm_state_cancel(mon, f);
qemu_savevm_state_cancel(f);
return ret;
}
}
ret = qemu_file_get_error(f);
if (ret != 0) {
qemu_savevm_state_cancel(mon, f);
qemu_savevm_state_cancel(f);
}
return ret;
@ -1609,7 +1607,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
* 0 : We haven't finished, caller have to go again
* 1 : We have finished, we can go to complete phase
*/
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
int qemu_savevm_state_iterate(QEMUFile *f)
{
SaveStateEntry *se;
int ret = 1;
@ -1622,7 +1620,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
qemu_put_byte(f, QEMU_VM_SECTION_PART);
qemu_put_be32(f, se->section_id);
ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
ret = se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
if (ret <= 0) {
/* Do not proceed to the next vmstate before this one reported
completion of the current stage. This serializes the migration
@ -1636,12 +1634,12 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
}
ret = qemu_file_get_error(f);
if (ret != 0) {
qemu_savevm_state_cancel(mon, f);
qemu_savevm_state_cancel(f);
}
return ret;
}
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
int qemu_savevm_state_complete(QEMUFile *f)
{
SaveStateEntry *se;
int ret;
@ -1656,7 +1654,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
qemu_put_byte(f, QEMU_VM_SECTION_END);
qemu_put_be32(f, se->section_id);
ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
ret = se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
if (ret < 0) {
return ret;
}
@ -1688,37 +1686,37 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
return qemu_file_get_error(f);
}
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
void qemu_savevm_state_cancel(QEMUFile *f)
{
SaveStateEntry *se;
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
if (se->save_live_state) {
se->save_live_state(mon, f, -1, se->opaque);
se->save_live_state(f, -1, se->opaque);
}
}
}
static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
static int qemu_savevm_state(QEMUFile *f)
{
int ret;
if (qemu_savevm_state_blocked(mon)) {
if (qemu_savevm_state_blocked(NULL)) {
ret = -EINVAL;
goto out;
}
ret = qemu_savevm_state_begin(mon, f, 0, 0);
ret = qemu_savevm_state_begin(f, 0, 0);
if (ret < 0)
goto out;
do {
ret = qemu_savevm_state_iterate(mon, f);
ret = qemu_savevm_state_iterate(f);
if (ret < 0)
goto out;
} while (ret == 0);
ret = qemu_savevm_state_complete(mon, f);
ret = qemu_savevm_state_complete(f);
out:
if (ret == 0) {
@ -1837,7 +1835,7 @@ int qemu_loadvm_state(QEMUFile *f)
unsigned int v;
int ret;
if (qemu_savevm_state_blocked(default_mon)) {
if (qemu_savevm_state_blocked(NULL)) {
return -EINVAL;
}
@ -2081,7 +2079,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
monitor_printf(mon, "Could not open VM state file\n");
goto the_end;
}
ret = qemu_savevm_state(mon, f);
ret = qemu_savevm_state(f);
vm_state_size = qemu_ftell(f);
qemu_fclose(f);
if (ret < 0) {

View File

@ -76,12 +76,11 @@ void do_info_snapshots(Monitor *mon);
void qemu_announce_self(void);
bool qemu_savevm_state_blocked(Monitor *mon);
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
int shared);
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
bool qemu_savevm_state_blocked(Error **errp);
int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared);
int qemu_savevm_state_iterate(QEMUFile *f);
int qemu_savevm_state_complete(QEMUFile *f);
void qemu_savevm_state_cancel(QEMUFile *f);
int qemu_loadvm_state(QEMUFile *f);
/* SLIRP */

View File

@ -28,8 +28,7 @@
typedef void SaveSetParamsHandler(int blk_enable, int shared, void * opaque);
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
void *opaque);
typedef int SaveLiveStateHandler(QEMUFile *f, int stage, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
int register_savevm(DeviceState *dev,