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