From: Anthony Liguori <anthony@codemonkey.ws>
To: "Shribman, Aidan" <aidan.shribman@sap.com>
Cc: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [PATCH] Add warmup phase for live migration of large memory apps
Date: Wed, 11 May 2011 08:35:19 -0500 [thread overview]
Message-ID: <4DCA9097.7000609@codemonkey.ws> (raw)
In-Reply-To: <AB5A8C7661872E428D6B8E1C2DFA35085CAA5A80A2@DEWDFECCR02.wdf.sap.corp>
On 05/11/2011 02:58 AM, Shribman, Aidan wrote:
> From: Aidan Shribman<aidan.shribman@sap.com>
>
> [PATCH] Add warmup phase for live migration of large memory apps
>
> By invoking "migrate -w<url>" we initiate a background live-migration
> transferring of dirty pages continuously until invocation of "migrate_end"
> which attempts to complete the live migration operation.
>
> Qemu host: Ubuntu 10.10
>
> Testing: live migration (with/without warmup phase) tested successfully.
>
> Signed-off-by: Benoit Hudzia<benoit.hudzia@sap.com>
> Signed-off-by: Petter Svard<petters@cs.umu.se>
> Signed-off-by: Aidan Shribman<aidan.shribman@sap.com>
If you do:
migrate_set_downtime 0
migrate -d <url>
You'll achieve the same result. The migration will never converge
because there's no way QEMU can meet the downtime expectation.
You can then do:
migrate_set_downtime 30ms
To let migration go. You can even use info migrate to figure out when
migration has been sufficiently warmed up.
You can also always do migrate_cancel to abort the operation.
Regards,
Anthony Liguori
> ---
> hmp-commands.hx | 34 +++++++++++++++++++++++++---------
> migration.c | 23 ++++++++++++++++++++++-
> migration.h | 2 ++
> qmp-commands.hx | 41 ++++++++++++++++++++++++++++++++++-------
> savevm.c | 12 ++++++++++++
> sysemu.h | 1 +
> 6 files changed, 96 insertions(+), 17 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index e5585ba..234a952 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -717,24 +717,27 @@ ETEXI
>
> {
> .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)",
> + .args_type = "detach:-d,blk:-b,inc:-i,warmup:-w,uri:s",
> + .params = "[-d] [-b] [-i] [-w] uri",
> + .help = "migrate to URI"
> + "\n\t -d to not wait for completion"
> + "\n\t -b for migration without shared storage with"
> + " full copy of disk"
> + "\n\t -i for migration without"
> + " shared storage with incremental copy of disk"
> + " (base image shared between source and destination)"
> + "\n\t -w to enter warmup phase",
> .user_print = monitor_user_noop,
> .mhandler.cmd_new = do_migrate,
> },
>
> -
> STEXI
> -@item migrate [-d] [-b] [-i] @var{uri}
> +@item migrate [-d] [-b] [-i] [-w] @var{uri}
> @findex migrate
> Migrate to @var{uri} (using -d to not wait for completion).
> -b for migration with full copy of disk
> -i for migration with incremental copy of disk (base image is shared)
> + -w to enter warmup phase
> ETEXI
>
> {
> @@ -753,6 +756,19 @@ Cancel the current VM migration.
> ETEXI
>
> {
> + .name = "migrate_end",
> + .args_type = "",
> + .params = "",
> + .help = "Complete warmup and move to full live migration",
> + .mhandler.cmd = do_migrate_end,
> + },
> +
> +STEXI
> +@item migrate_end
> +Complete warmup and move to full live migration.
> +ETEXI
> +
> + {
> .name = "migrate_set_speed",
> .args_type = "value:o",
> .params = "value",
> diff --git a/migration.c b/migration.c
> index 9ee8b17..7525b47 100644
> --- a/migration.c
> +++ b/migration.c
> @@ -31,6 +31,8 @@
> do { } while (0)
> #endif
>
> +static int is_migrate_warmup = 0;
> +
> /* Migration speed throttling */
> static uint32_t max_throttle = (32<< 20);
>
> @@ -81,6 +83,11 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
> 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");
> + is_migrate_warmup = qdict_get_try_bool(qdict, "warmup", 0);
> +
> + if (is_migrate_warmup) {
> + detach = 1; /* as we need migrate_end to complte */
> + }
>
> if (current_migration&&
> current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
> @@ -361,7 +368,9 @@ void migrate_fd_put_ready(void *opaque)
> }
>
> DPRINTF("iterate\n");
> - if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
> + if (is_migrate_warmup) {
> + qemu_savevm_state_warmup(s->mon, s->file);
> + } else if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
> int state;
> int old_vm_running = vm_running;
>
> @@ -448,3 +457,15 @@ int migrate_fd_close(void *opaque)
> qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
> return s->close(s);
> }
> +
> +void do_migrate_end(Monitor *mon, const QDict *qdict)
> +{
> + if (!vm_running) {
> + return;
> + }
> + if (!is_migrate_warmup) {
> + return;
> + }
> + is_migrate_warmup = 0;
> +}
> +
> diff --git a/migration.h b/migration.h
> index d13ed4f..6a96b29 100644
> --- a/migration.h
> +++ b/migration.h
> @@ -134,4 +134,6 @@ static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state)
> return container_of(mig_state, FdMigrationState, mig_state);
> }
>
> +void do_migrate_end(Monitor *mon, const QDict *qdict);
> +
> #endif
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 793cf1c..58fe696 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -431,13 +431,16 @@ 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)",
> + .args_type = "detach:-d,blk:-b,inc:-i,xbrle:-x,warmup:-w,uri:s",
> + .params = "[-d] [-b] [-i] [-w] uri",
> + .help = "migrate to URI"
> + "\n\t -d to not wait for completion"
> + "\n\t -b for migration without shared storage with"
> + " full copy of disk"
> + "\n\t -i for migration without"
> + " shared storage with incremental copy of disk"
> + " (base image shared between source and destination)"
> + "\n\t -w to enter warmup phase",
> .user_print = monitor_user_noop,
> .mhandler.cmd_new = do_migrate,
> },
> @@ -453,6 +456,7 @@ Arguments:
> - "blk": block migration, full disk copy (json-bool, optional)
> - "inc": incremental disk copy (json-bool, optional)
> - "uri": Destination URI (json-string)
> +- "warmup":to enter warmup phasen
>
> Example:
>
> @@ -494,6 +498,29 @@ Example:
> EQMP
>
> {
> + .name = "migrate_end",
> + .args_type = "",
> + .params = "",
> + .help = "Complete warmup and move to full live migration",
> + .mhandler.cmd = do_migrate_end,
> + },
> +
> +SQMP
> +migrate_end
> +-----------
> +
> +End the current migration warmup.
> +
> +Arguments: None.
> +
> +Example:
> +
> +-> { "execute": "migrate_end" }
> +<- { "return": {} }
> +
> +EQMP
> +
> + {
> .name = "migrate_set_speed",
> .args_type = "value:f",
> .params = "value",
> diff --git a/savevm.c b/savevm.c
> index 4e49765..521589c 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -1471,6 +1471,18 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
> return 0;
> }
>
> +int qemu_savevm_state_warmup(Monitor *mon, QEMUFile *f) {
> + int ret = 1;
> +
> + ret = qemu_savevm_state_iterate(mon, f);
> +
> + if (ret == -EIO) {
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
> {
> SaveStateEntry *se;
> diff --git a/sysemu.h b/sysemu.h
> index b81a70e..74e8a48 100644
> --- a/sysemu.h
> +++ b/sysemu.h
> @@ -76,6 +76,7 @@ void main_loop_wait(int nonblocking);
> 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_warmup(Monitor *mon, QEMUFile *f);
> int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
> void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
> int qemu_loadvm_state(QEMUFile *f);
next prev parent reply other threads:[~2011-05-11 13:35 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-11 7:58 [Qemu-devel] [PATCH] Add warmup phase for live migration of large memory apps Shribman, Aidan
2011-05-11 9:19 ` Stefan Hajnoczi
2011-05-12 8:42 ` Shribman, Aidan
2011-05-12 10:39 ` Juan Quintela
2011-05-12 10:54 ` Isaku Yamahata
2011-05-13 2:55 ` Yoshiaki Tamura
2011-05-15 14:25 ` Shribman, Aidan
2011-05-11 13:35 ` Anthony Liguori [this message]
2011-05-11 14:23 ` Shribman, Aidan
2011-05-12 10:57 ` Juan Quintela
2011-05-12 11:23 ` Shribman, Aidan
2011-05-12 13:12 ` Anthony Liguori
2011-05-12 10:55 ` Juan Quintela
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4DCA9097.7000609@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=aidan.shribman@sap.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.