[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 |