From patchwork Wed May 11 07:58:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Shribman, Aidan" X-Patchwork-Id: 95114 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id AA0931007ED for ; Wed, 11 May 2011 18:19:31 +1000 (EST) Received: from localhost ([::1]:53782 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QK4dj-0001ik-Bx for incoming@patchwork.ozlabs.org; Wed, 11 May 2011 04:19:27 -0400 Received: from eggs.gnu.org ([140.186.70.92]:57135) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QK4dU-0001if-U0 for qemu-devel@nongnu.org; Wed, 11 May 2011 04:19:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QK4dT-0006Up-BQ for qemu-devel@nongnu.org; Wed, 11 May 2011 04:19:12 -0400 Received: from smtpgw02.sap-ag.de ([155.56.66.97]:12679 helo=smtpgw.sap-ag.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QK4dS-0006UR-V8 for qemu-devel@nongnu.org; Wed, 11 May 2011 04:19:11 -0400 From: "Shribman, Aidan" To: "qemu-devel@nongnu.org" Date: Wed, 11 May 2011 09:58:13 +0200 Thread-Topic: [PATCH] Add warmup phase for live migration of large memory apps Thread-Index: AcwPsS2U9tEZ8yKTQYinCdyF86aHhA== Message-ID: Accept-Language: en-US, de-DE Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: acceptlanguage: en-US, de-DE MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Windows 2000 SP2+, XP SP1+ (seldom 98) X-Received-From: 155.56.66.97 Subject: [Qemu-devel] [PATCH] Add warmup phase for live migration of large memory apps X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Aidan Shribman [PATCH] Add warmup phase for live migration of large memory apps By invoking "migrate -w " 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 Signed-off-by: Petter Svard Signed-off-by: Aidan Shribman --- 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);