WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] libxenlight: fix suspend/resume

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] libxenlight: fix suspend/resume
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 30 Nov 2009 03:05:13 -0800
Delivery-date: Mon, 30 Nov 2009 03:05:32 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1259578419 0
# Node ID 093cd0e7d537860df31cb85da5400b437fe7cb7e
# Parent  6864bc03783fed55abdef5f6b34e2efd57cf47d0
libxenlight: fix suspend/resume

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 tools/libxl/libxl.c          |   89 ++++++++++++++++-----
 tools/libxl/libxl.h          |    6 +
 tools/libxl/libxl_dom.c      |  176 +++++++++++++++++++++----------------------
 tools/libxl/libxl_internal.h |    1 
 tools/libxl/xl.c             |  143 +++++++++++++++++++++++++++++++++-
 5 files changed, 294 insertions(+), 121 deletions(-)

diff -r 6864bc03783f -r 093cd0e7d537 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Mon Nov 30 10:47:36 2009 +0000
+++ b/tools/libxl/libxl.c       Mon Nov 30 10:53:39 2009 +0000
@@ -217,29 +217,36 @@ int libxl_domain_build(struct libxl_ctx 
 }
 
 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
-                          uint32_t domid, int fd)
-{
-    libxl_domain_build_state state;
+                         uint32_t domid, int fd, libxl_domain_build_state 
*state,
+                         libxl_device_model_info *dm_info)
+{
     char **vments = NULL, **localents = NULL;
 
-    memset(&state, '\0', sizeof(state));
-
-    build_pre(ctx, domid, info, &state);
-    restore_common(ctx, domid, info, &state, fd);
+    build_pre(ctx, domid, info, state);
+    restore_common(ctx, domid, info, state, fd);
     if (info->hvm) {
-        vments = libxl_calloc(ctx, 4, sizeof(char *));
+        vments = libxl_calloc(ctx, 5, sizeof(char *));
         vments[0] = "rtc/timeoffset";
         vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
+        vments[2] = "image/ostype";
+        vments[3] = "hvm";
     } else {
-        localents = libxl_calloc(ctx, 4 * 2, sizeof(char *));
-        localents[0] = "serial/0/limit";
-        localents[1] = libxl_sprintf(ctx, "%d", 65536);
-        localents[2] = "console/port";
-        localents[3] = libxl_sprintf(ctx, "%d", state.console_port);
-        localents[4] = "console/ring-ref";
-        localents[5] = libxl_sprintf(ctx, "%ld", state.console_mfn);
-    }
-    build_post(ctx, domid, info, &state, vments, localents);
+        vments = libxl_calloc(ctx, 9, sizeof(char *));
+        vments[0] = "image/ostype";
+        vments[1] = "linux";
+        vments[2] = "image/kernel";
+        vments[3] = (char*) info->kernel;
+        vments[4] = "image/ramdisk";
+        vments[5] = (char*) info->u.pv.ramdisk;
+        vments[6] = "image/cmdline";
+        vments[7] = (char*) info->u.pv.cmdline;
+    }
+    build_post(ctx, domid, info, state, vments, localents);
+    if (info->hvm)
+        asprintf(&(dm_info->saved_state), "/var/lib/xen/qemu-save.%d", domid);
+    else
+        dm_info->saved_state = NULL;
+
     return 0;
 }
 
@@ -299,17 +306,37 @@ xc_dominfo_t * libxl_domain_infolist(str
     return info;
 }
 
+static int libxl_save_device_model(struct libxl_ctx *ctx, uint32_t domid, int 
fd)
+{
+    int fd2, c;
+    char buf[1024];
+    char *filename = libxl_sprintf(ctx, "/var/lib/xen/qemu-save.%d", domid);
+
+    XL_LOG(ctx, XL_LOG_DEBUG, "Saving device model state to %s", filename);
+    libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d/command", domid), "save", strlen("save"));
+    libxl_wait_for_device_model(ctx, domid, "paused", NULL, NULL);
+
+    write(fd, QEMU_SIGNATURE, strlen(QEMU_SIGNATURE));
+    fd2 = open(filename, O_RDONLY);
+    while ((c = read(fd2, buf, sizeof(buf))) != 0) {
+        write(fd, buf, c);
+    }
+    close(fd2);
+    unlink(filename);
+    return 0;
+}
+
 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info 
