[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH for-4.6 v2 3/6] tools/libxl: Save and restore EMULATOR_XENSTORE_DATA content
The new EMULATOR_XENSTORE_DATA content is a sequence of NUL terminated key/value strings, with the key relative to the device model's xenstore tree. A sample might look like (as decoded by verify-stream-v2): Emulator Xenstore Data (Qemu Upstream, idx 0) 'physmap/1f00000/start_addr' = 'f0000000' 'physmap/1f00000/size' = '800000' 'physmap/1f00000/name' = 'vga.vram' This patch introduces libxl helpers to save and restore this new format, which reimplement the existing libxl__toolstack_{save,restore}() logic. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Ian Campbell <Ian.Campbell@xxxxxxxxxx> CC: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> CC: Wei Liu <wei.liu2@xxxxxxxxxx> v2: * Factor out pointer arithmatic into helper functions NB: I was unable to remove the rel_start bit, but its use has changed slightly and is hopefully more clear now. --- tools/libxl/libxl_dom.c | 138 ++++++++++++++++++++++++++++++++++++++++++ tools/libxl/libxl_internal.h | 4 ++ 2 files changed, 142 insertions(+) diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 5555fea..feed7b6 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -1151,6 +1151,76 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *ptr, return ret; } +/* + * Inspect the buffer between start and end, and return a pointer to the + * character following the NUL terminator of start, or NULL if start is not + * terminated before end. + */ +static const char *_next_string(const char *start, const char *end) +{ + if (start >= end) return NULL; + + size_t total_len = end - start; + size_t len = strnlen(start, total_len); + + if (len == total_len) + return NULL; + else + return start + len + 1; +} + +int libxl__restore_emulator_xenstore_data(libxl__domain_create_state *dcs, + const char *ptr, uint32_t size) +{ + STATE_AO_GC(dcs->ao); + const char *next = ptr, *end = ptr + size, *key, *val; + int rc; + + const uint32_t domid = dcs->guest_domid; + const uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid); + const char *xs_root = libxl__device_model_xs_path(gc, dm_domid, domid, ""); + + while (next < end) { + key = next; + next = _next_string(next, end); + + /* Sanitise 'key'. */ + if (!next) { + rc = ERROR_FAIL; + LOG(ERROR, "Key in xenstore data not NUL terminated"); + goto out; + } + if (key[0] == '\0') { + rc = ERROR_FAIL; + LOG(ERROR, "empty key found in xenstore data"); + goto out; + } + if (key[0] == '/') { + rc = ERROR_FAIL; + LOG(ERROR, "Key in xenstore data not relative"); + goto out; + } + + val = next; + next = _next_string(next, end); + + /* Sanitise 'val'. */ + if (!next) { + rc = ERROR_FAIL; + LOG(ERROR, "Val in xenstore data not NUL terminated"); + goto out; + } + + libxl__xs_write(gc, XBT_NULL, + GCSPRINTF("%s/%s", xs_root, key), "%s", val); + } + + rc = 0; + + out: + return rc; +} + /*==================== Domain suspend (save) ====================*/ static void stream_done(libxl__egc *egc, @@ -1487,6 +1557,74 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf, return ret; } +/* + * Expand the buffer 'buf' of length 'len', to append 'str' including its NUL + * terminator. + */ +static void _append_string(libxl__gc *gc, char **buf, uint32_t *len, + const char *str) +{ + size_t extralen = strlen(str) + 1; + char *new = libxl__realloc(gc, *buf, *len + extralen); + + *buf = new; + memcpy(new + *len, str, extralen); + *len += extralen; +} + +int libxl__save_emulator_xenstore_data(libxl__domain_suspend_state *dss, + char **callee_buf, + uint32_t *callee_len) +{ + STATE_AO_GC(dss->ao); + const char *xs_path; + char **entries, *buf = NULL; + unsigned int nr_entries, rel_start, i, j, len = 0; + int rc; + + const uint32_t domid = dss->domid; + const uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid); + + rel_start = strlen(libxl__device_model_xs_path(gc, dm_domid, domid, "/")); + /* path + rel_start is the xenstore path start from the dm root. */ + + xs_path = libxl__device_model_xs_path(gc, dm_domid, domid, "/physmap"); + if (!xs_path) { rc = 0; goto out; } + + entries = libxl__xs_directory(gc, 0, xs_path, &nr_entries); + if (!entries || nr_entries == 0) { rc = 0; goto out; } + + for (i = 0; i < nr_entries; ++i) { + static const char *const physmap_subkeys[] = { + "start_addr", "size", "name" + }; + + for (j = 0; j < ARRAY_SIZE(physmap_subkeys); ++j) { + const char *key = libxl__device_model_xs_path(gc, dm_domid, domid, + "/physmap/%s/%s", entries[i], physmap_subkeys[j]); + + if (!key) { rc = ERROR_FAIL; goto out; } + + const char *val = libxl__xs_read(gc, XBT_NULL, key); + + if (!val) { rc = ERROR_FAIL; goto out; } + + _append_string(gc, &buf, &len, key + rel_start); + _append_string(gc, &buf, &len, val); + } + } + + rc = 0; + + out: + if (!rc) { + *callee_buf = buf; + *callee_len = len; + } + + return rc; +} + /*----- remus callbacks -----*/ static void remus_domain_suspend_callback_common_done(libxl__egc *egc, libxl__domain_suspend_state *dss, int ok); diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 22d6a26..da2a785 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -3439,6 +3439,10 @@ void libxl__xc_domain_saverestore_async_callback_done(libxl__egc *egc, (int domid, unsigned int enable, void *data); _hidden int libxl__toolstack_save(uint32_t domid, uint8_t **buf, uint32_t *len, void *data); +_hidden int libxl__save_emulator_xenstore_data(libxl__domain_suspend_state *dss, + char **buf, uint32_t *len); +_hidden int libxl__restore_emulator_xenstore_data + (libxl__domain_create_state *dcs, const char *ptr, uint32_t size); /* calls libxl__xc_domain_restore_done when done */ -- 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 |