summary refs log tree commit diff stats
path: root/hw/xen/xen-bus-helper.c
diff options
context:
space:
mode:
authorPaul Durrant <paul.durrant@citrix.com>2019-01-08 14:48:49 +0000
committerAnthony PERARD <anthony.perard@citrix.com>2019-01-14 13:45:40 +0000
commit094a22399f1b3e796727fc7e584c7a1f2beca24b (patch)
tree0847863e115f47588149d2cba3f049d0f1ede2e9 /hw/xen/xen-bus-helper.c
parent1a72d9ae31517b2f83ec7923c820daf1887fde50 (diff)
downloadfocaccia-qemu-094a22399f1b3e796727fc7e584c7a1f2beca24b.tar.gz
focaccia-qemu-094a22399f1b3e796727fc7e584c7a1f2beca24b.zip
xen: create xenstore areas for XenDevice-s
This patch adds a new source module, xen-bus-helper.c, which builds on
basic libxenstore primitives to provide functions to create (setting
permissions appropriately) and destroy xenstore areas, and functions to
'printf' and 'scanf' nodes therein. The main xen-bus code then uses
these primitives [1] to initialize and destroy the frontend and backend
areas for a XenDevice during realize and unrealize respectively.

The 'xen-block' implementation is extended with a 'get_name' method that
returns the VBD number. This number is required to 'name' the xenstore
areas.

NOTE: An exit handler is also added to make sure the xenstore areas are
      cleaned up if QEMU terminates without devices being unrealized.

[1] The 'scanf' functions are actually not yet needed, but they will be
    needed by code delivered in subsequent patches.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Reviewed-by: Anthony Perard <anthony.perard@citrix.com>
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Diffstat (limited to 'hw/xen/xen-bus-helper.c')
-rw-r--r--hw/xen/xen-bus-helper.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/hw/xen/xen-bus-helper.c b/hw/xen/xen-bus-helper.c
new file mode 100644
index 0000000000..15b3ad8d78
--- /dev/null
+++ b/hw/xen/xen-bus-helper.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2018  Citrix Systems Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/sysbus.h"
+#include "hw/xen/xen.h"
+#include "hw/xen/xen-bus.h"
+#include "hw/xen/xen-bus-helper.h"
+#include "qapi/error.h"
+
+#include <glib/gprintf.h>
+
+struct xs_state {
+    enum xenbus_state statenum;
+    const char *statestr;
+};
+#define XS_STATE(state) { state, #state }
+
+static struct xs_state xs_state[] = {
+    XS_STATE(XenbusStateUnknown),
+    XS_STATE(XenbusStateInitialising),
+    XS_STATE(XenbusStateInitWait),
+    XS_STATE(XenbusStateInitialised),
+    XS_STATE(XenbusStateConnected),
+    XS_STATE(XenbusStateClosing),
+    XS_STATE(XenbusStateClosed),
+    XS_STATE(XenbusStateReconfiguring),
+    XS_STATE(XenbusStateReconfigured),
+};
+
+#undef XS_STATE
+
+const char *xs_strstate(enum xenbus_state state)
+{
+    unsigned int i;
+
+   for (i = 0; i < ARRAY_SIZE(xs_state); i++) {
+        if (xs_state[i].statenum == state) {
+            return xs_state[i].statestr;
+        }
+    }
+
+    return "INVALID";
+}
+
+void xs_node_create(struct xs_handle *xsh, xs_transaction_t tid,
+                    const char *node, struct xs_permissions perms[],
+                    unsigned int nr_perms, Error **errp)
+{
+    trace_xs_node_create(node);
+
+    if (!xs_write(xsh, tid, node, "", 0)) {
+        error_setg_errno(errp, errno, "failed to create node '%s'", node);
+        return;
+    }
+
+    if (!xs_set_permissions(xsh, tid, node, perms, nr_perms)) {
+        error_setg_errno(errp, errno, "failed to set node '%s' permissions",
+                         node);
+    }
+}
+
+void xs_node_destroy(struct xs_handle *xsh, xs_transaction_t tid,
+                     const char *node, Error **errp)
+{
+    trace_xs_node_destroy(node);
+
+    if (!xs_rm(xsh, tid, node)) {
+        error_setg_errno(errp, errno, "failed to destroy node '%s'", node);
+    }
+}
+
+void xs_node_vprintf(struct xs_handle *xsh, xs_transaction_t tid,
+                     const char *node, const char *key, Error **errp,
+                     const char *fmt, va_list ap)
+{
+    char *path, *value;
+    int len;
+
+    path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
+        g_strdup(key);
+    len = g_vasprintf(&value, fmt, ap);
+
+    trace_xs_node_vprintf(path, value);
+
+    if (!xs_write(xsh, tid, path, value, len)) {
+        error_setg_errno(errp, errno, "failed to write '%s' to '%s'",
+                         value, path);
+    }
+
+    g_free(value);
+    g_free(path);
+}
+
+void xs_node_printf(struct xs_handle *xsh,  xs_transaction_t tid,
+                    const char *node, const char *key, Error **errp,
+                    const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    xs_node_vprintf(xsh, tid, node, key, errp, fmt, ap);
+    va_end(ap);
+}
+
+int xs_node_vscanf(struct xs_handle *xsh,  xs_transaction_t tid,
+                   const char *node, const char *key, Error **errp,
+                   const char *fmt, va_list ap)
+{
+    char *path, *value;
+    int rc;
+
+    path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
+        g_strdup(key);
+    value = xs_read(xsh, tid, path, NULL);
+
+    trace_xs_node_vscanf(path, value);
+
+    if (value) {
+        rc = vsscanf(value, fmt, ap);
+    } else {
+        error_setg_errno(errp, errno, "failed to read from '%s'",
+                         path);
+        rc = EOF;
+    }
+
+    free(value);
+    g_free(path);
+
+    return rc;
+}
+
+int xs_node_scanf(struct xs_handle *xsh,  xs_transaction_t tid,
+                  const char *node, const char *key, Error **errp,
+                  const char *fmt, ...)
+{
+    va_list ap;
+    int rc;
+
+    va_start(ap, fmt);
+    rc = xs_node_vscanf(xsh, tid, node, key, errp, fmt, ap);
+    va_end(ap);
+
+    return rc;
+}