*info,
                          uint32_t domid, int fd)
 {
-    int hvm = 1;
-    int live = 0;
-    int debug = 0;
-    char savesig[] = "XenSavedDomain\n";
-
-    write(fd, savesig, strlen(savesig));
+    int hvm = is_hvm(ctx, domid);
+    int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
+    int debug = info != NULL && info->flags & XL_SUSPEND_LIVE;
+
 
     core_suspend(ctx, domid, fd, hvm, live, debug);
+    if (hvm)
+        libxl_save_device_model(ctx, domid, fd);
 
     return 0;
 }
@@ -322,7 +349,19 @@ int libxl_domain_pause(struct libxl_ctx 
 
 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid)
 {
+    char path[50];
+    char *state;
+
+    if (is_hvm(ctx, domid)) {
+        snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", 
domid);
+        state = libxl_xs_read(ctx, XBT_NULL, path);
+        if (state != NULL && !strcmp(state, "paused")) {
+            libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, 
"/local/domain/0/device-model/%d/command", domid), "continue", 
strlen("continue"));
+            libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL);
+        }
+    }
     xc_domain_unpause(ctx->xch, domid);
+
     return 0;
 }
 
@@ -578,6 +617,10 @@ static char ** libxl_build_device_model_
                             vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
             }
         }
+    }
+    if (info->saved_state) {
+        flexarray_set(dm_args, num++, "-loadvm");
+        flexarray_set(dm_args, num++, info->saved_state);
     }
     for (i = 0; info->extra && info->extra[i] != NULL; i++)
         flexarray_set(dm_args, num++, info->extra[i]);
diff -r 6864bc03783f -r 093cd0e7d537 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Mon Nov 30 10:47:36 2009 +0000
+++ b/tools/libxl/libxl.h       Mon Nov 30 10:53:39 2009 +0000
@@ -94,6 +94,8 @@ typedef struct {
 } libxl_domain_build_state;
 
 typedef struct {
+#define XL_SUSPEND_DEBUG 1
+#define XL_SUSPEND_LIVE 2
     int flags;
     int (*suspend_callback)(void *, int);
 } libxl_domain_suspend_info;
@@ -107,6 +109,7 @@ typedef struct {
     int domid;
     char *dom_name;
     char *device_model;
+    char *saved_state;
     libxl_qemu_machine_type type;
     int videoram; /* size of the videoram in MB */
     bool stdvga; /* stdvga enabled or disabled */
@@ -254,7 +257,8 @@ int libxl_domain_make(struct libxl_ctx *
 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info, 
uint32_t *domid);
 int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, 
uint32_t domid, /* out */ libxl_domain_build_state *state);
 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
-                          uint32_t domid, int fd);
+                         uint32_t domid, int fd, libxl_domain_build_state 
*state,
+                         libxl_device_model_info *dm_info);
 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info 
*info,
                           uint32_t domid, int fd);
 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
diff -r 6864bc03783f -r 093cd0e7d537 tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c   Mon Nov 30 10:47:36 2009 +0000
+++ b/tools/libxl/libxl_dom.c   Mon Nov 30 10:53:39 2009 +0000
@@ -163,71 +163,36 @@ int restore_common(struct libxl_ctx *ctx
                       state->store_port, &state->store_mfn,
                       state->console_port, &state->console_mfn,
                       info->hvm, info->u.hvm.pae, 0);
-    return 0;
-}
-
-/* the following code is extremely ugly and racy without forking.
-   we intend to fix the re-entrancy of the underlying code instead of forking 
*/
-static struct libxl_ctx *global_suspend_ctx = NULL;
-static struct suspendinfo {
-    int xch;
+#if defined(__i386__) || defined(__x86_64__)
+    xc_cpuid_apply_policy(ctx->xch, domid);
+#endif
+    return 0;
+}
+
+struct suspendinfo {
+    struct libxl_ctx *ctx;
     int xce; /* event channel handle */
     int suspend_eventchn;
     int domid;
     int hvm;
     unsigned int flags;
-} si;
-
-void core_suspend_switch_qemu_logdirty(int domid, unsigned int enable)
-{
-    struct xs_handle *xs;
-    char *path, *ret_path, *cmd_path, *ret_str, *cmd_str, **watch;
-    unsigned int len;
-    struct timeval tv;
-    fd_set fdset;
-    struct libxl_ctx *ctx = global_suspend_ctx;
-
-    xs = xs_daemon_open();
-    if (!xs)
-        return;
-    path = libxl_sprintf(ctx, "/local/domain/0/device-model/%i/logdirty", 
domid);
-    if (!path)
-        return;
-    ret_path = libxl_sprintf(ctx, "%s/ret", path);
-    if (!ret_path)
-        return;
-    cmd_path = libxl_sprintf(ctx, "%s/cmd", path);
-    if (!ret_path)
-        return;
-
-    /* Watch for qemu's return value */
-    if (!xs_watch(xs, ret_path, "qemu-logdirty-ret"))
-        return;
-
-    cmd_str = (enable == 0) ? "disable" : "enable";
-
-    /* Tell qemu that we want it to start logging dirty page to Xen */
-    if (!xs_write(xs, XBT_NULL, cmd_path, cmd_str, strlen(cmd_str)))
-        return;
-
-    /* Wait a while for qemu to signal that it has service logdirty command */
-read_again:
-    tv.tv_sec = 5;
-    tv.tv_usec = 0;
-    FD_ZERO(&fdset);
-    FD_SET(xs_fileno(xs), &fdset);
-
-    if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1)
-        return;
-
-    watch = xs_read_watch(xs, &len);
-    free(watch);
-
-    ret_str = xs_read(xs, XBT_NULL, ret_path, &len);
-    if (ret_str == NULL || strcmp(ret_str, cmd_str))
-        /* Watch fired but value is not yet right */
-        goto read_again;
-    free(ret_str);
+};
+
+static void core_suspend_switch_qemu_logdirty(int domid, unsigned int enable)
+{
+    struct xs_handle *xsh;
+    char path[64];
+
+    snprintf(path, sizeof(path), 
"/local/domain/0/device-model/%u/logdirty/cmd", domid);
+
+    xsh = xs_daemon_open();
+
+    if (enable)
+        xs_write(xsh, XBT_NULL, path, "enable", strlen("enable"));
+    else
+        xs_write(xsh, XBT_NULL, path, "disable", strlen("disable"));
+
+    xs_daemon_close(xsh);
 }
 
 static int core_suspend_callback(void *data)
@@ -235,46 +200,77 @@ static int core_suspend_callback(void *d
     struct suspendinfo *si = data;
     unsigned long s_state = 0;
     int ret;
+    char *path, *state = "suspend";
+    int watchdog = 60;
 
     if (si->hvm)
-        xc_get_hvm_param(si->xch, si->domid, HVM_PARAM_ACPI_S_STATE, &s_state);
+        xc_get_hvm_param(si->ctx->xch, si->domid, HVM_PARAM_ACPI_S_STATE, 
&s_state);
     if ((s_state == 0) && (si->suspend_eventchn >= 0)) {
-        ret = xc_evtchn_notify(si->xch, si->suspend_eventchn);
+        ret = xc_evtchn_notify(si->xce, si->suspend_eventchn);
         if (ret < 0) {
+            XL_LOG(si->ctx, XL_LOG_ERROR, "xc_evtchn_notify failed ret=%d", 
ret);
             return 0;
         }
-        ret = xc_await_suspend(si->xch, si->suspend_eventchn);
+        ret = xc_await_suspend(si->xce, si->suspend_eventchn);
         if (ret < 0) {
+            XL_LOG(si->ctx, XL_LOG_ERROR, "xc_await_suspend failed ret=%d", 
ret);
             return 0;
         }
         return 1;
     }
-    /* need to shutdown (to suspend) the domain here */
-    return 0;
-}
-
-static struct save_callbacks callbacks;
+    path = libxl_sprintf(si->ctx, "%s/control/shutdown", 
libxl_xs_get_dompath(si->ctx, si->domid));
+    libxl_xs_write(si->ctx, XBT_NULL, path, "suspend", strlen("suspend"));
+    if (si->hvm) {
+        unsigned long hvm_pvdrv, hvm_s_state;
+        xc_get_hvm_param(si->ctx->xch, si->domid, HVM_PARAM_CALLBACK_IRQ, 
&hvm_pvdrv);
+        xc_get_hvm_param(si->ctx->xch, si->domid, HVM_PARAM_ACPI_S_STATE, 
&hvm_s_state);
+        if (!hvm_pvdrv || hvm_s_state) {
+            XL_LOG(si->ctx, XL_LOG_DEBUG, "Calling xc_domain_shutdown on the 
domain");
+            xc_domain_shutdown(si->ctx->xch, si->domid, SHUTDOWN_suspend);
+        }
+    }
+    XL_LOG(si->ctx, XL_LOG_DEBUG, "wait for the guest to suspend");
+    while (!strcmp(state, "suspend") && watchdog > 0) {
+        int nb_domain, i;
+        xc_dominfo_t *list = NULL;
+        usleep(100000);
+        list = libxl_domain_infolist(si->ctx, &nb_domain);
+        for (i = 0; i < nb_domain; i++) {
+            if (si->domid == list[i].domid) {
+                if (list[i].shutdown != 0 && list[i].shutdown_reason == 
SHUTDOWN_suspend) {
+                    free(list);
+                    return 1;
+                }
+            }
+        }
+        free(list);
+        state = libxl_xs_read(si->ctx, XBT_NULL, path);
+        watchdog--;
+    }
+    if (!strcmp(state, "suspend")) {
+        XL_LOG(si->ctx, XL_LOG_ERROR, "guest didn't suspend in time");
+        libxl_xs_write(si->ctx, XBT_NULL, path, "", 1);
+    }
+    return 1;
+}
 
 int core_suspend(struct libxl_ctx *ctx, uint32_t domid, int fd,
                int hvm, int live, int debug)
 {
     int flags;
     int port;
+    struct save_callbacks callbacks;
+    struct suspendinfo si;
 
     flags = (live) ? XCFLAGS_LIVE : 0
-          | (debug) ? XCFLAGS_DEBUG : 0;
-
-    /* crappy global lock until we make everything clean */
-    while (global_suspend_ctx) {
-        sleep(1);
-    }
-    global_suspend_ctx = ctx;
+          | (debug) ? XCFLAGS_DEBUG : 0
+          | (hvm) ? XCFLAGS_HVM : 0;
 
     si.domid = domid;
     si.flags = flags;
     si.hvm = hvm;
-    si.suspend_eventchn = si.xce = -1;
-    si.xch = ctx->xch;
+    si.ctx = ctx;
+    si.suspend_eventchn = -1;
 
     si.xce = xc_evtchn_open();
     if (si.xce < 0)
@@ -284,28 +280,28 @@ int core_suspend(struct libxl_ctx *ctx, 
         port = xs_suspend_evtchn_port(si.domid);
 
         if (port < 0) {
+            XL_LOG(ctx, XL_LOG_WARNING, "Failed to get the suspend evtchn 
port");
         } else {
-            si.suspend_eventchn = xc_suspend_evtchn_init(si.xch, si.xce, 
si.domid, port);
-
-            if (si.suspend_eventchn < 0) {
-            }
-        }
-    }
-
+            si.suspend_eventchn = xc_suspend_evtchn_init(si.ctx->xch, si.xce, 
si.domid, port);
+
+            if (si.suspend_eventchn < 0)
+                XL_LOG(ctx, XL_LOG_WARNING, "Suspend event channel 
initialization failed");
+        }
+    }
+
+    memset(&callbacks, 0, sizeof(callbacks));
     callbacks.suspend = core_suspend_callback;
-    callbacks.postcopy = NULL;
-    callbacks.checkpoint = NULL;
     callbacks.data = &si;
 
     xc_domain_save(ctx->xch, fd, domid, 0, 0, flags,
                    &callbacks, hvm,
-                   core_suspend_switch_qemu_logdirty);
+                   &core_suspend_switch_qemu_logdirty);
 
     if (si.suspend_eventchn > 0)
         xc_suspend_evtchn_release(si.xce, si.suspend_eventchn);
     if (si.xce > 0)
         xc_evtchn_close(si.xce);
 
