[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 6/6] qapi: Convert migrate
From: |
Wen Congyang |
Subject: |
Re: [Qemu-devel] [PATCH 6/6] qapi: Convert migrate |
Date: |
Wed, 15 Feb 2012 17:07:16 +0800 |
User-agent: |
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100413 Fedora/3.0.4-2.fc13 Thunderbird/3.0.4 |
At 02/11/2012 03:31 AM, Luiz Capitulino Wrote:
> The migrate command is one of those commands where HMP and QMP completely
> mix up together. This made the conversion to the QAPI (which separates the
> command into QMP and HMP parts) a bit difficult.
>
> The first important change to be noticed is that this commit completes the
> removal of the Monitor object from migration code, started by the previous
> commit.
>
> Another important and tricky change is about supporting the non-detached
> mode. That's, if the user doesn't pass '-d' the migrate command will lock
> the monitor and will only release it when migration is finished.
>
> To support that in the new HMP command (hmp_migrate()), it was necessary
> to create a timer which runs every second and checks if the migration is
> still active. If it's, the timer callback will re-schedule itself to run
> one second in the future. If the migration has already finished, the
> monitor lock is relased and the user can use it normally.
>
> All these changes should be transparent to the user.
>
> Signed-off-by: Anthony Liguori <address@hidden>
> Signed-off-by: Luiz Capitulino <address@hidden>
> ---
> hmp-commands.hx | 3 +-
> hmp.c | 51 +++++++++++++++++++++++++++++++++++++++++
> hmp.h | 1 +
> migration-fd.c | 2 +-
> migration.c | 66
> ++++++++++++++----------------------------------------
> migration.h | 3 --
> qapi-schema.json | 21 +++++++++++++++++
> qmp-commands.hx | 9 +------
> savevm.c | 13 +++++-----
> sysemu.h | 2 +-
> 10 files changed, 100 insertions(+), 71 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 573b823..10d3f1b 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -792,8 +792,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,
> },
>
>
> diff --git a/hmp.c b/hmp.c
> index 8ff8c94..70bd574 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -14,6 +14,7 @@
> */
>
> #include "hmp.h"
> +#include "qemu-timer.h"
> #include "qmp-commands.h"
>
> static void hmp_handle_error(Monitor *mon, Error **errp)
> @@ -851,3 +852,53 @@ void hmp_block_job_cancel(Monitor *mon, const QDict
> *qdict)
>
> hmp_handle_error(mon, &error);
> }
> +
> +typedef struct MigrationStatus
> +{
> + QEMUTimer *timer;
> + Monitor *mon;
> +} 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) {
> + qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock) + 1000);
> + goto out;
> + }
> +
> + monitor_resume(status->mon);
> + qemu_del_timer(status->timer);
> + g_free(status);
> +
> +out:
> + 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 = g_malloc0(sizeof(*status));
> + status->timer = qemu_new_timer_ms(rt_clock, hmp_migrate_status_cb,
> + status);
> + status->mon = mon;
> + monitor_suspend(mon);
> + qemu_mod_timer(status->timer, qemu_get_clock_ms(rt_clock));
> + }
> +}
> diff --git a/hmp.h b/hmp.h
> index 18eecbd..989a613 100644
> --- a/hmp.h
> +++ b/hmp.h
> @@ -58,5 +58,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
> diff --git a/migration-fd.c b/migration-fd.c
> index 5a068c6..99f192d 100644
> --- a/migration-fd.c
> +++ b/migration-fd.c
> @@ -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 = qemu_get_fd(fdname);
> if (s->fd == -1) {
> DPRINTF("fd_migration: invalid file descriptor identifier\n");
> goto err_after_get_fd;
> diff --git a/migration.c b/migration.c
> index 5c5c94c..6f148f9 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -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) {
> @@ -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);
> }
> @@ -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);
It seems that the variable detach is not used now.
Does it mean we always run migration at the background?
Thanks
Wen Congyang
> + 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)
> diff --git a/migration.h b/migration.h
> index 0e44197..691b367 100644
> --- a/migration.h
> +++ b/migration.h
> @@ -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);
> diff --git a/qapi-schema.json b/qapi-schema.json
> index d02ee86..0cdc3ce 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -1582,3 +1582,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 should not
> +# be used.
> +#
> +# Returns: nothing on success
> +#
> +# Since: 0.14.0
> +##
> +{ 'command': 'migrate',
> + 'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' }
> }
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index b5e2ab8..84b348a 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -425,14 +425,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
> diff --git a/savevm.c b/savevm.c
> index 70f5c4f..5fdc3e1 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -1540,14 +1540,13 @@ 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;
> }
> }
> @@ -1698,11 +1697,11 @@ void qemu_savevm_state_cancel(QEMUFile *f)
> }
> }
>
> -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;
> }
> @@ -1836,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;
> }
>
> @@ -2080,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) {
> diff --git a/sysemu.h b/sysemu.h
> index 3a0f683..18c07ca 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -65,7 +65,7 @@ void do_info_snapshots(Monitor *mon);
>
> void qemu_announce_self(void);
>
> -bool qemu_savevm_state_blocked(Monitor *mon);
> +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);
[Qemu-devel] [PATCH 5/6] Purge migration of (almost) everything to do with monitors, Luiz Capitulino, 2012/02/10
Re: [Qemu-devel] [PATCH 5/6] Purge migration of (almost) everything to do with monitors, Juan Quintela, 2012/02/15
[Qemu-devel] [PATCH 6/6] qapi: Convert migrate, Luiz Capitulino, 2012/02/10
Re: [Qemu-devel] [PATCH 6/6] qapi: Convert migrate, Jan Kiszka, 2012/02/15
Re: [Qemu-devel] [PATCH 0/6] qapi: Convert migrate, Jan Kiszka, 2012/02/15