[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[mini-os master] mini-os: drop xenbus directory



commit 8623cff59ba1b00d9bc838bea0c473f8ae137daa
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Mon Jun 20 09:38:13 2022 +0200
Commit:     Julien Grall <jgrall@xxxxxxxxxx>
CommitDate: Mon Jul 4 09:49:58 2022 +0100

    mini-os: drop xenbus directory
    
    The xenbus directory contains only a single source. Move this source
    up and remove the xenbus directory.
    
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
    Reviewed-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
---
 Makefile        |   3 +-
 xenbus.c        | 989 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xenbus/xenbus.c | 989 --------------------------------------------------------
 3 files changed, 990 insertions(+), 991 deletions(-)

diff --git a/Makefile b/Makefile
index 9f95d19..16d1f5d 100644
--- a/Makefile
+++ b/Makefile
@@ -57,6 +57,7 @@ src-y += sched.c
 src-y += shutdown.c
 src-$(CONFIG_TEST) += test.c
 src-$(CONFIG_BALLOON) += balloon.c
+src-$(CONFIG_XENBUS) += xenbus.c
 
 src-y += lib/ctype.c
 src-y += lib/math.c
@@ -67,8 +68,6 @@ src-y += lib/sys.c
 src-y += lib/xmalloc.c
 src-$(CONFIG_LIBXS) += lib/xs.c
 
-src-$(CONFIG_XENBUS) += xenbus/xenbus.c
-
 src-y += console/console.c
 src-y += console/xencons_ring.c
 src-$(CONFIG_CONSFRONT) += console/xenbus.c
diff --git a/xenbus.c b/xenbus.c
new file mode 100644
index 0000000..b687678
--- /dev/null
+++ b/xenbus.c
@@ -0,0 +1,989 @@
+/* 
+ ****************************************************************************
+ * (C) 2006 - Cambridge University
+ ****************************************************************************
+ *
+ *        File: xenbus.c
+ *      Author: Steven Smith (sos22@xxxxxxxxx) 
+ *     Changes: Grzegorz Milos (gm281@xxxxxxxxx)
+ *     Changes: John D. Ramsdell
+ *              
+ *        Date: Jun 2006, chages Aug 2005
+ * 
+ * Environment: Xen Minimal OS
+ * Description: Minimal implementation of xenbus
+ *
+ ****************************************************************************
+ **/
+#include <inttypes.h>
+#include <mini-os/os.h>
+#include <mini-os/mm.h>
+#include <mini-os/traps.h>
+#include <mini-os/lib.h>
+#include <mini-os/xenbus.h>
+#include <mini-os/events.h>
+#include <mini-os/errno.h>
+#include <mini-os/sched.h>
+#include <mini-os/wait.h>
+#include <xen/io/xs_wire.h>
+#include <xen/hvm/params.h>
+#include <mini-os/spinlock.h>
+#include <mini-os/xmalloc.h>
+#include <mini-os/semaphore.h>
+
+#define min(x,y) ({                       \
+        typeof(x) tmpx = (x);                 \
+        typeof(y) tmpy = (y);                 \
+        tmpx < tmpy ? tmpx : tmpy;            \
+        })
+
+#ifdef XENBUS_DEBUG
+#define DEBUG(_f, _a...) \
+    printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
+#else
+#define DEBUG(_f, _a...)    ((void)0)
+#endif
+
+static struct xenstore_domain_interface *xenstore_buf;
+static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
+static __DECLARE_SEMAPHORE_GENERIC(xb_write_sem, 1);
+
+xenbus_event_queue xenbus_events;
+static struct watch {
+    char *token;
+    char *path;
+    xenbus_event_queue *events;
+    struct watch *next;
+} *watches;
+struct xenbus_req_info 
+{
+    int in_use:1;
+    struct wait_queue_head waitq;
+    void *reply;
+};
+
+#define NR_REQS 32
+static struct xenbus_req_info req_info[NR_REQS];
+
+static char *errmsg(struct xsd_sockmsg *rep);
+
+uint32_t xenbus_evtchn;
+
+#ifdef CONFIG_PARAVIRT
+void get_xenbus(void *p)
+{
+    start_info_t *si = p;
+
+    xenbus_evtchn = si->store_evtchn;
+    xenstore_buf = mfn_to_virt(si->store_mfn);
+}
+#else
+void get_xenbus(void *p)
+{
+    uint64_t v;
+
+    if ( hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v) )
+        BUG();
+    xenbus_evtchn = v;
+
+    if( hvm_get_parameter(HVM_PARAM_STORE_PFN, &v) )
+        BUG();
+    xenstore_buf = (struct xenstore_domain_interface *)map_frame_virt(v);
+}
+#endif
+
+static void memcpy_from_ring(const void *Ring,
+        void *Dest,
+        int off,
+        int len)
+{
+    int c1, c2;
+    const char *ring = Ring;
+    char *dest = Dest;
+    c1 = min(len, XENSTORE_RING_SIZE - off);
+    c2 = len - c1;
+    memcpy(dest, ring + off, c1);
+    memcpy(dest + c1, ring, c2);
+}
+
+char **xenbus_wait_for_watch_return(xenbus_event_queue *queue)
+{
+    struct xenbus_event *event;
+    DEFINE_WAIT(w);
+    if (!queue)
+        queue = &xenbus_events;
+    while (!(event = *queue)) {
+        add_waiter(w, xenbus_watch_queue);
+        schedule();
+    }
+    remove_waiter(w, xenbus_watch_queue);
+    *queue = event->next;
+    return &event->path;
+}
+
+void xenbus_wait_for_watch(xenbus_event_queue *queue)
+{
+    char **ret;
+    if (!queue)
+        queue = &xenbus_events;
+    ret = xenbus_wait_for_watch_return(queue);
+    if (ret)
+        free(ret);
+    else
+        printk("unexpected path returned by watch\n");
+}
+
+void xenbus_release_wait_for_watch(xenbus_event_queue *queue)
+{
+    struct xenbus_event *event = malloc(sizeof(*event));
+    event->next = *queue;
+    *queue = event;
+    wake_up(&xenbus_watch_queue);
+}
+
+char* xenbus_wait_for_value(const char* path, const char* value, 
xenbus_event_queue *queue)
+{
+    if (!queue)
+        queue = &xenbus_events;
+    for(;;)
+    {
+        char *res, *msg;
+        int r;
+
+        msg = xenbus_read(XBT_NIL, path, &res);
+        if(msg) return msg;
+
+        r = strcmp(value,res);
+        free(res);
+
+        if(r==0) break;
+        else xenbus_wait_for_watch(queue);
+    }
+    return NULL;
+}
+
+char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, 
XenbusState state)
+{
+    char *current_state;
+    char *msg = NULL;
+    char *msg2 = NULL;
+    char value[2];
+    XenbusState rs;
+    int xbt_flag = 0;
+    int retry = 0;
+
+    do {
+        if (xbt == XBT_NIL) {
+            msg = xenbus_transaction_start(&xbt);
+            if (msg) goto exit;
+            xbt_flag = 1;
+        }
+
+        msg = xenbus_read(xbt, path, &current_state);
+        if (msg) goto exit;
+
+        rs = (XenbusState) (current_state[0] - '0');
+        free(current_state);
+        if (rs == state) {
+            msg = NULL;
+            goto exit;
+        }
+
+        snprintf(value, 2, "%d", state);
+        msg = xenbus_write(xbt, path, value);
+
+exit:
+        if (xbt_flag) {
+            msg2 = xenbus_transaction_end(xbt, 0, &retry);
+            xbt = XBT_NIL;
+        }
+        if (msg == NULL && msg2 != NULL)
+            msg = msg2;
+        else
+            free(msg2);
+    } while (retry);
+
+    return msg;
+}
+
+char *xenbus_wait_for_state_change(const char* path, XenbusState *state, 
xenbus_event_queue *queue)
+{
+    if (!queue)
+        queue = &xenbus_events;
+    for(;;)
+    {
+        char *res, *msg;
+        XenbusState rs;
+
+        msg = xenbus_read(XBT_NIL, path, &res);
+        if(msg) return msg;
+
+        rs = (XenbusState) (res[0] - 48);
+        free(res);
+
+        if (rs == *state)
+            xenbus_wait_for_watch(queue);
+        else {
+            *state = rs;
+            break;
+        }
+    }
+    return NULL;
+}
+
+
+static void xenbus_read_data(char *buf, unsigned int len)
+{
+    unsigned int off = 0;
+    unsigned int prod, cons;
+    unsigned int size;
+
+    while (off != len)
+    {
+        wait_event(xb_waitq, xenstore_buf->rsp_prod != xenstore_buf->rsp_cons);
+
+        prod = xenstore_buf->rsp_prod;
+        cons = xenstore_buf->rsp_cons;
+        DEBUG("Rsp_cons %d, rsp_prod %d.\n", cons, prod);
+        size = min(len - off, prod - cons);
+
+        rmb();   /* Make sure data read from ring is ordered with rsp_prod. */
+        memcpy_from_ring(xenstore_buf->rsp, buf + off,
+                         MASK_XENSTORE_IDX(cons), size);
+        off += size;
+        mb();    /* memcpy() and rsp_cons update must not be reordered. */
+        xenstore_buf->rsp_cons += size;
+        mb();    /* rsp_cons must be visible before we look at rsp_prod. */
+        if (xenstore_buf->rsp_prod - cons >= XENSTORE_RING_SIZE)
+            notify_remote_via_evtchn(xenbus_evtchn);
+    }
+}
+
+static void xenbus_thread_func(void *ign)
+{
+    struct xsd_sockmsg msg;
+    char *data;
+
+    for (;;) {
+        xenbus_read_data((char *)&msg, sizeof(msg));
+        DEBUG("Msg len %d, %d avail, id %d.\n", msg.len + sizeof(msg),
+              xenstore_buf->rsp_prod - xenstore_buf->rsp_cons, msg.req_id);
+
+        if (msg.len > XENSTORE_PAYLOAD_MAX) {
+            printk("Xenstore violates protocol, message longer than 
allowed.\n");
+            return;
+        }
+
+        if (msg.type == XS_WATCH_EVENT) {
+            struct xenbus_event *event = malloc(sizeof(*event) + msg.len);
+            xenbus_event_queue *events = NULL;
+            struct watch *watch;
+            char *c;
+            int zeroes = 0;
+
+            data = (char*)event + sizeof(*event);
+            xenbus_read_data(data, msg.len);
+
+            for (c = data; c < data + msg.len; c++)
+                if (!*c)
+                    zeroes++;
+            if (zeroes != 2) {
+                printk("Xenstore: illegal watch event data\n");
+                free(event);
+                continue;
+            }
+
+            event->path = data;
+            event->token = event->path + strlen(event->path) + 1;
+
+            for (watch = watches; watch; watch = watch->next)
+                if (!strcmp(watch->token, event->token)) {
+                    events = watch->events;
+                    break;
+                }
+
+            if (events) {
+                event->next = *events;
+                *events = event;
+                wake_up(&xenbus_watch_queue);
+            } else {
+                printk("Xenstore: unexpected watch token %s\n", event->token);
+                free(event);
+            }
+
+            continue;
+        }
+
+        data = malloc(sizeof(msg) + msg.len);
+        memcpy(data, &msg, sizeof(msg));
+        xenbus_read_data(data + sizeof(msg), msg.len);
+
+        if (msg.req_id >= NR_REQS || !req_info[msg.req_id].in_use) {
+            printk("Xenstore: illegal request id %d\n", msg.req_id);
+            free(data);
+            continue;
+        }
+
+        DEBUG("Message is good.\n");
+
+        req_info[msg.req_id].reply = data;
+
+        wake_up(&req_info[msg.req_id].waitq);
+    }
+}
+
+static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
+                                 void *ign)
+{
+    wake_up(&xb_waitq);
+}
+
+static int nr_live_reqs;
+static DEFINE_SPINLOCK(req_lock);
+static DECLARE_WAIT_QUEUE_HEAD(req_wq);
+
+/* Release a xenbus identifier */
+static void release_xenbus_id(int id)
+{
+    BUG_ON(!req_info[id].in_use);
+    spin_lock(&req_lock);
+    req_info[id].in_use = 0;
+    nr_live_reqs--;
+    req_info[id].in_use = 0;
+    if (nr_live_reqs == 0 || nr_live_reqs == NR_REQS - 1)
+        wake_up(&req_wq);
+    spin_unlock(&req_lock);
+}
+
+/* Allocate an identifier for a xenbus request.  Blocks if none are
+   available. */
+static int allocate_xenbus_id(void)
+{
+    static int probe;
+    int o_probe;
+
+    while (1) 
+    {
+        spin_lock(&req_lock);
+        if (nr_live_reqs < NR_REQS)
+            break;
+        spin_unlock(&req_lock);
+        wait_event(req_wq, (nr_live_reqs < NR_REQS));
+    }
+
+    o_probe = probe;
+    for (;;) 
+    {
+        if (!req_info[o_probe].in_use)
+            break;
+        o_probe = (o_probe + 1) % NR_REQS;
+        BUG_ON(o_probe == probe);
+    }
+    nr_live_reqs++;
+    req_info[o_probe].in_use = 1;
+    probe = (o_probe + 1) % NR_REQS;
+    spin_unlock(&req_lock);
+    init_waitqueue_head(&req_info[o_probe].waitq);
+
+    return o_probe;
+}
+
+/* Initialise xenbus. */
+void init_xenbus(void)
+{
+    int err;
+    DEBUG("init_xenbus called.\n");
+    create_thread("xenstore", xenbus_thread_func, NULL);
+    DEBUG("buf at %p.\n", xenstore_buf);
+    err = bind_evtchn(xenbus_evtchn, xenbus_evtchn_handler, NULL);
+    unmask_evtchn(xenbus_evtchn);
+    printk("xenbus initialised on irq %d\n", err);
+}
+
+void fini_xenbus(void)
+{
+}
+
+void suspend_xenbus(void)
+{
+    /* Check for live requests and wait until they finish */
+    while (1)
+    {
+        spin_lock(&req_lock);
+        if (nr_live_reqs == 0)
+            break;
+        spin_unlock(&req_lock);
+        wait_event(req_wq, (nr_live_reqs == 0));
+    }
+
+    mask_evtchn(xenbus_evtchn);
+    xenstore_buf = NULL;
+    spin_unlock(&req_lock);
+}
+
+void resume_xenbus(int canceled)
+{
+    char *msg;
+    struct watch *watch;
+    struct write_req req[2];
+    struct xsd_sockmsg *rep;
+
+#ifdef CONFIG_PARAVIRT
+    get_xenbus(&start_info);
+#else
+    get_xenbus(0);
+#endif
+    unmask_evtchn(xenbus_evtchn);
+
+    if (!canceled) {
+        for (watch = watches; watch; watch = watch->next) {
+            req[0].data = watch->path;
+            req[0].len = strlen(watch->path) + 1;
+            req[1].data = watch->token;
+            req[1].len = strlen(watch->token) + 1;
+
+            rep = xenbus_msg_reply(XS_WATCH, XBT_NIL, req, ARRAY_SIZE(req));
+            msg = errmsg(rep);
+            if (msg) {
+                xprintk("error on XS_WATCH: %s\n", msg);
+                free(msg);
+            } else
+                free(rep);
+        }
+    }
+
+    notify_remote_via_evtchn(xenbus_evtchn);
+}
+
+/* Send data to xenbus.  This can block.  All of the requests are seen
+   by xenbus as if sent atomically.  The header is added
+   automatically, using type %type, req_id %req_id, and trans_id
+   %trans_id. */
+static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
+                    const struct write_req *req, int nr_reqs)
+{
+    XENSTORE_RING_IDX prod;
+    int r;
+    int len = 0;
+    const struct write_req *cur_req;
+    int req_off;
+    int total_off;
+    int this_chunk;
+    struct xsd_sockmsg m = {.type = type, .req_id = req_id,
+        .tx_id = trans_id };
+    struct write_req header_req = { &m, sizeof(m) };
+
+    for (r = 0; r < nr_reqs; r++)
+        len += req[r].len;
+    m.len = len;
+    len += sizeof(m);
+
+    cur_req = &header_req;
+
+    BUG_ON(len > XENSTORE_PAYLOAD_MAX);
+
+    /* Make sure we are the only thread trying to write. */
+    down(&xb_write_sem);
+
+    /* Send the message in chunks using free ring space when available. */
+    total_off = 0;
+    req_off = 0;
+    while (total_off < len)
+    {
+        prod = xenstore_buf->req_prod;
+        if (prod - xenstore_buf->req_cons >= XENSTORE_RING_SIZE)
+        {
+            /* Send evtchn to notify remote */
+            notify_remote_via_evtchn(xenbus_evtchn);
+
+            /* Wait for there to be space on the ring */
+            DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n", prod,
+                  len - total_off, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
+            wait_event(xb_waitq,
+                       prod - xenstore_buf->req_cons < XENSTORE_RING_SIZE);
+            DEBUG("Back from wait.\n");
+        }
+
+        this_chunk = min(cur_req->len - req_off,
+                         XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
+        this_chunk = min(this_chunk,
+                         xenstore_buf->req_cons + XENSTORE_RING_SIZE - prod);
+        memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
+               (char *)cur_req->data + req_off, this_chunk);
+        prod += this_chunk;
+        req_off += this_chunk;
+        total_off += this_chunk;
+        if (req_off == cur_req->len)
+        {
+            req_off = 0;
+            if (cur_req == &header_req)
+                cur_req = req;
+            else
+                cur_req++;
+        }
+
+        /* Remote must see entire message before updating indexes */
+        wmb();
+        xenstore_buf->req_prod = prod;
+    }
+
+    /* Send evtchn to notify remote */
+    notify_remote_via_evtchn(xenbus_evtchn);
+
+    DEBUG("Complete main loop of xb_write.\n");
+    BUG_ON(req_off != 0);
+    BUG_ON(total_off != len);
+
+    up(&xb_write_sem);
+}
+
+/* Send a mesasge to xenbus, in the same fashion as xb_write, and
+   block waiting for a reply.  The reply is malloced and should be
+   freed by the caller. */
+struct xsd_sockmsg *
+xenbus_msg_reply(int type,
+                xenbus_transaction_t trans,
+                struct write_req *io,
+                int nr_reqs)
+{
+    int id;
+    DEFINE_WAIT(w);
+    struct xsd_sockmsg *rep;
+
+    id = allocate_xenbus_id();
+    add_waiter(w, req_info[id].waitq);
+
+    xb_write(type, id, trans, io, nr_reqs);
+
+    schedule();
+    remove_waiter(w, req_info[id].waitq);
+    wake(current);
+
+    rep = req_info[id].reply;
+    BUG_ON(rep->req_id != id);
+    release_xenbus_id(id);
+    return rep;
+}
+
+static char *errmsg(struct xsd_sockmsg *rep)
+{
+    char *res;
+    if (!rep) {
+       char msg[] = "No reply";
+       size_t len = strlen(msg) + 1;
+       return memcpy(malloc(len), msg, len);
+    }
+    if (rep->type != XS_ERROR)
+       return NULL;
+    res = malloc(rep->len + 1);
+    memcpy(res, rep + 1, rep->len);
+    res[rep->len] = 0;
+    free(rep);
+    return res;
+}
+
+/* List the contents of a directory.  Returns a malloc()ed array of
+   pointers to malloc()ed strings.  The array is NULL terminated.  May
+   block. */
+char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
+{
+    struct xsd_sockmsg *reply, *repmsg;
+    struct write_req req[] = { { pre, strlen(pre)+1 } };
+    int nr_elems, x, i;
+    char **res, *msg;
+
+    repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
+    msg = errmsg(repmsg);
+    if (msg) {
+       *contents = NULL;
+       return msg;
+    }
+    reply = repmsg + 1;
+    for (x = nr_elems = 0; x < repmsg->len; x++)
+        nr_elems += (((char *)reply)[x] == 0);
+    res = malloc(sizeof(res[0]) * (nr_elems + 1));
+    for (x = i = 0; i < nr_elems; i++) {
+        int l = strlen((char *)reply + x);
+        res[i] = malloc(l + 1);
+        memcpy(res[i], (char *)reply + x, l + 1);
+        x += l + 1;
+    }
+    res[i] = NULL;
+    free(repmsg);
+    *contents = res;
+    return NULL;
+}
+
+char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
+{
+    struct write_req req[] = { {path, strlen(path) + 1} };
+    struct xsd_sockmsg *rep;
+    char *res, *msg;
+    rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
+    msg = errmsg(rep);
+    if (msg) {
+       *value = NULL;
+       return msg;
+    }
+    res = malloc(rep->len + 1);
+    memcpy(res, rep + 1, rep->len);
+    res[rep->len] = 0;
+    free(rep);
+    *value = res;
+    return NULL;
+}
+
+char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char 
*value)
+{
+    struct write_req req[] = { 
+       {path, strlen(path) + 1},
+       {value, strlen(value)},
+    };
+    struct xsd_sockmsg *rep;
+    char *msg;
+    rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
+    msg = errmsg(rep);
+    if (msg) return msg;
+    free(rep);
+    return NULL;
+}
+
+char* xenbus_watch_path_token( xenbus_transaction_t xbt, const char *path, 
const char *token, xenbus_event_queue *events)
+{
+    struct xsd_sockmsg *rep;
+
+    struct write_req req[] = { 
+        {path, strlen(path) + 1},
+       {token, strlen(token) + 1},
+    };
+
+    struct watch *watch = malloc(sizeof(*watch));
+
+    char *msg;
+
+    if (!events)
+        events = &xenbus_events;
+
+    watch->token = strdup(token);
+    watch->path = strdup(path);
+    watch->events = events;
+    watch->next = watches;
+    watches = watch;
+
+    rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
+
+    msg = errmsg(rep);
+    if (msg) return msg;
+    free(rep);
+
+    return NULL;
+}
+
+char* xenbus_unwatch_path_token( xenbus_transaction_t xbt, const char *path, 
const char *token)
+{
+    struct xsd_sockmsg *rep;
+
+    struct write_req req[] = { 
+        {path, strlen(path) + 1},
+       {token, strlen(token) + 1},
+    };
+
+    struct watch *watch, **prev;
+
+    char *msg;
+
+    rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
+
+    msg = errmsg(rep);
+    if (msg) return msg;
+    free(rep);
+
+    for (prev = &watches, watch = *prev; watch; prev = &watch->next, watch = 
*prev)
+        if (!strcmp(watch->token, token)) {
+            free(watch->token);
+            free(watch->path);
+            *prev = watch->next;
+            free(watch);
+            break;
+        }
+
+    return NULL;
+}
+
+char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
+{
+    struct write_req req[] = { {path, strlen(path) + 1} };
+    struct xsd_sockmsg *rep;
+    char *msg;
+    rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
+    msg = errmsg(rep);
+    if (msg)
+       return msg;
+    free(rep);
+    return NULL;
+}
+
+char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char 
**value)
+{
+    struct write_req req[] = { {path, strlen(path) + 1} };
+    struct xsd_sockmsg *rep;
+    char *res, *msg;
+    rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
+    msg = errmsg(rep);
+    if (msg) {
+       *value = NULL;
+       return msg;
+    }
+    res = malloc(rep->len + 1);
+    memcpy(res, rep + 1, rep->len);
+    res[rep->len] = 0;
+    free(rep);
+    *value = res;
+    return NULL;
+}
+
+#define PERM_MAX_SIZE 32
+char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t 
dom, char perm)
+{
+    char value[PERM_MAX_SIZE];
+    struct write_req req[] = { 
+       {path, strlen(path) + 1},
+       {value, 0},
+    };
+    struct xsd_sockmsg *rep;
+    char *msg;
+    snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
+    req[1].len = strlen(value) + 1;
+    rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
+    msg = errmsg(rep);
+    if (msg)
+       return msg;
+    free(rep);
+    return NULL;
+}
+
+char *xenbus_transaction_start(xenbus_transaction_t *xbt)
+{
+    /* xenstored becomes angry if you send a length 0 message, so just
+       shove a nul terminator on the end */
+    struct write_req req = { "", 1};
+    struct xsd_sockmsg *rep;
+    char *err;
+
+    rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
+    err = errmsg(rep);
+    if (err)
+       return err;
+    sscanf((char *)(rep + 1), "%lu", xbt);
+    free(rep);
+    return NULL;
+}
+
+char *
+xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
+{
+    struct xsd_sockmsg *rep;
+    struct write_req req;
+    char *err;
+
+    *retry = 0;
+
+    req.data = abort ? "F" : "T";
+    req.len = 2;
+    rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
+    err = errmsg(rep);
+    if (err) {
+       if (!strcmp(err, "EAGAIN")) {
+           *retry = 1;
+           free(err);
+           return NULL;
+       } else {
+           return err;
+       }
+    }
+    free(rep);
+    return NULL;
+}
+
+int xenbus_read_integer(const char *path)
+{
+    char *res, *buf;
+    int t;
+
+    res = xenbus_read(XBT_NIL, path, &buf);
+    if (res) {
+       printk("Failed to read %s.\n", path);
+       free(res);
+       return -1;
+    }
+    sscanf(buf, "%d", &t);
+    free(buf);
+    return t;
+}
+
+int xenbus_read_uuid(const char* path, unsigned char uuid[16]) {
+   char * res, *buf;
+   res = xenbus_read(XBT_NIL, path, &buf);
+   if(res) {
+      printk("Failed to read %s.\n", path);
+      free(res);
+      return 0;
+   }
+   if(strlen(buf) != ((2*16)+4) /* 16 hex bytes and 4 hyphens */
+         || sscanf(buf,
+            "%2hhx%2hhx%2hhx%2hhx-"
+            "%2hhx%2hhx-"
+            "%2hhx%2hhx-"
+            "%2hhx%2hhx-"
+            "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
+            uuid, uuid + 1, uuid + 2, uuid + 3,
+            uuid + 4, uuid + 5, uuid + 6, uuid + 7,
+            uuid + 8, uuid + 9, uuid + 10, uuid + 11,
+            uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
+      printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
+      free(buf);
+      return 0;
+   }
+   free(buf);
+   return 1;
+}
+
+char* xenbus_printf(xenbus_transaction_t xbt,
+                                  const char* node, const char* path,
+                                  const char* fmt, ...)
+{
+#define BUFFER_SIZE 256
+    char fullpath[BUFFER_SIZE];
+    char val[BUFFER_SIZE];
+    va_list args;
+
+    BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
+    sprintf(fullpath,"%s/%s", node, path);
+    va_start(args, fmt);
+    vsprintf(val, fmt, args);
+    va_end(args);
+    return xenbus_write(xbt,fullpath,val);
+}
+
+domid_t xenbus_get_self_id(void)
+{
+    char *dom_id;
+    domid_t ret;
+
+    BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
+    sscanf(dom_id, "%"SCNd16, &ret);
+
+    return ret;
+}
+
+#ifdef CONFIG_TEST
+/* Send a debug message to xenbus.  Can block. */
+static void xenbus_debug_msg(const char *msg)
+{
+    int len = strlen(msg);
+    struct write_req req[] = {
+        { "print", sizeof("print") },
+        { msg, len },
+        { "", 1 }};
+    struct xsd_sockmsg *reply;
+
+    reply = xenbus_msg_reply(XS_DEBUG, 0, req, ARRAY_SIZE(req));
+    printk("Got a reply, type %d, id %d, len %d.\n",
+            reply->type, reply->req_id, reply->len);
+}
+
+static void do_ls_test(const char *pre)
+{
+    char **dirs, *msg;
+    int x;
+
+    printk("ls %s...\n", pre);
+    msg = xenbus_ls(XBT_NIL, pre, &dirs);
+    if (msg) {
+       printk("Error in xenbus ls: %s\n", msg);
+       free(msg);
+       return;
+    }
+    for (x = 0; dirs[x]; x++) 
+    {
+        printk("ls %s[%d] -> %s\n", pre, x, dirs[x]);
+        free(dirs[x]);
+    }
+    free(dirs);
+}
+
+static void do_read_test(const char *path)
+{
+    char *res, *msg;
+    printk("Read %s...\n", path);
+    msg = xenbus_read(XBT_NIL, path, &res);
+    if (msg) {
+       printk("Error in xenbus read: %s\n", msg);
+       free(msg);
+       return;
+    }
+    printk("Read %s -> %s.\n", path, res);
+    free(res);
+}
+
+static void do_write_test(const char *path, const char *val)
+{
+    char *msg;
+    printk("Write %s to %s...\n", val, path);
+    msg = xenbus_write(XBT_NIL, path, val);
+    if (msg) {
+       printk("Result %s\n", msg);
+       free(msg);
+    } else {
+       printk("Success.\n");
+    }
+}
+
+static void do_rm_test(const char *path)
+{
+    char *msg;
+    printk("rm %s...\n", path);
+    msg = xenbus_rm(XBT_NIL, path);
+    if (msg) {
+       printk("Result %s\n", msg);
+       free(msg);
+    } else {
+       printk("Success.\n");
+    }
+}
+
+/* Simple testing thing */
+void test_xenbus(void)
+{
+    printk("Doing xenbus test.\n");
+    xenbus_debug_msg("Testing xenbus...\n");
+
+    printk("Doing ls test.\n");
+    do_ls_test("device");
+    do_ls_test("device/vif");
+    do_ls_test("device/vif/0");
+
+    printk("Doing read test.\n");
+    do_read_test("device/vif/0/mac");
+    do_read_test("device/vif/0/backend");
+
+    printk("Doing write test.\n");
+    do_write_test("device/vif/0/flibble", "flobble");
+    do_read_test("device/vif/0/flibble");
+    do_write_test("device/vif/0/flibble", "widget");
+    do_read_test("device/vif/0/flibble");
+
+    printk("Doing rm test.\n");
+    do_rm_test("device/vif/0/flibble");
+    do_read_test("device/vif/0/flibble");
+    printk("(Should have said ENOENT)\n");
+}
+#endif /* CONFIG_TEST */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/xenbus/xenbus.c b/xenbus/xenbus.c
deleted file mode 100644
index b687678..0000000
--- a/xenbus/xenbus.c
+++ /dev/null
@@ -1,989 +0,0 @@
-/* 
- ****************************************************************************
- * (C) 2006 - Cambridge University
- ****************************************************************************
- *
- *        File: xenbus.c
- *      Author: Steven Smith (sos22@xxxxxxxxx) 
- *     Changes: Grzegorz Milos (gm281@xxxxxxxxx)
- *     Changes: John D. Ramsdell
- *              
- *        Date: Jun 2006, chages Aug 2005
- * 
- * Environment: Xen Minimal OS
- * Description: Minimal implementation of xenbus
- *
- ****************************************************************************
- **/
-#include <inttypes.h>
-#include <mini-os/os.h>
-#include <mini-os/mm.h>
-#include <mini-os/traps.h>
-#include <mini-os/lib.h>
-#include <mini-os/xenbus.h>
-#include <mini-os/events.h>
-#include <mini-os/errno.h>
-#include <mini-os/sched.h>
-#include <mini-os/wait.h>
-#include <xen/io/xs_wire.h>
-#include <xen/hvm/params.h>
-#include <mini-os/spinlock.h>
-#include <mini-os/xmalloc.h>
-#include <mini-os/semaphore.h>
-
-#define min(x,y) ({                       \
-        typeof(x) tmpx = (x);                 \
-        typeof(y) tmpy = (y);                 \
-        tmpx < tmpy ? tmpx : tmpy;            \
-        })
-
-#ifdef XENBUS_DEBUG
-#define DEBUG(_f, _a...) \
-    printk("MINI_OS(file=xenbus.c, line=%d) " _f , __LINE__, ## _a)
-#else
-#define DEBUG(_f, _a...)    ((void)0)
-#endif
-
-static struct xenstore_domain_interface *xenstore_buf;
-static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
-DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
-static __DECLARE_SEMAPHORE_GENERIC(xb_write_sem, 1);
-
-xenbus_event_queue xenbus_events;
-static struct watch {
-    char *token;
-    char *path;
-    xenbus_event_queue *events;
-    struct watch *next;
-} *watches;
-struct xenbus_req_info 
-{
-    int in_use:1;
-    struct wait_queue_head waitq;
-    void *reply;
-};
-
-#define NR_REQS 32
-static struct xenbus_req_info req_info[NR_REQS];
-
-static char *errmsg(struct xsd_sockmsg *rep);
-
-uint32_t xenbus_evtchn;
-
-#ifdef CONFIG_PARAVIRT
-void get_xenbus(void *p)
-{
-    start_info_t *si = p;
-
-    xenbus_evtchn = si->store_evtchn;
-    xenstore_buf = mfn_to_virt(si->store_mfn);
-}
-#else
-void get_xenbus(void *p)
-{
-    uint64_t v;
-
-    if ( hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v) )
-        BUG();
-    xenbus_evtchn = v;
-
-    if( hvm_get_parameter(HVM_PARAM_STORE_PFN, &v) )
-        BUG();
-    xenstore_buf = (struct xenstore_domain_interface *)map_frame_virt(v);
-}
-#endif
-
-static void memcpy_from_ring(const void *Ring,
-        void *Dest,
-        int off,
-        int len)
-{
-    int c1, c2;
-    const char *ring = Ring;
-    char *dest = Dest;
-    c1 = min(len, XENSTORE_RING_SIZE - off);
-    c2 = len - c1;
-    memcpy(dest, ring + off, c1);
-    memcpy(dest + c1, ring, c2);
-}
-
-char **xenbus_wait_for_watch_return(xenbus_event_queue *queue)
-{
-    struct xenbus_event *event;
-    DEFINE_WAIT(w);
-    if (!queue)
-        queue = &xenbus_events;
-    while (!(event = *queue)) {
-        add_waiter(w, xenbus_watch_queue);
-        schedule();
-    }
-    remove_waiter(w, xenbus_watch_queue);
-    *queue = event->next;
-    return &event->path;
-}
-
-void xenbus_wait_for_watch(xenbus_event_queue *queue)
-{
-    char **ret;
-    if (!queue)
-        queue = &xenbus_events;
-    ret = xenbus_wait_for_watch_return(queue);
-    if (ret)
-        free(ret);
-    else
-        printk("unexpected path returned by watch\n");
-}
-
-void xenbus_release_wait_for_watch(xenbus_event_queue *queue)
-{
-    struct xenbus_event *event = malloc(sizeof(*event));
-    event->next = *queue;
-    *queue = event;
-    wake_up(&xenbus_watch_queue);
-}
-
-char* xenbus_wait_for_value(const char* path, const char* value, 
xenbus_event_queue *queue)
-{
-    if (!queue)
-        queue = &xenbus_events;
-    for(;;)
-    {
-        char *res, *msg;
-        int r;
-
-        msg = xenbus_read(XBT_NIL, path, &res);
-        if(msg) return msg;
-
-        r = strcmp(value,res);
-        free(res);
-
-        if(r==0) break;
-        else xenbus_wait_for_watch(queue);
-    }
-    return NULL;
-}
-
-char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, 
XenbusState state)
-{
-    char *current_state;
-    char *msg = NULL;
-    char *msg2 = NULL;
-    char value[2];
-    XenbusState rs;
-    int xbt_flag = 0;
-    int retry = 0;
-
-    do {
-        if (xbt == XBT_NIL) {
-            msg = xenbus_transaction_start(&xbt);
-            if (msg) goto exit;
-            xbt_flag = 1;
-        }
-
-        msg = xenbus_read(xbt, path, &current_state);
-        if (msg) goto exit;
-
-        rs = (XenbusState) (current_state[0] - '0');
-        free(current_state);
-        if (rs == state) {
-            msg = NULL;
-            goto exit;
-        }
-
-        snprintf(value, 2, "%d", state);
-        msg = xenbus_write(xbt, path, value);
-
-exit:
-        if (xbt_flag) {
-            msg2 = xenbus_transaction_end(xbt, 0, &retry);
-            xbt = XBT_NIL;
-        }
-        if (msg == NULL && msg2 != NULL)
-            msg = msg2;
-        else
-            free(msg2);
-    } while (retry);
-
-    return msg;
-}
-
-char *xenbus_wait_for_state_change(const char* path, XenbusState *state, 
xenbus_event_queue *queue)
-{
-    if (!queue)
-        queue = &xenbus_events;
-    for(;;)
-    {
-        char *res, *msg;
-        XenbusState rs;
-
-        msg = xenbus_read(XBT_NIL, path, &res);
-        if(msg) return msg;
-
-        rs = (XenbusState) (res[0] - 48);
-        free(res);
-
-        if (rs == *state)
-            xenbus_wait_for_watch(queue);
-        else {
-            *state = rs;
-            break;
-        }
-    }
-    return NULL;
-}
-
-
-static void xenbus_read_data(char *buf, unsigned int len)
-{
-    unsigned int off = 0;
-    unsigned int prod, cons;
-    unsigned int size;
-
-    while (off != len)
-    {
-        wait_event(xb_waitq, xenstore_buf->rsp_prod != xenstore_buf->rsp_cons);
-
-        prod = xenstore_buf->rsp_prod;
-        cons = xenstore_buf->rsp_cons;
-        DEBUG("Rsp_cons %d, rsp_prod %d.\n", cons, prod);
-        size = min(len - off, prod - cons);
-
-        rmb();   /* Make sure data read from ring is ordered with rsp_prod. */
-        memcpy_from_ring(xenstore_buf->rsp, buf + off,
-                         MASK_XENSTORE_IDX(cons), size);
-        off += size;
-        mb();    /* memcpy() and rsp_cons update must not be reordered. */
-        xenstore_buf->rsp_cons += size;
-        mb();    /* rsp_cons must be visible before we look at rsp_prod. */
-        if (xenstore_buf->rsp_prod - cons >= XENSTORE_RING_SIZE)
-            notify_remote_via_evtchn(xenbus_evtchn);
-    }
-}
-
-static void xenbus_thread_func(void *ign)
-{
-    struct xsd_sockmsg msg;
-    char *data;
-
-    for (;;) {
-        xenbus_read_data((char *)&msg, sizeof(msg));
-        DEBUG("Msg len %d, %d avail, id %d.\n", msg.len + sizeof(msg),
-              xenstore_buf->rsp_prod - xenstore_buf->rsp_cons, msg.req_id);
-
-        if (msg.len > XENSTORE_PAYLOAD_MAX) {
-            printk("Xenstore violates protocol, message longer than 
allowed.\n");
-            return;
-        }
-
-        if (msg.type == XS_WATCH_EVENT) {
-            struct xenbus_event *event = malloc(sizeof(*event) + msg.len);
-            xenbus_event_queue *events = NULL;
-            struct watch *watch;
-            char *c;
-            int zeroes = 0;
-
-            data = (char*)event + sizeof(*event);
-            xenbus_read_data(data, msg.len);
-
-            for (c = data; c < data + msg.len; c++)
-                if (!*c)
-                    zeroes++;
-            if (zeroes != 2) {
-                printk("Xenstore: illegal watch event data\n");
-                free(event);
-                continue;
-            }
-
-            event->path = data;
-            event->token = event->path + strlen(event->path) + 1;
-
-            for (watch = watches; watch; watch = watch->next)
-                if (!strcmp(watch->token, event->token)) {
-                    events = watch->events;
-                    break;
-                }
-
-            if (events) {
-                event->next = *events;
-                *events = event;
-                wake_up(&xenbus_watch_queue);
-            } else {
-                printk("Xenstore: unexpected watch token %s\n", event->token);
-                free(event);
-            }
-
-            continue;
-        }
-
-        data = malloc(sizeof(msg) + msg.len);
-        memcpy(data, &msg, sizeof(msg));
-        xenbus_read_data(data + sizeof(msg), msg.len);
-
-        if (msg.req_id >= NR_REQS || !req_info[msg.req_id].in_use) {
-            printk("Xenstore: illegal request id %d\n", msg.req_id);
-            free(data);
-            continue;
-        }
-
-        DEBUG("Message is good.\n");
-
-        req_info[msg.req_id].reply = data;
-
-        wake_up(&req_info[msg.req_id].waitq);
-    }
-}
-
-static void xenbus_evtchn_handler(evtchn_port_t port, struct pt_regs *regs,
-                                 void *ign)
-{
-    wake_up(&xb_waitq);
-}
-
-static int nr_live_reqs;
-static DEFINE_SPINLOCK(req_lock);
-static DECLARE_WAIT_QUEUE_HEAD(req_wq);
-
-/* Release a xenbus identifier */
-static void release_xenbus_id(int id)
-{
-    BUG_ON(!req_info[id].in_use);
-    spin_lock(&req_lock);
-    req_info[id].in_use = 0;
-    nr_live_reqs--;
-    req_info[id].in_use = 0;
-    if (nr_live_reqs == 0 || nr_live_reqs == NR_REQS - 1)
-        wake_up(&req_wq);
-    spin_unlock(&req_lock);
-}
-
-/* Allocate an identifier for a xenbus request.  Blocks if none are
-   available. */
-static int allocate_xenbus_id(void)
-{
-    static int probe;
-    int o_probe;
-
-    while (1) 
-    {
-        spin_lock(&req_lock);
-        if (nr_live_reqs < NR_REQS)
-            break;
-        spin_unlock(&req_lock);
-        wait_event(req_wq, (nr_live_reqs < NR_REQS));
-    }
-
-    o_probe = probe;
-    for (;;) 
-    {
-        if (!req_info[o_probe].in_use)
-            break;
-        o_probe = (o_probe + 1) % NR_REQS;
-        BUG_ON(o_probe == probe);
-    }
-    nr_live_reqs++;
-    req_info[o_probe].in_use = 1;
-    probe = (o_probe + 1) % NR_REQS;
-    spin_unlock(&req_lock);
-    init_waitqueue_head(&req_info[o_probe].waitq);
-
-    return o_probe;
-}
-
-/* Initialise xenbus. */
-void init_xenbus(void)
-{
-    int err;
-    DEBUG("init_xenbus called.\n");
-    create_thread("xenstore", xenbus_thread_func, NULL);
-    DEBUG("buf at %p.\n", xenstore_buf);
-    err = bind_evtchn(xenbus_evtchn, xenbus_evtchn_handler, NULL);
-    unmask_evtchn(xenbus_evtchn);
-    printk("xenbus initialised on irq %d\n", err);
-}
-
-void fini_xenbus(void)
-{
-}
-
-void suspend_xenbus(void)
-{
-    /* Check for live requests and wait until they finish */
-    while (1)
-    {
-        spin_lock(&req_lock);
-        if (nr_live_reqs == 0)
-            break;
-        spin_unlock(&req_lock);
-        wait_event(req_wq, (nr_live_reqs == 0));
-    }
-
-    mask_evtchn(xenbus_evtchn);
-    xenstore_buf = NULL;
-    spin_unlock(&req_lock);
-}
-
-void resume_xenbus(int canceled)
-{
-    char *msg;
-    struct watch *watch;
-    struct write_req req[2];
-    struct xsd_sockmsg *rep;
-
-#ifdef CONFIG_PARAVIRT
-    get_xenbus(&start_info);
-#else
-    get_xenbus(0);
-#endif
-    unmask_evtchn(xenbus_evtchn);
-
-    if (!canceled) {
-        for (watch = watches; watch; watch = watch->next) {
-            req[0].data = watch->path;
-            req[0].len = strlen(watch->path) + 1;
-            req[1].data = watch->token;
-            req[1].len = strlen(watch->token) + 1;
-
-            rep = xenbus_msg_reply(XS_WATCH, XBT_NIL, req, ARRAY_SIZE(req));
-            msg = errmsg(rep);
-            if (msg) {
-                xprintk("error on XS_WATCH: %s\n", msg);
-                free(msg);
-            } else
-                free(rep);
-        }
-    }
-
-    notify_remote_via_evtchn(xenbus_evtchn);
-}
-
-/* Send data to xenbus.  This can block.  All of the requests are seen
-   by xenbus as if sent atomically.  The header is added
-   automatically, using type %type, req_id %req_id, and trans_id
-   %trans_id. */
-static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
-                    const struct write_req *req, int nr_reqs)
-{
-    XENSTORE_RING_IDX prod;
-    int r;
-    int len = 0;
-    const struct write_req *cur_req;
-    int req_off;
-    int total_off;
-    int this_chunk;
-    struct xsd_sockmsg m = {.type = type, .req_id = req_id,
-        .tx_id = trans_id };
-    struct write_req header_req = { &m, sizeof(m) };
-
-    for (r = 0; r < nr_reqs; r++)
-        len += req[r].len;
-    m.len = len;
-    len += sizeof(m);
-
-    cur_req = &header_req;
-
-    BUG_ON(len > XENSTORE_PAYLOAD_MAX);
-
-    /* Make sure we are the only thread trying to write. */
-    down(&xb_write_sem);
-
-    /* Send the message in chunks using free ring space when available. */
-    total_off = 0;
-    req_off = 0;
-    while (total_off < len)
-    {
-        prod = xenstore_buf->req_prod;
-        if (prod - xenstore_buf->req_cons >= XENSTORE_RING_SIZE)
-        {
-            /* Send evtchn to notify remote */
-            notify_remote_via_evtchn(xenbus_evtchn);
-
-            /* Wait for there to be space on the ring */
-            DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n", prod,
-                  len - total_off, xenstore_buf->req_cons, XENSTORE_RING_SIZE);
-            wait_event(xb_waitq,
-                       prod - xenstore_buf->req_cons < XENSTORE_RING_SIZE);
-            DEBUG("Back from wait.\n");
-        }
-
-        this_chunk = min(cur_req->len - req_off,
-                         XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
-        this_chunk = min(this_chunk,
-                         xenstore_buf->req_cons + XENSTORE_RING_SIZE - prod);
-        memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
-               (char *)cur_req->data + req_off, this_chunk);
-        prod += this_chunk;
-        req_off += this_chunk;
-        total_off += this_chunk;
-        if (req_off == cur_req->len)
-        {
-            req_off = 0;
-            if (cur_req == &header_req)
-                cur_req = req;
-            else
-                cur_req++;
-        }
-
-        /* Remote must see entire message before updating indexes */
-        wmb();
-        xenstore_buf->req_prod = prod;
-    }
-
-    /* Send evtchn to notify remote */
-    notify_remote_via_evtchn(xenbus_evtchn);
-
-    DEBUG("Complete main loop of xb_write.\n");
-    BUG_ON(req_off != 0);
-    BUG_ON(total_off != len);
-
-    up(&xb_write_sem);
-}
-
-/* Send a mesasge to xenbus, in the same fashion as xb_write, and
-   block waiting for a reply.  The reply is malloced and should be
-   freed by the caller. */
-struct xsd_sockmsg *
-xenbus_msg_reply(int type,
-                xenbus_transaction_t trans,
-                struct write_req *io,
-                int nr_reqs)
-{
-    int id;
-    DEFINE_WAIT(w);
-    struct xsd_sockmsg *rep;
-
-    id = allocate_xenbus_id();
-    add_waiter(w, req_info[id].waitq);
-
-    xb_write(type, id, trans, io, nr_reqs);
-
-    schedule();
-    remove_waiter(w, req_info[id].waitq);
-    wake(current);
-
-    rep = req_info[id].reply;
-    BUG_ON(rep->req_id != id);
-    release_xenbus_id(id);
-    return rep;
-}
-
-static char *errmsg(struct xsd_sockmsg *rep)
-{
-    char *res;
-    if (!rep) {
-       char msg[] = "No reply";
-       size_t len = strlen(msg) + 1;
-       return memcpy(malloc(len), msg, len);
-    }
-    if (rep->type != XS_ERROR)
-       return NULL;
-    res = malloc(rep->len + 1);
-    memcpy(res, rep + 1, rep->len);
-    res[rep->len] = 0;
-    free(rep);
-    return res;
-}
-
-/* List the contents of a directory.  Returns a malloc()ed array of
-   pointers to malloc()ed strings.  The array is NULL terminated.  May
-   block. */
-char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
-{
-    struct xsd_sockmsg *reply, *repmsg;
-    struct write_req req[] = { { pre, strlen(pre)+1 } };
-    int nr_elems, x, i;
-    char **res, *msg;
-
-    repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
-    msg = errmsg(repmsg);
-    if (msg) {
-       *contents = NULL;
-       return msg;
-    }
-    reply = repmsg + 1;
-    for (x = nr_elems = 0; x < repmsg->len; x++)
-        nr_elems += (((char *)reply)[x] == 0);
-    res = malloc(sizeof(res[0]) * (nr_elems + 1));
-    for (x = i = 0; i < nr_elems; i++) {
-        int l = strlen((char *)reply + x);
-        res[i] = malloc(l + 1);
-        memcpy(res[i], (char *)reply + x, l + 1);
-        x += l + 1;
-    }
-    res[i] = NULL;
-    free(repmsg);
-    *contents = res;
-    return NULL;
-}
-
-char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
-{
-    struct write_req req[] = { {path, strlen(path) + 1} };
-    struct xsd_sockmsg *rep;
-    char *res, *msg;
-    rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
-    msg = errmsg(rep);
-    if (msg) {
-       *value = NULL;
-       return msg;
-    }
-    res = malloc(rep->len + 1);
-    memcpy(res, rep + 1, rep->len);
-    res[rep->len] = 0;
-    free(rep);
-    *value = res;
-    return NULL;
-}
-
-char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char 
*value)
-{
-    struct write_req req[] = { 
-       {path, strlen(path) + 1},
-       {value, strlen(value)},
-    };
-    struct xsd_sockmsg *rep;
-    char *msg;
-    rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
-    msg = errmsg(rep);
-    if (msg) return msg;
-    free(rep);
-    return NULL;
-}
-
-char* xenbus_watch_path_token( xenbus_transaction_t xbt, const char *path, 
const char *token, xenbus_event_queue *events)
-{
-    struct xsd_sockmsg *rep;
-
-    struct write_req req[] = { 
-        {path, strlen(path) + 1},
-       {token, strlen(token) + 1},
-    };
-
-    struct watch *watch = malloc(sizeof(*watch));
-
-    char *msg;
-
-    if (!events)
-        events = &xenbus_events;
-
-    watch->token = strdup(token);
-    watch->path = strdup(path);
-    watch->events = events;
-    watch->next = watches;
-    watches = watch;
-
-    rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
-
-    msg = errmsg(rep);
-    if (msg) return msg;
-    free(rep);
-
-    return NULL;
-}
-
-char* xenbus_unwatch_path_token( xenbus_transaction_t xbt, const char *path, 
const char *token)
-{
-    struct xsd_sockmsg *rep;
-
-    struct write_req req[] = { 
-        {path, strlen(path) + 1},
-       {token, strlen(token) + 1},
-    };
-
-    struct watch *watch, **prev;
-
-    char *msg;
-
-    rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
-
-    msg = errmsg(rep);
-    if (msg) return msg;
-    free(rep);
-
-    for (prev = &watches, watch = *prev; watch; prev = &watch->next, watch = 
*prev)
-        if (!strcmp(watch->token, token)) {
-            free(watch->token);
-            free(watch->path);
-            *prev = watch->next;
-            free(watch);
-            break;
-        }
-
-    return NULL;
-}
-
-char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
-{
-    struct write_req req[] = { {path, strlen(path) + 1} };
-    struct xsd_sockmsg *rep;
-    char *msg;
-    rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
-    msg = errmsg(rep);
-    if (msg)
-       return msg;
-    free(rep);
-    return NULL;
-}
-
-char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char 
**value)
-{
-    struct write_req req[] = { {path, strlen(path) + 1} };
-    struct xsd_sockmsg *rep;
-    char *res, *msg;
-    rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
-    msg = errmsg(rep);
-    if (msg) {
-       *value = NULL;
-       return msg;
-    }
-    res = malloc(rep->len + 1);
-    memcpy(res, rep + 1, rep->len);
-    res[rep->len] = 0;
-    free(rep);
-    *value = res;
-    return NULL;
-}
-
-#define PERM_MAX_SIZE 32
-char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t 
dom, char perm)
-{
-    char value[PERM_MAX_SIZE];
-    struct write_req req[] = { 
-       {path, strlen(path) + 1},
-       {value, 0},
-    };
-    struct xsd_sockmsg *rep;
-    char *msg;
-    snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
-    req[1].len = strlen(value) + 1;
-    rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
-    msg = errmsg(rep);
-    if (msg)
-       return msg;
-    free(rep);
-    return NULL;
-}
-
-char *xenbus_transaction_start(xenbus_transaction_t *xbt)
-{
-    /* xenstored becomes angry if you send a length 0 message, so just
-       shove a nul terminator on the end */
-    struct write_req req = { "", 1};
-    struct xsd_sockmsg *rep;
-    char *err;
-
-    rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
-    err = errmsg(rep);
-    if (err)
-       return err;
-    sscanf((char *)(rep + 1), "%lu", xbt);
-    free(rep);
-    return NULL;
-}
-
-char *
-xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
-{
-    struct xsd_sockmsg *rep;
-    struct write_req req;
-    char *err;
-
-    *retry = 0;
-
-    req.data = abort ? "F" : "T";
-    req.len = 2;
-    rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
-    err = errmsg(rep);
-    if (err) {
-       if (!strcmp(err, "EAGAIN")) {
-           *retry = 1;
-           free(err);
-           return NULL;
-       } else {
-           return err;
-       }
-    }
-    free(rep);
-    return NULL;
-}
-
-int xenbus_read_integer(const char *path)
-{
-    char *res, *buf;
-    int t;
-
-    res = xenbus_read(XBT_NIL, path, &buf);
-    if (res) {
-       printk("Failed to read %s.\n", path);
-       free(res);
-       return -1;
-    }
-    sscanf(buf, "%d", &t);
-    free(buf);
-    return t;
-}
-
-int xenbus_read_uuid(const char* path, unsigned char uuid[16]) {
-   char * res, *buf;
-   res = xenbus_read(XBT_NIL, path, &buf);
-   if(res) {
-      printk("Failed to read %s.\n", path);
-      free(res);
-      return 0;
-   }
-   if(strlen(buf) != ((2*16)+4) /* 16 hex bytes and 4 hyphens */
-         || sscanf(buf,
-            "%2hhx%2hhx%2hhx%2hhx-"
-            "%2hhx%2hhx-"
-            "%2hhx%2hhx-"
-            "%2hhx%2hhx-"
-            "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
-            uuid, uuid + 1, uuid + 2, uuid + 3,
-            uuid + 4, uuid + 5, uuid + 6, uuid + 7,
-            uuid + 8, uuid + 9, uuid + 10, uuid + 11,
-            uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
-      printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
-      free(buf);
-      return 0;
-   }
-   free(buf);
-   return 1;
-}
-
-char* xenbus_printf(xenbus_transaction_t xbt,
-                                  const char* node, const char* path,
-                                  const char* fmt, ...)
-{
-#define BUFFER_SIZE 256
-    char fullpath[BUFFER_SIZE];
-    char val[BUFFER_SIZE];
-    va_list args;
-
-    BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
-    sprintf(fullpath,"%s/%s", node, path);
-    va_start(args, fmt);
-    vsprintf(val, fmt, args);
-    va_end(args);
-    return xenbus_write(xbt,fullpath,val);
-}
-
-domid_t xenbus_get_self_id(void)
-{
-    char *dom_id;
-    domid_t ret;
-
-    BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
-    sscanf(dom_id, "%"SCNd16, &ret);
-
-    return ret;
-}
-
-#ifdef CONFIG_TEST
-/* Send a debug message to xenbus.  Can block. */
-static void xenbus_debug_msg(const char *msg)
-{
-    int len = strlen(msg);
-    struct write_req req[] = {
-        { "print", sizeof("print") },
-        { msg, len },
-        { "", 1 }};
-    struct xsd_sockmsg *reply;
-
-    reply = xenbus_msg_reply(XS_DEBUG, 0, req, ARRAY_SIZE(req));
-    printk("Got a reply, type %d, id %d, len %d.\n",
-            reply->type, reply->req_id, reply->len);
-}
-
-static void do_ls_test(const char *pre)
-{
-    char **dirs, *msg;
-    int x;
-
-    printk("ls %s...\n", pre);
-    msg = xenbus_ls(XBT_NIL, pre, &dirs);
-    if (msg) {
-       printk("Error in xenbus ls: %s\n", msg);
-       free(msg);
-       return;
-    }
-    for (x = 0; dirs[x]; x++) 
-    {
-        printk("ls %s[%d] -> %s\n", pre, x, dirs[x]);
-        free(dirs[x]);
-    }
-    free(dirs);
-}
-
-static void do_read_test(const char *path)
-{
-    char *res, *msg;
-    printk("Read %s...\n", path);
-    msg = xenbus_read(XBT_NIL, path, &res);
-    if (msg) {
-       printk("Error in xenbus read: %s\n", msg);
-       free(msg);
-       return;
-    }
-    printk("Read %s -> %s.\n", path, res);
-    free(res);
-}
-
-static void do_write_test(const char *path, const char *val)
-{
-    char *msg;
-    printk("Write %s to %s...\n", val, path);
-    msg = xenbus_write(XBT_NIL, path, val);
-    if (msg) {
-       printk("Result %s\n", msg);
-       free(msg);
-    } else {
-       printk("Success.\n");
-    }
-}
-
-static void do_rm_test(const char *path)
-{
-    char *msg;
-    printk("rm %s...\n", path);
-    msg = xenbus_rm(XBT_NIL, path);
-    if (msg) {
-       printk("Result %s\n", msg);
-       free(msg);
-    } else {
-       printk("Success.\n");
-    }
-}
-
-/* Simple testing thing */
-void test_xenbus(void)
-{
-    printk("Doing xenbus test.\n");
-    xenbus_debug_msg("Testing xenbus...\n");
-
-    printk("Doing ls test.\n");
-    do_ls_test("device");
-    do_ls_test("device/vif");
-    do_ls_test("device/vif/0");
-
-    printk("Doing read test.\n");
-    do_read_test("device/vif/0/mac");
-    do_read_test("device/vif/0/backend");
-
-    printk("Doing write test.\n");
-    do_write_test("device/vif/0/flibble", "flobble");
-    do_read_test("device/vif/0/flibble");
-    do_write_test("device/vif/0/flibble", "widget");
-    do_read_test("device/vif/0/flibble");
-
-    printk("Doing rm test.\n");
-    do_rm_test("device/vif/0/flibble");
-    do_read_test("device/vif/0/flibble");
-    printk("(Should have said ENOENT)\n");
-}
-#endif /* CONFIG_TEST */
-
-/*
- * Local variables:
- * mode: C
- * c-basic-offset: 4
- * End:
- */
--
generated by git-patchbot for /home/xen/git/mini-os.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.