-    global_suspend_ctx = NULL;
-    return 0;
-}
+    return 0;
+}
+
diff -r 6864bc03783f -r 093cd0e7d537 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Mon Nov 30 10:47:36 2009 +0000
+++ b/tools/libxl/libxl_internal.h      Mon Nov 30 10:53:39 2009 +0000
@@ -30,6 +30,7 @@
 #define LIBXL_DESTROY_TIMEOUT 10
 #define LIBXL_XENCONSOLE_LIMIT 1048576
 #define LIBXL_XENCONSOLE_PROTOCOL "vt100"
+#define QEMU_SIGNATURE "QemuDeviceModelRecord"
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
diff -r 6864bc03783f -r 093cd0e7d537 tools/libxl/xl.c
--- a/tools/libxl/xl.c  Mon Nov 30 10:47:36 2009 +0000
+++ b/tools/libxl/xl.c  Mon Nov 30 10:53:39 2009 +0000
@@ -31,6 +31,7 @@
 #include <sys/select.h>
 #include <arpa/inet.h>
 #include <xenctrl.h>
+
 
 #include "libxl.h"
 #include "libxl_utils.h"
@@ -575,7 +576,7 @@ skip_pci:
         }                                                               \
     })
 
-static void create_domain(int debug, const char *filename)
+static void create_domain(int debug, const char *config_file, const char 
*restore_file, int paused)
 {
     struct libxl_ctx ctx;
     uint32_t domid;
@@ -593,9 +594,10 @@ static void create_domain(int debug, con
     int i, fd;
     int need_daemon = 1;
     libxl_device_model_starting *dm_starting = 0;
-
-    printf("Parsing config file %s\n", filename);
-    parse_config_file(filename, &info1, &info2, &disks, &num_disks, &vifs, 
&num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, 
&dm_info);
+    memset(&dm_info, 0x00, sizeof(dm_info));
+
+    printf("Parsing config file %s\n", config_file);
+    parse_config_file(config_file, &info1, &info2, &disks, &num_disks, &vifs, 
&num_vifs, &pcidevs, &num_pcidevs, &vfbs, &num_vfbs, &vkbs, &num_vkbs, 
&dm_info);
     if (debug)
         printf_info(&info1, &info2, disks, num_disks, vifs, num_vifs, pcidevs, 
num_pcidevs, vfbs, num_vfbs, vkbs, num_vkbs, &dm_info);
 
@@ -605,7 +607,20 @@ start:
     libxl_ctx_init(&ctx);
     libxl_ctx_set_log(&ctx, log_callback, NULL);
     libxl_domain_make(&ctx, &info1, &domid);
-    libxl_domain_build(&ctx, &info2, domid, &state);
+
+    if (!restore_file || !need_daemon) {
+        if (dm_info.saved_state) {
+            free(dm_info.saved_state);
+            dm_info.saved_state = NULL;
+        }
+        libxl_domain_build(&ctx, &info2, domid, &state);
+    } else {
+        int restore_fd;
+
+        restore_fd = open(restore_file, O_RDONLY);
+        libxl_domain_restore(&ctx, &info2, domid, restore_fd, &state, 
&dm_info);
+        close(restore_fd);
+    }
 
     for (i = 0; i < num_disks; i++) {
         disk_info_domid_fixup(disks + i, domid);
@@ -640,7 +655,8 @@ start:
     for (i = 0; i < num_pcidevs; i++)
         libxl_device_pci_add(&ctx, domid, &pcidevs[i]);
 
-    libxl_domain_unpause(&ctx, domid);
+    if (!paused)
+        libxl_domain_unpause(&ctx, domid);
 
     if (need_daemon) {
         char *fullname, *name;
@@ -712,6 +728,8 @@ static void help(char *command)
         printf(" pause                         pause execution of a 
domain\n\n");
         printf(" unpause                       unpause a paused domain\n\n");
         printf(" console                       attach to domain's 
console\n\n");
+        printf(" save                          save a domain state to restore 
later\n\n");
+        printf(" restore                       restore a domain from a saved 
state\n\n");
     } else if(!strcmp(command, "create")) {
         printf("Usage: xl create <ConfigFile> [options] [vars]\n\n");
         printf("Create a domain based on <ConfigFile>.\n\n");
@@ -736,6 +754,18 @@ static void help(char *command)
     } else if(!strcmp(command, "unpause")) {
         printf("Usage: xl unpause <Domain>\n\n");
         printf("Unpause a paused domain.\n\n");
+    } else if(!strcmp(command, "save")) {
+        printf("Usage: xl save [options] <Domain> <CheckpointFile>\n\n");
+        printf("Save a domain state to restore later.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-c                     Leave domain running after creating the 
snapshot.\n");
+    } else if(!strcmp(command, "restore")) {
+        printf("Usage: xl restore [options] <ConfigFile> 
<CheckpointFile>\n\n");
+        printf("Restore a domain from a saved state.\n\n");
+        printf("Options:\n\n");
+        printf("-h                     Print this help.\n");
+        printf("-p                     Do not unpause domain after restoring 
it.\n");
     } else if(!strcmp(command, "destroy")) {
         printf("Usage: xl destroy <Domain>\n\n");
         printf("Terminate a domain immediately.\n\n");
@@ -1015,6 +1045,101 @@ void list_domains(void)
     free(info);
 }
 
+int save_domain(char *p, char *filename, int checkpoint)
+{
+    struct libxl_ctx ctx;
+    uint32_t domid;
+    int fd;
+
+    libxl_ctx_init(&ctx);
+    libxl_ctx_set_log(&ctx, log_callback, NULL);
+
+    if (libxl_param_to_domid(&ctx, p, &domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", p);
+        exit(2);
+    }
+    fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+    if (fd < 0) {
+        fprintf(stderr, "Failed to open temp file %s for writing\n", filename);
+        exit(2);
+    }
+    libxl_domain_suspend(&ctx, NULL, domid, fd);
+    close(fd);
+
+    if (checkpoint)
+        libxl_domain_unpause(&ctx, domid);
+    else
+        libxl_domain_destroy(&ctx, domid, 0);
+
+    exit(0);
+}
+
+int main_restore(int argc, char **argv)
+{
+    char *checkpoint_file = NULL;
+    char *config_file = NULL;
+    int paused = 0, debug = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hpd")) != -1) {
+        switch (opt) {
+        case 'p':
+            paused = 1;
+            break;
+        case 'd':
+            debug = 1;
+            break;
+        case 'h':
+            help("restore");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (optind >= argc - 1) {
+        help("restore");
+        exit(2);
+    }
+
+    config_file = argv[optind];
+    checkpoint_file = argv[optind + 1];
+    create_domain(debug, config_file, checkpoint_file, paused);
+    exit(0);
+}
+
+int main_save(int argc, char **argv)
+{
+    char *filename = NULL, *p = NULL;
+    int checkpoint = 0;
+    int opt;
+
+    while ((opt = getopt(argc, argv, "hc")) != -1) {
+        switch (opt) {
+        case 'c':
+            checkpoint = 1;
+            break;
+        case 'h':
+            help("save");
+            exit(0);
+        default:
+            fprintf(stderr, "option not supported\n");
+            break;
+        }
+    }
+
+    if (optind >= argc - 1) {
+        help("save");
+        exit(2);
+    }
+
+    p = argv[optind];
+    filename = argv[optind + 1];
+    save_domain(p, filename, checkpoint);
+    exit(0);
+}
+
 int main_pause(int argc, char **argv)
 {
     int opt;
@@ -1140,7 +1265,7 @@ int main_create(int argc, char **argv)
     }
 
     filename = argv[optind];
-    create_domain(debug, filename);
+    create_domain(debug, filename, NULL, 0);
     exit(0);
 }
 
@@ -1169,6 +1294,10 @@ int main(int argc, char **argv)
         main_unpause(argc - 1, argv + 1);
     } else if (!strcmp(argv[1], "console")) {
         main_console(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "save")) {
+        main_save(argc - 1, argv + 1);
+    } else if (!strcmp(argv[1], "restore")) {
+        main_restore(argc - 1, argv + 1);
     } else if (!strcmp(argv[1], "help")) {
         if (argc > 2)
             help(argv[2]);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] libxenlight: fix suspend/resume, Xen patchbot-unstable <=