From patchwork Wed Aug 22 12:32:03 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Grall X-Patchwork-Id: 179395 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 87E2C2C00A6 for ; Thu, 23 Aug 2012 05:51:13 +1000 (EST) Received: from localhost ([::1]:52569 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T4GxL-0000gP-N6 for incoming@patchwork.ozlabs.org; Wed, 22 Aug 2012 15:51:11 -0400 Received: from eggs.gnu.org ([208.118.235.92]:55246) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T4G5S-0003Gm-Sp for qemu-devel@nongnu.org; Wed, 22 Aug 2012 14:55:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T4G5P-0007lk-RL for qemu-devel@nongnu.org; Wed, 22 Aug 2012 14:55:30 -0400 Received: from smtp.citrix.com ([66.165.176.89]:13432) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T4G5P-0007FA-Hm for qemu-devel@nongnu.org; Wed, 22 Aug 2012 14:55:27 -0400 X-IronPort-AV: E=Sophos;i="4.80,809,1344225600"; d="scan'208";a="35484818" Received: from ftlpmailmx01.citrite.net ([10.13.107.65]) by FTLPIPO01.CITRIX.COM with ESMTP/TLS/RC4-MD5; 22 Aug 2012 14:55:27 -0400 Received: from meteora.cam.xci-test.com (10.80.248.22) by smtprelay.citrix.com (10.13.107.65) with Microsoft SMTP Server id 8.3.213.0; Wed, 22 Aug 2012 14:55:26 -0400 From: Julien Grall To: qemu-devel@nongnu.org Date: Wed, 22 Aug 2012 13:32:03 +0100 Message-ID: <0daed9ef86102101bbc23a26ac887d751aa8f8ae.1345552068.git.julien.grall@citrix.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 66.165.176.89 Cc: Julien Grall , christian.limpach@gmail.com, Stefano.Stabellini@eu.citrix.com, xen-devel@lists.xen.org Subject: [Qemu-devel] [XEN][RFC PATCH V2 17/17] xl: implement save/restore for multiple device models 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 Each device model will be save/restore one by one. Signed-off-by: Julien Grall --- tools/libxl/libxl.c | 5 +- tools/libxl/libxl_dom.c | 143 ++++++++++++++++++++++++++++++++++-------- tools/libxl/libxl_internal.h | 16 +++-- 3 files changed, 130 insertions(+), 34 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 60718b6..e9d14e8 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -416,7 +416,7 @@ int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid, int suspend_cancel) } if (type == LIBXL_DOMAIN_TYPE_HVM) { - rc = libxl__domain_resume_device_model(gc, domid); + rc = libxl__domain_resume_device_models(gc, domid); if (rc) { LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "failed to resume device model for domain %u:%d", @@ -852,8 +852,9 @@ int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid) path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid); state = libxl__xs_read(gc, XBT_NULL, path); if (state != NULL && !strcmp(state, "paused")) { + /* FIXME: handle multiple qemu */ libxl__qemu_traditional_cmd(gc, domid, "continue"); - libxl__wait_for_device_model(gc, domid, "running", + libxl__wait_for_device_model(gc, domid, 0, "running", NULL, NULL, NULL); } } diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 475fea8..cd07140 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -582,6 +582,7 @@ int libxl__qemu_traditional_cmd(libxl__gc *gc, uint32_t domid, } struct libxl__physmap_info { + libxl_dmid device_model; uint64_t phys_offset; uint64_t start_addr; uint64_t size; @@ -640,6 +641,10 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf, pi = (struct libxl__physmap_info*) ptr; ptr += sizeof(struct libxl__physmap_info) + pi->namelen; + xs_path = restore_helper(gc, domid, pi->phys_offset, "device_model"); + ret = libxl__xs_write(gc, 0, xs_path, "%u", pi->device_model); + if (ret) + return -1; xs_path = restore_helper(gc, domid, pi->phys_offset, "start_addr"); ret = libxl__xs_write(gc, 0, xs_path, "%"PRIx64, pi->start_addr); if (ret) @@ -839,27 +844,28 @@ static void switch_logdirty_done(libxl__egc *egc, /*----- callbacks, called by xc_domain_save -----*/ -int libxl__domain_suspend_device_model(libxl__gc *gc, - libxl__domain_suspend_state *dss) +static int libxl__domain_suspend_device_model(libxl__gc *gc, + libxl_dmid dmid, + libxl__domain_suspend_state *dss) { libxl_ctx *ctx = libxl__gc_owner(gc); int ret = 0; uint32_t const domid = dss->domid; - const char *const filename = dss->dm_savefile; + const char *const filename = libxl__device_model_savefile(gc, domid, dmid); switch (libxl__device_model_version_running(gc, domid)) { case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: { LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Saving device model state to %s", filename); libxl__qemu_traditional_cmd(gc, domid, "save"); - libxl__wait_for_device_model(gc, domid, "paused", NULL, NULL, NULL); + libxl__wait_for_device_model(gc, domid, 0, "paused", NULL, NULL, NULL); break; } case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: - if (libxl__qmp_stop(gc, domid)) + if (libxl__qmp_stop(gc, domid, dmid)) return ERROR_FAIL; /* Save DM state into filename */ - ret = libxl__qmp_save(gc, domid, filename); + ret = libxl__qmp_save(gc, domid, dmid, filename); if (ret) unlink(filename); break; @@ -870,21 +876,67 @@ int libxl__domain_suspend_device_model(libxl__gc *gc, return ret; } -int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid) +int libxl__domain_suspend_device_models(libxl__gc *gc, + libxl__domain_suspend_state *dss) { + libxl_dmid *dms = NULL; + unsigned int num_dms = 0; + unsigned int i; + int ret; + + dms = libxl__list_device_models(gc, dss->domid, &num_dms); + + if (!dms) + return ERROR_FAIL; + + for (i = 0; i < num_dms; i++) + { + ret = libxl__domain_suspend_device_model(gc, dms[i], dss); + if (ret) + return ret; + } + + return 0; +} +static int libxl__domain_resume_device_model(libxl__gc *gc, libxl_domid domid, + libxl_dmid dmid) +{ switch (libxl__device_model_version_running(gc, domid)) { case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: { libxl__qemu_traditional_cmd(gc, domid, "continue"); - libxl__wait_for_device_model(gc, domid, "running", NULL, NULL, NULL); + libxl__wait_for_device_model(gc, domid, dmid, "running", NULL, NULL, + NULL); break; } case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN: - if (libxl__qmp_resume(gc, domid)) + if (libxl__qmp_resume(gc, domid, dmid)) return ERROR_FAIL; default: return ERROR_INVAL; } + return 0; +} + +int libxl__domain_resume_device_models(libxl__gc *gc, + libxl_domid domid) +{ + libxl_dmid *dms = NULL; + unsigned int num_dms = 0; + unsigned int i = 0; + int ret = 0; + + dms = libxl__list_device_models(gc, domid, &num_dms); + + if (!dms) + return ERROR_FAIL; + + for (i = 0; i < num_dms; i++) + { + ret = libxl__domain_resume_device_model(gc, domid, dms[i]); + if (ret) + return ret; + } return 0; } @@ -1014,9 +1066,10 @@ int libxl__domain_suspend_common_callback(void *user) guest_suspended: if (dss->hvm) { - ret = libxl__domain_suspend_device_model(gc, dss); + ret = libxl__domain_suspend_device_models(gc, dss); if (ret) { - LOG(ERROR, "libxl__domain_suspend_device_model failed ret=%d", ret); + LOG(ERROR, "libxl__domain_suspend_device_models failed ret=%d", + ret); return 0; } } @@ -1038,6 +1091,7 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf, STATE_AO_GC(dss->ao); int i = 0; char *start_addr = NULL, *size = NULL, *phys_offset = NULL, *name = NULL; + char *device_model = NULL; unsigned int num = 0; uint32_t count = 0, version = TOOLSTACK_SAVE_VERSION, namelen = 0; uint8_t *ptr = NULL; @@ -1068,6 +1122,13 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf, return -1; } + xs_path = physmap_path(gc, domid, phys_offset, "device_model"); + device_model = libxl__xs_read(gc, 0, xs_path); + if (device_model == NULL) { + LOG(ERROR, "%s is NULL", xs_path); + return -1; + } + xs_path = physmap_path(gc, domid, phys_offset, "start_addr"); start_addr = libxl__xs_read(gc, 0, xs_path); if (start_addr == NULL) { @@ -1095,6 +1156,7 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf, return -1; ptr = (*buf) + offset; pi = (struct libxl__physmap_info *) ptr; + pi->device_model = strtol(device_model, NULL, 10); pi->phys_offset = strtoll(phys_offset, NULL, 16); pi->start_addr = strtoll(start_addr, NULL, 16); pi->size = strtoll(size, NULL, 16); @@ -1144,7 +1206,7 @@ static void libxl__remus_domain_checkpoint_callback(void *data) /* This would go into tailbuf. */ if (dss->hvm) { - libxl__domain_save_device_model(egc, dss, remus_checkpoint_dm_saved); + libxl__domain_save_device_models(egc, dss, remus_checkpoint_dm_saved); } else { remus_checkpoint_dm_saved(egc, dss, 0); } @@ -1207,7 +1269,6 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss) dss->suspend_eventchn = -1; dss->guest_responded = 0; - dss->dm_savefile = libxl__device_model_savefile(gc, domid); if (r_info != NULL) { dss->interval = r_info->interval; @@ -1274,10 +1335,10 @@ void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void, } if (type == LIBXL_DOMAIN_TYPE_HVM) { - rc = libxl__domain_suspend_device_model(gc, dss); + rc = libxl__domain_suspend_device_models(gc, dss); if (rc) goto out; - libxl__domain_save_device_model(egc, dss, domain_suspend_done); + libxl__domain_save_device_models(egc, dss, domain_suspend_done); return; } @@ -1290,29 +1351,30 @@ out: static void save_device_model_datacopier_done(libxl__egc *egc, libxl__datacopier_state *dc, int onwrite, int errnoval); -void libxl__domain_save_device_model(libxl__egc *egc, - libxl__domain_suspend_state *dss, - libxl__save_device_model_cb *callback) +static void libxl__domain_save_device_model(libxl__egc *egc, + libxl__domain_suspend_state *dss) { STATE_AO_GC(dss->ao); struct stat st; uint32_t qemu_state_len; + uint32_t num_dms = dss->num_dms; int rc; - - dss->save_dm_callback = callback; + libxl_dmid dmid = dss->dms[dss->current_dm]; /* Convenience aliases */ - const char *const filename = dss->dm_savefile; + const char *const filename = libxl__device_model_savefile(gc, dss->domid, + dmid); const int fd = dss->fd; libxl__datacopier_state *dc = &dss->save_dm_datacopier; memset(dc, 0, sizeof(*dc)); - dc->readwhat = GCSPRINTF("qemu save file %s", filename); + dc->readwhat = GCSPRINTF("qemu %u save file %s", dmid, filename); dc->ao = ao; dc->readfd = -1; dc->writefd = fd; dc->maxsz = INT_MAX; - dc->copywhat = GCSPRINTF("qemu save file for domain %"PRIu32, dss->domid); + dc->copywhat = GCSPRINTF("qemu %u save file for domain %"PRIu32, + dmid, dss->domid); dc->writewhat = "save/migration stream"; dc->callback = save_device_model_datacopier_done; @@ -1339,8 +1401,16 @@ void libxl__domain_save_device_model(libxl__egc *egc, rc = libxl__datacopier_start(dc); if (rc) goto out; + /* FIXME: Ugly fix to add DMS_SIGNATURE */ + if (dss->current_dm == 0) { + libxl__datacopier_prefixdata(egc, dc, + DMS_SIGNATURE, strlen(DMS_SIGNATURE)); + libxl__datacopier_prefixdata(egc, dc, + &num_dms, sizeof (num_dms)); + } + libxl__datacopier_prefixdata(egc, dc, - QEMU_SIGNATURE, strlen(QEMU_SIGNATURE)); + DM_SIGNATURE, strlen(DM_SIGNATURE)); libxl__datacopier_prefixdata(egc, dc, &qemu_state_len, sizeof(qemu_state_len)); @@ -1350,6 +1420,20 @@ void libxl__domain_save_device_model(libxl__egc *egc, save_device_model_datacopier_done(egc, dc, -1, 0); } +void libxl__domain_save_device_models(libxl__egc *egc, + libxl__domain_suspend_state *dss, + libxl__save_device_model_cb *callback) +{ + STATE_AO_GC(dss->ao); + + dss->save_dm_callback = callback; + dss->num_dms = 0; + dss->current_dm = 0; + dss->dms = libxl__list_device_models(gc, dss->domid, &dss->num_dms); + + libxl__domain_save_device_model(egc, dss); +} + static void save_device_model_datacopier_done(libxl__egc *egc, libxl__datacopier_state *dc, int onwrite, int errnoval) { @@ -1358,7 +1442,9 @@ static void save_device_model_datacopier_done(libxl__egc *egc, STATE_AO_GC(dss->ao); /* Convenience aliases */ - const char *const filename = dss->dm_savefile; + libxl_dmid dmid = dss->dms[dss->current_dm]; + const char *const filename = libxl__device_model_savefile(gc, dss->domid, + dmid); int our_rc = 0; int rc; @@ -1375,7 +1461,12 @@ static void save_device_model_datacopier_done(libxl__egc *egc, rc = libxl__remove_file(gc, filename); if (!our_rc) our_rc = rc; - dss->save_dm_callback(egc, dss, our_rc); + dss->current_dm++; + + if (!our_rc && dss->num_dms != dss->current_dm) + libxl__domain_save_device_model(egc, dss); + else + dss->save_dm_callback(egc, dss, our_rc); } static void domain_suspend_done(libxl__egc *egc, diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 2e6eedc..9de1465 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -93,7 +93,8 @@ #define LIBXL_MIN_DOM0_MEM (128*1024) /* use 0 as the domid of the toolstack domain for now */ #define LIBXL_TOOLSTACK_DOMID 0 -#define QEMU_SIGNATURE "DeviceModelRecord0002" +#define DMS_SIGNATURE "DeviceModelRecords001" +#define DM_SIGNATURE "DeviceModelRecord0002" #define STUBDOM_CONSOLE_LOGGING 0 #define STUBDOM_CONSOLE_SAVE 1 #define STUBDOM_CONSOLE_RESTORE 2 @@ -896,7 +897,8 @@ _hidden int libxl__domain_rename(libxl__gc *gc, uint32_t domid, _hidden int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf, uint32_t size, void *data); -_hidden int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid); +_hidden int libxl__domain_resume_device_models(libxl__gc *gc, + libxl_domid domid); _hidden void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid); @@ -2230,10 +2232,12 @@ struct libxl__domain_suspend_state { int hvm; int xcflags; int guest_responded; - const char *dm_savefile; int interval; /* checkpoint interval (for Remus) */ libxl__save_helper_state shs; libxl__logdirty_switch logdirty; + unsigned int num_dms; + unsigned int current_dm; + libxl_dmid *dms; /* private for libxl__domain_save_device_model */ libxl__save_device_model_cb *save_dm_callback; libxl__datacopier_state save_dm_datacopier; @@ -2535,9 +2539,9 @@ _hidden void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void, int rc, int retval, int errnoval); /* Each time the dm needs to be saved, we must call suspend and then save */ -_hidden int libxl__domain_suspend_device_model(libxl__gc *gc, - libxl__domain_suspend_state *dss); -_hidden void libxl__domain_save_device_model(libxl__egc *egc, +_hidden int libxl__domain_suspend_device_models(libxl__gc *gc, + libxl__domain_suspend_state *dss); +_hidden void libxl__domain_save_device_models(libxl__egc *egc, libxl__domain_suspend_state *dss, libxl__save_device_model_cb *callback);