[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 4/5] libxl: domain save: API changes for asynchrony



Change the internal and external APIs for domain save (suspend) to be
capable of asynchronous operation.  The implementation remains
synchronous.

Public API changes:

 * libxl_domain_save takes an ao_how.

 * The `suspend_callback' function passed to libxl_domain_save is
   never called by the existing implementation in libxl.  Abolish it.

 * libxl_domain_save takes its flags parameter as an argument.
   Thus libxl_domain_suspend_info is abolished.

 * libxl_domain_save renamed from libxl_domain_suspend for coherency
   with "restore" and general consistency with higher-level
   terminology.

 * XL_SUSPEND_* flags renamed to LIBXL_SAVE_*.

 * Callers in xl updated.

Internal code restructuring:

 * libxl__domain_suspend renamed from libxl__domain_suspend_common.
   (_common here actually meant "internal function").

 * libxl__domain_suspend takes a libxl__domain_suspend_state, which
   where the parameters to the operation are filled in by the caller.

 * xc_domain_save is now called via libxl__xc_domain_save which can
   itself become asynchronous.

 * Consequently, libxl__domain_suspend is split into two functions at
   the callback boundary; the second half is
   libxl__xc_domain_save_done.

 * libxl__domain_save_device_model is now called by the actual
   implementation rather than by the public wrapper.  It is already in
   its proper place in the domain save execution sequence.  So
   officially make it part of that execution sequence, renaming it to
   domain_save_device_model.

 * Effectively, rewrite the public wrapper function libxl_domain_save.

 * Remove a needless #include <xenctrl.h>

Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
---
 tools/libxl/libxl.c              |   45 ++++++++++----
 tools/libxl/libxl.h              |   16 ++---
 tools/libxl/libxl_dom.c          |  124 ++++++++++++++++++++++++++-----------
 tools/libxl/libxl_internal.h     |   41 +++++++++++--
 tools/libxl/libxl_save_callout.c |   21 ++++++-
 tools/libxl/xl_cmdimpl.c         |    7 +--
 6 files changed, 185 insertions(+), 69 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 4d01cf8..a8dfd68 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -614,20 +614,43 @@ libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm)
     return ptr;
 }
 
-int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
-                         uint32_t domid, int fd)
+static void domain_save_cb(libxl__egc *egc,
+                           libxl__domain_suspend_state *dss, int rc)
 {
-    GC_INIT(ctx);
+    STATE_AO_GC(dss->ao);
+    libxl__ao_complete(egc,ao,rc);
+}
+
+int libxl_domain_save(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
+                      const libxl_asyncop_how *ao_how)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc;
+
     libxl_domain_type type = libxl__domain_type(gc, domid);
-    int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
-    int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
-    int rc = 0;
+    if (type < 0) {
+        LOG(ERROR,"domain %"PRIu32": unable to determine domain type", domid);
+        rc = ERROR_FAIL;
+        goto out_err;
+    }
 
-    rc = libxl__domain_suspend_common(gc, domid, fd, type, live, debug);
-    if (!rc && type == LIBXL_DOMAIN_TYPE_HVM)
-        rc = libxl__domain_save_device_model(gc, domid, fd);
-    GC_FREE;
-    return rc;
+    libxl__domain_suspend_state *dss;
+    GCNEW(dss);
+
+    dss->ao = ao;
+    dss->callback = domain_save_cb;
+
+    dss->domid = domid;
+    dss->fd = fd;
+    dss->type = type;
+    dss->live = flags & LIBXL_SAVE_LIVE;
+    dss->debug = flags & LIBXL_SAVE_DEBUG;
+
+    libxl__domain_suspend(egc, dss);
+    return AO_INPROGRESS;
+
+ out_err:
+    return AO_ABORT(rc);
 }
 
 int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index c86d8e7..467ef5d 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -359,13 +359,6 @@ typedef struct libxl__ctx libxl_ctx;
 
 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
 
-typedef struct {
-#define XL_SUSPEND_DEBUG 1
-#define XL_SUSPEND_LIVE 2
-    int flags;
-    int (*suspend_callback)(void *, int);
-} libxl_domain_suspend_info;
-
 enum {
     ERROR_NONSPECIFIC = -1,
     ERROR_VERSION = -2,
@@ -525,8 +518,13 @@ int libxl_domain_create_restore(libxl_ctx *ctx, 
libxl_domain_config *d_config,
 
 void libxl_domain_config_init(libxl_domain_config *d_config);
 void libxl_domain_config_dispose(libxl_domain_config *d_config);
-int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
-                          uint32_t domid, int fd);
+
+int libxl_domain_save(libxl_ctx *ctx, uint32_t domid, int fd,
+                      int flags, /* LIBXL_SAVE_* */
+                      const libxl_asyncop_how *ao_how);
+#define LIBXL_SAVE_DEBUG 1
+#define LIBXL_SAVE_LIVE 2
+
 int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid);
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index d29c705..d28f740 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -17,13 +17,11 @@
 
 #include <glob.h>
 
-#include <xenctrl.h>
-#include <xc_dom.h>
+#include "libxl_internal.h"
 
+#include <xc_dom.h>
 #include <xen/hvm/hvm_info_table.h>
 
-#include "libxl_internal.h"
-
 libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -515,11 +513,20 @@ int libxl__toolstack_restore(uint32_t domid, const 
uint8_t *buf,
     return 0;
 }
 
-static int libxl__domain_suspend_common_switch_qemu_logdirty
+/*==================== Domain suspend (save) ====================*/
+
+static void domain_save_device_model(libxl__egc *egc,
+                                     libxl__domain_suspend_state *dss);
+static void domain_suspend_done(libxl__egc *egc,
+                        libxl__domain_suspend_state *dss, int rc);
+
+/*----- callbacks, called by xc_domain_save -----*/
+
+int libxl__domain_suspend_common_switch_qemu_logdirty
                                (int domid, unsigned int enable, void *data)
 {
     libxl__domain_suspend_state *dss = data;
-    libxl__gc *gc = dss->gc;
+    STATE_AO_GC(dss->ao);
     char *path;
     bool rc;
 
@@ -536,10 +543,10 @@ static int 
libxl__domain_suspend_common_switch_qemu_logdirty
     return rc ? 0 : 1;
 }
 
-static int libxl__domain_suspend_common_callback(void *data)
+int libxl__domain_suspend_common_callback(void *data)
 {
     libxl__domain_suspend_state *dss = data;
-    libxl__gc *gc = dss->gc;
+    STATE_AO_GC(dss->ao);
     unsigned long hvm_s_state = 0, hvm_pvdrv = 0;
     int ret;
     char *state = "suspend";
@@ -667,11 +674,11 @@ static inline char *save_helper(libxl__gc *gc, uint32_t 
domid,
             domid, phys_offset, node);
 }
 
-static int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
+int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
         uint32_t *len, void *data)
 {
     libxl__domain_suspend_state *dss = data;
-    libxl__gc *gc = dss->gc;
+    STATE_AO_GC(dss->ao);
     int i = 0;
     char *start_addr = NULL, *size = NULL, *phys_offset = NULL, *name = NULL;
     unsigned int num = 0;
@@ -742,17 +749,22 @@ static int libxl__toolstack_save(uint32_t domid, uint8_t 
**buf,
     return 0;
 }
 
-int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
-                                 libxl_domain_type type,
-                                 int live, int debug)
+/*----- main code for suspending, in order of execution -----*/
+
+void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
 {
+    STATE_AO_GC(dss->ao);
     int xcflags;
     int port;
-    struct save_callbacks callbacks;
-    libxl__domain_suspend_state dss[1];
     int hvm, rc = ERROR_FAIL;
     unsigned long vm_generationid_addr;
 
+    /* Convenience aliases */
+    const uint32_t domid = dss->domid;
+    const libxl_domain_type type = dss->type;
+    const int live = dss->live;
+    const int debug = dss->debug;
+
     switch (type) {
     case LIBXL_DOMAIN_TYPE_HVM: {
         char *path;
@@ -771,17 +783,14 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t 
domid, int fd,
         hvm = 0;
         break;
     default:
-        return ERROR_INVAL;
+        abort();
     }
 
     xcflags = (live) ? XCFLAGS_LIVE : 0
           | (debug) ? XCFLAGS_DEBUG : 0
           | (hvm) ? XCFLAGS_HVM : 0;
 
-    dss->domid = domid;
-    dss->xcflags = xcflags;
     dss->hvm = hvm;
-    dss->gc = gc;
     dss->suspend_eventchn = -1;
     dss->guest_responded = 0;
 
@@ -801,16 +810,27 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t 
domid, int fd,
         }
     }
 
-    memset(&callbacks, 0, sizeof(callbacks));
-    callbacks.suspend = libxl__domain_suspend_common_callback;
-    callbacks.switch_qemu_logdirty = 
libxl__domain_suspend_common_switch_qemu_logdirty;
-    callbacks.toolstack_save = libxl__toolstack_save;
-    callbacks.data = dss;
+    libxl__xc_domain_save(egc, dss, xcflags, hvm, vm_generationid_addr);
+    return;
 
-    rc = xc_domain_save(CTX->xch, fd, domid, 0, 0, xcflags, &callbacks,
-                        hvm, vm_generationid_addr);
-    if ( rc ) {
-        LOGE(ERROR, "saving domain: %s",
+ out:
+    domain_suspend_done(egc, dss, rc);
+}
+
+void libxl__xc_domain_save_done(libxl__egc *egc,
+                                libxl__domain_suspend_state *dss,
+                                int rc, int retval, int errnoval)
+{
+    STATE_AO_GC(dss->ao);
+
+    /* Convenience aliases */
+    const libxl_domain_type type = dss->type;
+
+    if (rc)
+        goto out;
+
+    if (retval) {
+        LOGEV(ERROR, errnoval, "saving domain: %s",
                          dss->guest_responded ?
                          "domain responded to suspend request" :
                          "domain did not respond to suspend request");
@@ -818,20 +838,29 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t 
domid, int fd,
             rc = ERROR_GUEST_TIMEDOUT;
         else
             rc = ERROR_FAIL;
+        goto out;
     }
 
-    if (dss->suspend_eventchn > 0)
-        xc_suspend_evtchn_release(CTX->xch, dss->xce, domid,
-                                  dss->suspend_eventchn);
-    if (dss->xce != NULL)
-        xc_evtchn_close(dss->xce);
+    if (type == LIBXL_DOMAIN_TYPE_HVM) {
+        domain_save_device_model(egc, dss);
+    } else {
+        domain_suspend_done(egc, dss, 0);
+    }
+    return;
 
 out:
-    return rc;
+    domain_suspend_done(egc, dss, rc);
 }
 
-int libxl__domain_save_device_model(libxl__gc *gc, uint32_t domid, int fd)
+static void domain_save_device_model(libxl__egc *egc,
+                                     libxl__domain_suspend_state *dss)
 {
+    STATE_AO_GC(dss->ao);
+
+    /* Convenience aliases */
+    const uint32_t domid = dss->domid;
+    const int fd = dss->fd;
+
     int rc, fd2 = -1, c;
     char buf[1024];
     const char *filename = libxl__device_model_savefile(gc, domid);
@@ -852,7 +881,8 @@ int libxl__domain_save_device_model(libxl__gc *gc, uint32_t 
domid, int fd)
             goto out;
         break;
     default:
-        return ERROR_INVAL;
+        rc = ERROR_INVAL;
+        goto out;
     }
 
     if (stat(filename, &st) < 0)
@@ -896,9 +926,29 @@ int libxl__domain_save_device_model(libxl__gc *gc, 
uint32_t domid, int fd)
 out:
     if (fd2 >= 0) close(fd2);
     unlink(filename);
-    return rc;
+
+    domain_suspend_done(egc, dss, rc);
 }
 
+static void domain_suspend_done(libxl__egc *egc,
+                        libxl__domain_suspend_state *dss, int rc)
+{
+    STATE_AO_GC(dss->ao);
+
+    /* Convenience aliases */
+    const uint32_t domid = dss->domid;
+
+    if (dss->suspend_eventchn > 0)
+        xc_suspend_evtchn_release(CTX->xch, dss->xce, domid,
+                                  dss->suspend_eventchn);
+    if (dss->xce != NULL)
+        xc_evtchn_close(dss->xce);
+
+    dss->callback(egc, dss, rc);
+}
+
+/*==================== Miscellaneous ====================*/
+
 char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid)
 {
     char *s = libxl__sprintf(gc, LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index fa70a00..a06cc65 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1708,13 +1708,23 @@ _hidden int 
libxl__datacopier_start(libxl__datacopier_state *dc);
 
 typedef struct libxl__domain_suspend_state libxl__domain_suspend_state;
 
+typedef void libxl__domain_suspend_cb(libxl__egc*,
+                                      libxl__domain_suspend_state*, int rc);
+
 struct libxl__domain_suspend_state {
-    libxl__gc *gc;
+    /* set by caller of libxl__domain_suspend */
+    libxl__ao *ao;
+    libxl__domain_suspend_cb *callback;
+
+    uint32_t domid;
+    int fd;
+    libxl_domain_type type;
+    int live;
+    int debug;
+    /* private */
     xc_evtchn *xce; /* event channel handle */
     int suspend_eventchn;
-    int domid;
     int hvm;
-    unsigned int xcflags;
     int guest_responded;
 };
 
@@ -1816,9 +1826,28 @@ struct libxl__domain_create_state {
 
 /*----- Domain suspend (save) functions -----*/
 
-_hidden int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
-                                         libxl_domain_type type,
-                                         int live, int debug);
+/* calls callback when done */
+_hidden void libxl__domain_suspend(libxl__egc *egc,
+                                   libxl__domain_suspend_state *dss);
+
+
+/* calls libxl__xc_domain_suspend_done when done */
+_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*,
+                                   int xcflags, int hvm,
+                                   unsigned long vm_generationid_addr);
+/* If rc==0 then retval is the return value from xc_domain_save
+ * and errnoval is the errno value it provided.
+ * If rc!=0, retval and errnoval are undefined. */
+_hidden void libxl__xc_domain_save_done(libxl__egc*,
+                                        libxl__domain_suspend_state*,
+                                        int rc, int retval, int errnoval);
+
+_hidden int libxl__domain_suspend_common_callback(void *data);
+_hidden int libxl__domain_suspend_common_switch_qemu_logdirty
+                               (int domid, unsigned int enable, void *data);
+_hidden int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
+        uint32_t *len, void *data);
+
 
 /* calls libxl__xc_domain_restore_done when done */
 _hidden void libxl__xc_domain_restore(libxl__egc *egc,
diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c
index bad4e30..2355cc0 100644
--- a/tools/libxl/libxl_save_callout.c
+++ b/tools/libxl/libxl_save_callout.c
@@ -20,7 +20,6 @@ void libxl__xc_domain_restore(libxl__egc *egc, 
libxl__domain_create_state *dcs,
                               int hvm, int pae, int superpages,
                               int no_incr_generationid,
                               xc_toolstack_restore_cb *toolstack_restore)
-/* calls libxl__xc_domain_restore_done when done */
 {
     STATE_AO_GC(dcs->ao);
 
@@ -41,3 +40,23 @@ void libxl__xc_domain_restore(libxl__egc *egc, 
libxl__domain_create_state *dcs,
                               &state->vm_generationid_addr, &callbacks);
     libxl__xc_domain_restore_done(egc, dcs, 0, r, errno);
 }
+
+void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss,
+                           int xcflags, int hvm,
+                           unsigned long vm_generationid_addr)
+{
+    STATE_AO_GC(dss->ao);
+    struct save_callbacks callbacks;
+    int r;
+
+    memset(&callbacks, 0, sizeof(callbacks));
+    callbacks.suspend = libxl__domain_suspend_common_callback;
+    callbacks.switch_qemu_logdirty =
+        libxl__domain_suspend_common_switch_qemu_logdirty;
+    callbacks.toolstack_save = libxl__toolstack_save;
+    callbacks.data = dss;
+
+    r = xc_domain_save(CTX->xch, dss->fd, dss->domid, 0, 0, xcflags, 
&callbacks,
+                       hvm, vm_generationid_addr);
+    libxl__xc_domain_save_done(egc, dss, 0, r, errno);
+}
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 38c5726..2dc8a07 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -2808,7 +2808,7 @@ static int save_domain(const char *p, const char 
*filename, int checkpoint,
 
     save_domain_core_writeconfig(fd, filename, config_data, config_len);
 
-    CHK_ERRNO(libxl_domain_suspend(ctx, NULL, domid, fd));
+    CHK_ERRNO(libxl_domain_save(ctx, domid, fd, 0, NULL));
     close(fd);
 
     if (checkpoint)
@@ -2911,7 +2911,6 @@ static void migrate_domain(const char *domain_spec, const 
char *rune,
     int rc;
     int sendpipe[2], recvpipe[2];
     int send_fd, recv_fd;
-    libxl_domain_suspend_info suspinfo;
     char *away_domname;
     char rc_buf;
     uint8_t *config_data;
@@ -2964,9 +2963,7 @@ static void migrate_domain(const char *domain_spec, const 
char *rune,
 
     xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
 
-    memset(&suspinfo, 0, sizeof(suspinfo));
-    suspinfo.flags |= XL_SUSPEND_LIVE;
-    rc = libxl_domain_suspend(ctx, &suspinfo, domid, send_fd);
+    rc = libxl_domain_save(ctx, domid, send_fd, LIBXL_SAVE_LIVE, NULL);
     if (rc) {
         fprintf(stderr, "migration sender: libxl_domain_suspend failed"
                 " (rc=%d)\n", rc);
-- 
1.7.2.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.