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

[Xen-devel] [PATCH 26/29] tools/libxl: Implement libxl__domain_restore() for v2 streams



TODO:
 * Integrate with the json series

Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 tools/libxl/libxl_create.c   |  310 ++++++++++++++++++++++++++++++++++++++++--
 tools/libxl/libxl_dom.c      |    4 +-
 tools/libxl/libxl_internal.h |   10 +-
 3 files changed, 310 insertions(+), 14 deletions(-)

diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index a5e185e..9661f78 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -19,6 +19,7 @@
 
 #include "libxl_internal.h"
 #include "libxl_arch.h"
+#include "libxl_saverestore.h"
 
 #include <xc_dom.h>
 #include <xenguest.h>
@@ -934,8 +935,6 @@ static void domcreate_bootloader_done(libxl__egc *egc,
     libxl_domain_build_info *const info = &d_config->b_info;
     const int restore_fd = dcs->restore_fd;
     libxl__domain_build_state *const state = &dcs->build_state;
-    libxl__srm_restore_autogen_callbacks *const callbacks =
-        &dcs->shs.callbacks.restore.a;
 
     if (rc) {
         domcreate_rebuild_done(egc, dcs, rc);
@@ -975,7 +974,6 @@ static void domcreate_bootloader_done(libxl__egc *egc,
         hvm = 1;
         superpages = 1;
         pae = libxl_defbool_val(info->u.hvm.pae);
-        callbacks->toolstack_restore = libxl__toolstack_restore;
         break;
     case LIBXL_DOMAIN_TYPE_PV:
         hvm = 0;
@@ -1105,12 +1103,16 @@ static void domcreate_rebuild_done(libxl__egc *egc,
         goto error_out;
     }
 
-    store_libxl_entry(gc, domid, &d_config->b_info);
+    if (dcs->rebuild_callback) {
+        dcs->rebuild_callback(dcs);
+    } else {
+        store_libxl_entry(gc, domid, &d_config->b_info);
 
-    libxl__multidev_begin(ao, &dcs->multidev);
-    dcs->multidev.callback = domcreate_launch_dm;
-    libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev);
-    libxl__multidev_prepared(egc, &dcs->multidev, 0);
+        libxl__multidev_begin(ao, &dcs->multidev);
+        dcs->multidev.callback = domcreate_launch_dm;
+        libxl__add_disks(egc, ao, domid, d_config, &dcs->multidev);
+        libxl__multidev_prepared(egc, &dcs->multidev, 0);
+    }
 
     return;
 
@@ -1454,6 +1456,11 @@ static void domcreate_destruction_cb(libxl__egc *egc,
 typedef struct {
     libxl__domain_create_state dcs;
     uint32_t *domid_out;
+    libxl__datacopier_state dc;
+    libxl__datacopier_state stream_dc;
+    int expected_len;
+    struct restore_hdr hdr;
+    struct restore_rec_hdr rechdr;
 } libxl__app_domain_create_state;
 
 static void domain_create_cb(libxl__egc *egc,
@@ -1517,6 +1524,293 @@ int libxl_domain_create_restore(libxl_ctx *ctx, 
libxl_domain_config *d_config,
                             params->checkpointed_stream, ao_how, 
aop_console_how);
 }
 
+static void read_restore_rec_hdr(libxl__app_domain_create_state *cdcs);
+
+static void read_padding_cb(libxl__egc *egc, libxl__datacopier_state *dc,
+        int onwrite, int errnoval)
+{
+    libxl__app_domain_create_state *cdcs = CONTAINER_OF(dc, *cdcs, stream_dc);
+    STATE_AO_GC(cdcs->dcs.ao);
+    int ret = 0;
+
+    if (onwrite != 0 || errnoval != cdcs->expected_len) {
+        ret = ERROR_FAIL;
+        goto out;
+    }
+
+    read_restore_rec_hdr(cdcs);
+
+out:
+    if (ret)
+        libxl__ao_complete(egc, ao, ret);
+}
+
+static void restore_write_dm_cb(libxl__egc *egc,
+     libxl__datacopier_state *dc, int onwrite, int errnoval)
+{
+    libxl__app_domain_create_state *cdcs = CONTAINER_OF(dc, *cdcs, dc);
+    STATE_AO_GC(cdcs->dcs.ao);
+    int ret = 0, padding;
+    libxl__datacopier_state *stream_dc = &cdcs->stream_dc;
+    struct restore_rec_hdr *rechdr = &cdcs->rechdr;
+
+    if (onwrite || errnoval) {
+        ret = ERROR_FAIL;
+        goto out;
+    }
+
+    padding = ROUNDUP(rechdr->length - sizeof(struct restore_emulator_hdr),
+                  REC_ALIGN_ORDER) - rechdr->length - sizeof(struct 
restore_emulator_hdr);
+    if (padding > 0) {
+        stream_dc->readwhat = "padding";
+        stream_dc->maxread = padding;
+        cdcs->expected_len = stream_dc->maxread;
+        stream_dc->callback = read_padding_cb;
+        stream_dc->used = 0;
+        stream_dc->readbuf = libxl__malloc(gc, padding);
+        libxl__datacopier_start(stream_dc);
+    } else {
+        read_restore_rec_hdr(cdcs);
+    }
+
+out:
+    if (ret)
+        libxl__ao_complete(egc, ao, ret);
+}
+
+static void read_restore_record_complete(libxl__egc *egc,
+                                         libxl__app_domain_create_state *cdcs,
+                                         void *buf)
+{
+    STATE_AO_GC(cdcs->dcs.ao);
+    int ret = 0;
+
+    /* convenience aliases */
+    libxl_ctx *ctx = CTX;
+    libxl__domain_create_state *dcs = &cdcs->dcs;
+    struct restore_rec_hdr *rechdr = &cdcs->rechdr;
+
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
+               "Record: 0x%08x, length %u", rechdr->type, rechdr->length);
+    switch (rechdr->type) {
+    case REC_TYPE_END:
+        if (rechdr->length != 0) {
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                       "Encountered END record with non-zero length");
+            ret = ERROR_FAIL;
+        } else {
+            /* complete restore */
+            store_libxl_entry(gc, dcs->guest_domid, 
&dcs->guest_config->b_info);
+
+            libxl__multidev_begin(ao, &dcs->multidev);
+            dcs->multidev.callback = domcreate_launch_dm;
+            libxl__add_disks(egc, ao, dcs->guest_domid, dcs->guest_config, 
&dcs->multidev);
+            libxl__multidev_prepared(egc, &dcs->multidev, 0);
+        }
+        break;
+    case REC_TYPE_DOMAIN_JSON:
+        /* XXX handle domain JSON */
+        break;
+    case REC_TYPE_LIBXC_CONTEXT:
+        initiate_domain_create(egc, &cdcs->dcs);
+        break;
+    case REC_TYPE_XENSTORE_DATA:
+        ret = libxl__toolstack_restore(cdcs->dcs.guest_domid, buf,
+                                       rechdr->length, &cdcs->dcs);
+        if (!ret)
+            read_restore_rec_hdr(cdcs);
+        break;
+    case REC_TYPE_EMULATOR_CONTEXT: {
+        struct restore_emulator_hdr *emuhdr = buf;
+        char path[256];
+        libxl__datacopier_state *dc = &cdcs->dc;
+
+        if (emuhdr->id == EMULATOR_UNKNOWN) {
+            ret = ERROR_FAIL;
+            goto out;
+        }
+
+        sprintf(path, XC_DEVICE_MODEL_RESTORE_FILE".%u", 
cdcs->dcs.guest_domid);
+        memset(dc, 0, sizeof(*dc));
+        dc->ao = ao;
+        dc->readwhat = "save/migration stream";
+        dc->copywhat = "emulator context";
+        dc->writewhat = "qemu save file";
+        dc->readfd = cdcs->dcs.restore_fd;
+        dc->writefd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+        if (dc->writefd == -1) {
+            ret = ERROR_FAIL;
+            goto out;
+        }
+        dc->maxsz = INT_MAX;
+        dc->maxread = rechdr->length - sizeof(*emuhdr);
+        dc->callback = restore_write_dm_cb;
+
+        ret = libxl__datacopier_start(dc);
+        if (ret)
+            goto out;
+        break;
+    }
+    default:
+        ret = ERROR_FAIL;
+        break;
+    }
+
+    free(buf);
+
+out:
+    if (ret)
+        libxl__ao_complete(egc, ao, ret);
+}
+
+static void read_restore_rec_body_cb(libxl__egc *egc,
+     libxl__datacopier_state *dc, int onwrite, int errnoval)
+{
+    libxl__app_domain_create_state *cdcs = CONTAINER_OF(dc, *cdcs, stream_dc);
+    STATE_AO_GC(cdcs->dcs.ao);
+    int ret = 0;
+
+    if (onwrite != 0 || errnoval != cdcs->expected_len) {
+        ret = ERROR_FAIL;
+        free(dc->readbuf);
+        goto out;
+    }
+
+    read_restore_record_complete(egc, cdcs, dc->readbuf);
+
+out:
+    if (ret)
+        libxl__ao_complete(egc, ao, ret);
+}
+
+static void read_restore_rec_hdr_cb(libxl__egc *egc,
+     libxl__datacopier_state *dc, int onwrite, int errnoval)
+{
+    libxl__app_domain_create_state *cdcs = CONTAINER_OF(dc, *cdcs, stream_dc);
+    STATE_AO_GC(cdcs->dcs.ao);
+    int ret = 0;
+
+    /* convenience aliases */
+    struct restore_rec_hdr *rechdr = &cdcs->rechdr;
+
+    if (onwrite != 0 || errnoval != cdcs->expected_len) {
+        ret = ERROR_FAIL;
+        goto out;
+    }
+
+    if (rechdr->length > 0) {
+        dc->readwhat = "read record body";
+        if (rechdr->type == REC_TYPE_EMULATOR_CONTEXT)
+            dc->maxread = sizeof(struct restore_rec_hdr);
+        else
+            dc->maxread = ROUNDUP(rechdr->length, REC_ALIGN_ORDER);
+        cdcs->expected_len = dc->maxread;
+        dc->callback = read_restore_rec_body_cb;
+        dc->used = 0;
+        dc->readbuf = libxl__malloc(NOGC, dc->maxread);
+        libxl__datacopier_start(dc);
+    } else {
+        read_restore_record_complete(egc, cdcs, NULL);
+    }
+
+out:
+    if (ret)
+        libxl__ao_complete(egc, ao, ret);
+}
+
+static void read_restore_rec_hdr(libxl__app_domain_create_state *cdcs)
+{
+    STATE_AO_GC(cdcs->dcs.ao);
+
+    libxl__datacopier_state *dc = &cdcs->stream_dc;
+    dc->readwhat = "read record header";
+    dc->maxread = sizeof(cdcs->rechdr);
+    cdcs->expected_len = dc->maxread;
+    dc->used = 0;
+    dc->callback = read_restore_rec_hdr_cb;
+    dc->readbuf = &cdcs->rechdr;
+    dc->suppress_pollhup = 1;
+    libxl__datacopier_start(dc);
+}
+
+static void read_restore_hdr_cb(libxl__egc *egc,
+     libxl__datacopier_state *dc, int onwrite, int errnoval)
+{
+    libxl__app_domain_create_state *cdcs = CONTAINER_OF(dc, *cdcs, stream_dc);
+    STATE_AO_GC(cdcs->dcs.ao);
+    int ret = 0;
+
+    /* convenience aliases */
+    libxl_ctx *ctx = CTX;
+    struct restore_hdr *hdr = &cdcs->hdr;
+
+    if (onwrite != 0 || errnoval != sizeof(*hdr)) {
+        ret = ERROR_FAIL;
+        goto out;
+    }
+
+    hdr->ident = be64toh(hdr->ident);
+    hdr->version = be32toh(hdr->version);
+    hdr->options = be32toh(hdr->options);
+
+    if (hdr->ident != RESTORE_STREAM_IDENT) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "Invalid ident: Got 0x%016"PRIx64, hdr->ident);
+        ret = ERROR_FAIL;
+        goto out;
+    }
+    if (hdr->version != RESTORE_STREAM_VERSION) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "Invalid Version: Expected %u, Got %u",
+                   hdr->version, RESTORE_STREAM_VERSION);
+        ret = ERROR_FAIL;
+        goto out;
+    }
+    if (hdr->options & RESTORE_OPT_BIG_ENDIAN) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "Unable to handle big endian streams");
+        ret = ERROR_FAIL;
+        goto out;
+    }
+
+    read_restore_rec_hdr(cdcs);
+
+out:
+    if (ret)
+        libxl__ao_complete(egc, ao, ret);
+}
+
+static void restore_rebuild_complete(libxl__domain_create_state *dcs)
+{
+    libxl__app_domain_create_state *cdcs = CONTAINER_OF(dcs, *cdcs, dcs);
+    STATE_AO_GC(cdcs->dcs.ao);
+
+    read_restore_rec_hdr(cdcs);
+}
+
+static void libxl__domain_restore(libxl__egc *egc,
+                                  libxl__app_domain_create_state *cdcs)
+{
+    libxl__datacopier_state *dc = &cdcs->stream_dc;
+
+    memset(dc, 0, sizeof(*dc));
+    dc->readwhat = "read header";
+    dc->copywhat = "";
+    dc->writewhat = "";
+    dc->ao = cdcs->dcs.ao;
+    dc->readfd = cdcs->dcs.restore_fd;
+    dc->maxread = sizeof(cdcs->hdr);
+    cdcs->expected_len = dc->maxread;
+    dc->maxsz = INT_MAX;
+    dc->used = 0;
+    dc->callback = read_restore_hdr_cb;
+    dc->writefd = -1;
+    dc->readbuf = &cdcs->hdr;
+
+    libxl__datacopier_start(dc);
+}
+
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 2f74341..4160695 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -780,10 +780,8 @@ static inline char *restore_helper(libxl__gc *gc, uint32_t 
domid,
 }
 
 int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
