|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |