aboutsummaryrefslogtreecommitdiff
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)
downloadqemu-094a22399f1b3e796727fc7e584c7a1f2beca24b.zip
qemu-094a22399f1b3e796727fc7e584c7a1f2beca24b.tar.gz
qemu-094a22399f1b3e796727fc7e584c7a1f2beca24b.tar.bz2
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 0000000..15b3ad8
--- /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;
+}