-                             uint32_t size, void *user)
+                             uint32_t size, libxl__domain_create_state *dcs)
 {
-    libxl__save_helper_state *shs = user;
-    libxl__domain_create_state *dcs = CONTAINER_OF(shs, *dcs, shs);
     STATE_AO_GC(dcs->ao);
     int i, ret;
     const uint8_t *ptr = buf;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 537b523..3964009 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -991,8 +991,11 @@ _hidden int libxl__domain_rename(libxl__gc *gc, uint32_t 
domid,
                                  const char *old_name, const char *new_name,
                                  xs_transaction_t trans);
 
+typedef struct libxl__domain_create_state libxl__domain_create_state;
+
 _hidden int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
-                                     uint32_t size, void *data);
+                                     uint32_t size,
+                                     libxl__domain_create_state *dcs);
 _hidden int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid);
 
 _hidden const char *libxl__userdata_path(libxl__gc *gc, uint32_t domid,
@@ -2780,12 +2783,12 @@ _hidden int libxl__destroy_qdisk_backend(libxl__gc *gc, 
uint32_t domid);
 
 /*----- Domain creation -----*/
 
-typedef struct libxl__domain_create_state libxl__domain_create_state;
-
 typedef void libxl__domain_create_cb(libxl__egc *egc,
                                      libxl__domain_create_state*,
                                      int rc, uint32_t domid);
 
+typedef void libxl__domain_rebuild_cb(libxl__domain_create_state *dcs);
+
 struct libxl__domain_create_state {
     /* filled in by user */
     libxl__ao *ao;
@@ -2806,6 +2809,7 @@ struct libxl__domain_create_state {
     /* necessary if the domain creation failed and we have to destroy it */
     libxl__domain_destroy_state dds;
     libxl__multidev multidev;
+    libxl__domain_rebuild_cb *rebuild_callback;
 };
 
 /*----- Domain suspend (save) functions -----*/
-- 
1.7.10.4


_______________________________________________
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®.