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.

Signed-off-by: Andrew Cooper <andrew.coop...@citrix.com>
---
CC: Ian Campbell <ian.campb...@citrix.com>
CC: Ian Jackson <ian.jack...@eu.citrix.com>
CC: Wei Liu <wei.l...@citrix.com>
---
 tools/libxl/libxl_dom.c      |  141 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_internal.h |    4 ++
 2 files changed, 145 insertions(+)

diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 5555fea..885eb5e 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1151,6 +1151,65 @@ int libxl__toolstack_restore(uint32_t domid, const 
uint8_t *ptr,
     return ret;
 }
 
+int libxl__restore_emulator_xenstore_data(libxl__domain_create_state *dcs,
+                                          const char *ptr, uint32_t size)
+{
+    STATE_AO_GC(dcs->ao);
+    const char *key = ptr, *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 ( size ) {
+        /* Sanitise key. */
+        size_t keylen = strnlen(key, size);
+
+        if ( keylen == size ) {
+            rc = ERROR_FAIL;
+            LOG(ERROR, "Key in xenstore data not NUL terminated");
+            goto out;
+        }
+        if ( keylen == 0 ) {
+            rc = ERROR_FAIL;
+            LOG(ERROR, "NULL key found in xenstore data");
+            goto out;
+        }
+        if ( key[0] == '/' ) {
+            rc = ERROR_FAIL;
+            LOG(ERROR, "Key in xenstore data not relative");
+            goto out;
+        }
+
+        size -= (keylen + 1);
+
+        /* The val string starts after the NUL terminator of key. */
+        val = key + keylen + 1;
+
+        /* Sanitise val. */
+        size_t vallen = strnlen(val, size);
+
+        if ( vallen == size ) {
+            rc = ERROR_FAIL;
+            LOG(ERROR, "Val in xenstore data not NUL terminated");
+            goto out;
+        }
+
+        size -= (vallen + 1);
+
+        libxl__xs_write(gc, 0, GCSPRINTF("%s/%s", xs_root, key), "%s", val);
+
+        /* Move key forwards over the key and value pair just written. */
+        key = key + keylen + vallen + 2;
+    }
+
+    rc = 0;
+
+ out:
+    return rc;
+}
+
 /*==================== Domain suspend (save) ====================*/
 
 static void stream_done(libxl__egc *egc,
@@ -1487,6 +1546,88 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
     return ret;
 }
 
+int libxl__save_emulator_xenstore_data(libxl__domain_suspend_state *dss,
+                                       uint8_t **callee_buf,
+                                       uint32_t *callee_len)
+{
+    STATE_AO_GC(dss->ao);
+    const char *xs_path;
+    char **entries, *ptr, *buf = NULL;
+    unsigned int nr_entries, rel_start, i, len = 0;
+    int rc;
+
+    const uint32_t domid = dss->domid;
+    const uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid);
+
+    xs_path = libxl__device_model_xs_path(gc, dm_domid, domid, "/physmap");
+    if (!xs_path) { rc = 0; goto out; }
+
+    /* &foo[rel_start] is the xenstore path starting at the 'p' of physmap */
+    rel_start = strlen(xs_path) - 7;
+
+    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) {
+        const char *start_addr, *start_addr_val,
+            *size, *size_val, *name, *name_val;
+
+        start_addr = libxl__device_model_xs_path(
+            gc, dm_domid, domid, "/physmap/%s/start_addr", entries[i]);
+        size = libxl__device_model_xs_path(
+            gc, dm_domid, domid, "/physmap/%s/size", entries[i]);
+        name = libxl__device_model_xs_path(
+            gc, dm_domid, domid, "/physmap/%s/name", entries[i]);
+
+        if (!start_addr || !size || !name) { rc = ERROR_FAIL; goto out; }
+
+        start_addr_val = libxl__xs_read(gc, 0, start_addr);
+        size_val = libxl__xs_read(gc, 0, size);
+        name_val = libxl__xs_read(gc, 0, name);
+
+        if (!start_addr_val || !size_val || !name_val) {
+            rc = ERROR_FAIL; goto out;
+        }
+
+        /*
+         * Appends 's' to 'buf', including a NUL teriminator.  Mutates
+         * 'buf', 'ptr' and 'len' in scope.
+         */
+#define APPEND_STRING(s) ({                                     \
+                size_t sz = strlen(s) + 1;                      \
+                ptr = realloc(buf, len + sz);                   \
+                if (!ptr) { rc = ERROR_NOMEM; goto out; }       \
+                buf = ptr;                                      \
+                strcpy(&buf[len], s);                           \
+                len += sz;                                      \
+                buf[len - 1] = '\0';                            \
+            })
+
+        APPEND_STRING(&start_addr[rel_start]);
+        APPEND_STRING(start_addr_val);
+
+        APPEND_STRING(&size[rel_start]);
+        APPEND_STRING(size_val);
+
+        APPEND_STRING(&name[rel_start]);
+        APPEND_STRING(name_val);
+
+#undef APPEND_STRING
+    }
+
+    rc = 0;
+
+ out:
+    if (rc)
+        free(buf);
+    else {
+        *callee_buf = (uint8_t *)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 911de2d..8426221 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,
+                                               uint8_t **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@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to