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

[Xen-changelog] Add xenbus driver.



ChangeSet 1.1766, 2005/06/28 16:44:49+01:00, cl349@xxxxxxxxxxxxxxxxxxxx

        Add xenbus driver.
        XendDomainInfo.py:
          Connect/Disconnect domains to/from store.
        Signed-off-by: Rusty Russel <rusty@xxxxxxxxxxxxxxx> (authored)
        Signed-off-by: Mike Wray <mike.wray@xxxxxx>
        Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>



 linux-2.6.11-xen-sparse/drivers/xen/Makefile              |    1 
 linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile       |   10 
 linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c |  208 +++
 linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h |   14 
 linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c |  870 ++++++++++++++
 linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c    |  488 +++++++
 linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h          |  143 ++
 tools/python/xen/xend/XendDomainInfo.py                   |   18 
 8 files changed, 1743 insertions(+), 9 deletions(-)


diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/Makefile 
b/linux-2.6.11-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6.11-xen-sparse/drivers/xen/Makefile      2005-06-28 14:02:15 
-04:00
+++ b/linux-2.6.11-xen-sparse/drivers/xen/Makefile      2005-06-28 14:02:15 
-04:00
@@ -4,6 +4,7 @@
 obj-y  += evtchn/
 obj-y  += balloon/
 obj-y  += privcmd/
+obj-y  += xenbus/
 
 obj-$(CONFIG_XEN_BLKDEV_BACKEND)       += blkback/
 obj-$(CONFIG_XEN_NETDEV_BACKEND)       += netback/
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile 
b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile       2005-06-28 
14:02:15 -04:00
@@ -0,0 +1,10 @@
+obj-y  += xenbus.o
+
+xenbus-objs =
+xenbus-objs += xenbus_comms.o
+xenbus-objs += xenbus_xs.o
+xenbus-objs += xenbus_probe.o 
+
+XEN_TOOLS_DIR := "../tools"
+vpath %.h $(XEN_TOOLS_DIR)
+EXTRA_CFLAGS += -I $(XEN_TOOLS_DIR)
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c 
b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c 2005-06-28 
14:02:15 -04:00
@@ -0,0 +1,208 @@
+/******************************************************************************
+ * xenbus_comms.c
+ *
+ * Low level code to talks to Xen Store: ringbuffer and event channel.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+//#define DEBUG
+
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/evtchn.h>
+#include <linux/wait.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include "xenbus_comms.h"
+
+#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
+struct ringbuf_head
+{
+       u32 write; /* Next place to write to */
+       u32 read; /* Next place to read from */
+       u8 flags;
+       char buf[0];
+} __attribute__((packed));
+
+DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+
+static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
+{
+       wake_up(&xb_waitq);
+       return IRQ_HANDLED;
+}
+
+static int check_buffer(const struct ringbuf_head *h)
+{
+       return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
+}
+
+/* We can't fill last byte: would look like empty buffer. */
+static void *get_output_chunk(const struct ringbuf_head *h,
+                             void *buf, u32 *len)
+{
+       u32 read_mark;
+
+       if (h->read == 0)
+               read_mark = RINGBUF_DATASIZE - 1;
+       else
+               read_mark = h->read - 1;
+
+       /* Here to the end of buffer, unless they haven't read some out. */
+       *len = RINGBUF_DATASIZE - h->write;
+       if (read_mark >= h->write)
+               *len = read_mark - h->write;
+       return buf + h->write;
+}
+
+static const void *get_input_chunk(const struct ringbuf_head *h,
+                                  const void *buf, u32 *len)
+{
+       /* Here to the end of buffer, unless they haven't written some. */
+       *len = RINGBUF_DATASIZE - h->read;
+       if (h->write >= h->read)
+               *len = h->write - h->read;
+       return buf + h->read;
+}
+
+static void update_output_chunk(struct ringbuf_head *h, u32 len)
+{
+       h->write += len;
+       if (h->write == RINGBUF_DATASIZE)
+               h->write = 0;
+}
+
+static void update_input_chunk(struct ringbuf_head *h, u32 len)
+{
+       h->read += len;
+       if (h->read == RINGBUF_DATASIZE)
+               h->read = 0;
+}
+
+static int output_avail(struct ringbuf_head *out)
+{
+       unsigned int avail;
+
+       get_output_chunk(out, out->buf, &avail);
+       return avail != 0;
+}
+
+int xb_write(struct ringbuf_head *out, const void *data, unsigned len)
+{
+       struct ringbuf_head h;
+
+       do {
+               void *dst;
+               unsigned int avail;
+
+               wait_event(xb_waitq, output_avail(out));
+
+               /* Read, then check: not that we don't trust store.
+                * Hell, some of my best friends are daemons.  But,
+                * in this post-911 world... */
+               h = *out;
+               mb();
+               if (!check_buffer(&h)) {
+                       set_current_state(TASK_RUNNING);
+                       return -EIO; /* ETERRORIST! */
+               }
+
+               dst = get_output_chunk(&h, out->buf, &avail);
+               if (avail > len)
+                       avail = len;
+               memcpy(dst, data, avail);
+               data += avail;
+               len -= avail;
+               update_output_chunk(out, avail);
+               notify_via_evtchn(xen_start_info.store_evtchn);
+       } while (len != 0);
+
+       return 0;
+}
+
+int xs_input_avail(struct ringbuf_head *in)
+{
+       unsigned int avail;
+
+       get_input_chunk(in, in->buf, &avail);
+       return avail != 0;
+}
+
+int xb_read(struct ringbuf_head *in, void *data, unsigned len)
+{
+       struct ringbuf_head h;
+       int was_full;
+
+       while (len != 0) {
+               unsigned int avail;
+               const char *src;
+
+               wait_event(xb_waitq, xs_input_avail(in));
+               h = *in;
+               mb();
+               if (!check_buffer(&h)) {
+                       set_current_state(TASK_RUNNING);
+                       return -EIO;
+               }
+
+               src = get_input_chunk(&h, in->buf, &avail);
+               if (avail > len)
+                       avail = len;
+               was_full = !output_avail(&h);
+
+               memcpy(data, src, avail);
+               data += avail;
+               len -= avail;
+               update_input_chunk(in, avail);
+               pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
+               /* If it was full, tell them we've taken some. */
+               if (was_full)
+                       notify_via_evtchn(xen_start_info.store_evtchn);
+       }
+
+       /* If we left something, wake watch thread to deal with it. */
+       if (xs_input_avail(in))
+               wake_up(&xb_waitq);
+
+       return 0;
+}
+
+/* Set up interrpt handler off store event channel. */
+int xb_init_comms(void **in, void **out)
+{
+       int err, irq;
+
+       irq = bind_evtchn_to_irq(xen_start_info.store_evtchn);
+
+       err = request_irq(irq, wake_waiting, SA_SHIRQ, "xenbus", &xb_waitq);
+       if (err) {
+               printk(KERN_ERR "XENBUS request irq failed %i\n", err);
+               unbind_evtchn_from_irq(xen_start_info.store_evtchn);
+               return err;
+       }
+
+       *out = (void *)xen_start_info.store_page;
+       *in = (void *)xen_start_info.store_page + PAGE_SIZE/2;
+       return 0;
+}
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h 
b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h 2005-06-28 
14:02:15 -04:00
@@ -0,0 +1,14 @@
+/* Private include for xenbus communications. */
+#ifndef _XENBUS_COMMS_H
+#define _XENBUS_COMMS_H
+int xs_init(void);
+int xb_init_comms(void **in, void **out);
+
+/* Low level routines. */
+struct ringbuf_head;
+int xb_write(struct ringbuf_head *out, const void *data, unsigned len);
+int xb_read(struct ringbuf_head *in, void *data, unsigned len);
+int xs_input_avail(struct ringbuf_head *in);
+extern wait_queue_head_t xb_waitq;
+
+#endif /* _XENBUS_COMMS_H */
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c 
b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c 2005-06-28 
14:02:15 -04:00
@@ -0,0 +1,870 @@
+/******************************************************************************
+ * Talks to Xen Store to figure out what devices we have.
+ * Currently experiment code, but when I grow up I'll be a bus driver!
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * Copyright (C) 2005 Mike Wray, Hewlett-Packard
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <asm-xen/hypervisor.h>
+#include <asm-xen/xenbus.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/fcntl.h>
+#include <stdarg.h>
+#include "xenbus_comms.h"
+
+/* Directory inside a domain containing devices. */
+#define XENBUS_DEVICE_DIR  "device"
+
+/* Directory inside a domain containing backends. */
+#define XENBUS_BACKEND_DIR  "backend"
+
+/* Name of field containing device id. */
+#define XENBUS_DEVICE_ID   "id"
+
+/* Name of field containing device type. */
+#define XENBUS_DEVICE_TYPE "type"
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define dprintf(_fmt, _args...) \
+printk(KERN_INFO __stringify(KBUILD_MODNAME) " [DBG] %s"    _fmt, 
__FUNCTION__, ##_args)
+#else
+#define dprintf(_fmt, _args...) do { } while(0)
+#endif
+
+static int xs_init_done = 0;
+
+/* Return the path to dir with /name appended.
+ * If name is null or empty returns a copy of dir.
+ */ 
+char *xenbus_path(const char *dir, const char *name)
+{
+       char *ret;
+        if(name && strlen(name)){
+                ret = kmalloc(strlen(dir) + 1 + strlen(name) + 1, GFP_KERNEL);
+                if (!ret)
+                        return NULL;
+                strcpy(ret, dir);
+               strcat(ret, "/");
+               strcat(ret, name);
+       } else {
+                ret = kmalloc(strlen(dir) + 1, GFP_KERNEL);
+                if (!ret)
+                        return NULL;
+                strcpy(ret, dir);
+        }
+       return ret;
+}
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+char *xenbus_read(const char *dir, const char *name, unsigned int *data_n)
+{
+        int err = 0;
+       char *data = NULL;
+       char *path = xenbus_path(dir, name);
+        int n = 0;
+
+       if (!path) {
+                err = -ENOMEM;
+                goto out;
+        }
+       data = xs_read(path, &n);
+       if (IS_ERR(data)){
+                err = PTR_ERR(data);
+                if(err == -EISDIR){
+                        err = -ENOENT;
+                }
+        } else if(n == 0){
+                err = -ENOENT;
+                kfree(data);
+        } else if(data[n - 1] != '\0') {
+                /* This shouldn't happen: everything is supposed to be a 
string. */
+               printk("XENBUS: Reading path %s: missing null terminator 
len=%i\n", path, n); 
+                err = -EINVAL;
+                kfree(data);
+                n = 0;
+        }
+        kfree(path);
+  out:
+        if(data_n)
+                *data_n = n;
+       return (err ? ERR_PTR(err) : data);
+}
+
+int xenbus_write(const char *dir, const char *name, const char *data, int 
data_n)
+{
+        int err = 0;
+       char *path = xenbus_path(dir, name);
+
+       if (!path)
+               return -ENOMEM;
+        err = xs_write(path, data, data_n, O_CREAT);
+       kfree(path);
+        return err;
+}
+
+int xenbus_read_string(const char *dir, const char *name, char **val)
+{
+        int err = 0;
+
+        *val = xenbus_read(dir, name, NULL);
+        if (IS_ERR(*val)) {
+                err = PTR_ERR(*val);
+                *val = NULL;
+        }
+        return err;
+}
+
+int xenbus_write_string(const char *dir, const char *name, const char *val)
+{
+        return xenbus_write(dir, name, val, strlen(val) + 1);
+}
+
+int xenbus_read_ulong(const char *dir, const char *name, unsigned long *val)
+{
+       int err = 0;
+       char *data = NULL, *end = NULL;
+       unsigned int data_n = 0;
+
+       data = xenbus_read(dir, name, &data_n);
+       if (IS_ERR(data)) {
+               err = PTR_ERR(data);
+                goto out;
+        }
+        if (data_n <= 1) {
+                err = -ENOENT;
+                goto free_data;
+        }
+        *val = simple_strtoul(data, &end, 10);
+        if (end != data + data_n - 1) {
+                printk("XENBUS: Path %s/%s, bad parse of '%s' as ulong\n",
+                       dir, name, data);
+                err = -EINVAL;
+       }
+  free_data:
+       kfree(data);
+  out:
+        if (err)
+                *val = 0;
+       return err;
+}
+
+int xenbus_write_ulong(const char *dir, const char *name, unsigned long val)
+{
+       char data[32] = {};
+
+        snprintf(data, sizeof(data), "%lu", val);
+       return xenbus_write(dir, name, data, strlen(data) + 1);
+}
+
+int xenbus_read_long(const char *dir, const char *name, long *val)
+{
+       int err = 0;
+       char *data = NULL, *end = NULL;
+       unsigned int data_n = 0;
+
+       data = xenbus_read(dir, name, &data_n);
+       if (IS_ERR(data)) {
+               err = PTR_ERR(data);
+                goto out;
+        }
+        if (data_n <= 1) {
+                err = -ENOENT;
+                goto free_data;
+        }
+        *val = simple_strtol(data, &end, 10);
+        if (end != data + data_n - 1) {
+                printk("XENBUS: Path %s/%s, bad parse of '%s' as long\n",
+                       dir, name, data);
+                err = -EINVAL;
+        }
+  free_data:
+       kfree(data);
+  out:
+        if (err)
+                *val = 0;
+       return err;
+}
+
+int xenbus_write_long(const char *dir, const char *name, long val)
+{
+       char data[32] = {};
+
+        snprintf(data, sizeof(data), "%li", val);
+       return xenbus_write(dir, name, data, strlen(data) + 1);
+}
+
+/* Number of characters in string form of a MAC address. */
+#define MAC_LENGTH    17
+
+/** Convert a mac address from a string of the form
+ * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
+ * Each X denotes a hex digit: 0..9, a..f, A..F.
+ * Also supports using '-' as the separator instead of ':'.
+ */
+static int mac_aton(const char *macstr, unsigned int n, unsigned char mac[6]){
+        int err = -EINVAL;
+        int i, j;
+        const char *p;
+        char sep = 0;
+        
+        if(!macstr || n != MAC_LENGTH){
+                goto exit;
+        }
+        for(i = 0, p = macstr; i < 6; i++){
+                unsigned char d = 0;
+                if(i){
+                        if(!sep){
+                                if(*p == ':' || *p == '-') sep = *p;
+                        }
+                        if(sep && *p == sep){
+                                p++;
+                        } else {
+                                goto exit;
+                        }
+                }
+                for(j = 0; j < 2; j++, p++){
+                        if(j) d <<= 4;
+                        if(isdigit(*p)){
+                                d += *p - '0';
+                        } else if(isxdigit(*p)){
+                                d += toupper(*p) - 'A' + 10;
+                        } else {
+                                goto exit;
+                        }
+                }
+                mac[i] = d;
+        }
+        err = 0;
+  exit:
+        return err;
+}
+
+int xenbus_read_mac(const char *dir, const char *name, unsigned char mac[6])
+{
+       int err = 0;
+       char *data = 0;
+       unsigned int data_n = 0;
+
+       data = xenbus_read(dir, name, &data_n);
+       if (IS_ERR(data)) {
+               err = PTR_ERR(data);
+                goto out;
+        }
+        if (data_n <= 1) {
+                err = -ENOENT;
+                goto free_data;
+        }
+        err = mac_aton(data, data_n - 1, mac);
+        if (err) {
+                printk("XENBUS: Path %s/%s, bad parse of '%s' as mac\n",
+                       dir, name, data);
+                err = -EINVAL;
+        }
+  free_data:
+        kfree(data);
+  out:
+        if(err)
+                memset(mac, 0, sizeof(mac));
+        return err;
+}
+
+int xenbus_write_mac(const char *dir, const char *name, const unsigned char 
mac[6])
+{
+        char buf[MAC_LENGTH + 1] = {};
+        int buf_n = sizeof(buf);
+        
+        snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
+                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+        buf[buf_n - 1] = '\0';
+        return xenbus_write(dir, name, buf, buf_n);
+}
+
+/* Read event channel information from xenstore.
+ *
+ * Event channel xenstore fields:
+ * dom1                - backend domain id (int)
+ * port1       - backend port (int)
+ * dom2                - frontend domain id (int)
+ * port2       - frontend port (int)
+ */
+int xenbus_read_evtchn(const char *dir, const char *name, struct xenbus_evtchn 
*evtchn)
+{
+        int err = 0;
+        char *evtchn_path = xenbus_path(dir, name);
+
+        if (!evtchn_path) {
+                err = -ENOMEM;
+                goto out;
+        }
+        err = xenbus_read_ulong(evtchn_path, "dom1",  &evtchn->dom1);
+        if(err)
+                goto free_evtchn_path;
+        err = xenbus_read_ulong(evtchn_path, "port1", &evtchn->port1);
+        if(err)
+                goto free_evtchn_path;
+        err = xenbus_read_ulong(evtchn_path, "dom2",  &evtchn->dom2);
+        if(err)
+                goto free_evtchn_path;
+        err = xenbus_read_ulong(evtchn_path, "port2", &evtchn->port2);
+
+  free_evtchn_path:
+        kfree(evtchn_path);
+  out:
+        if (err)
+                *evtchn = (struct xenbus_evtchn){};
+        return err;
+}
+
+/* Write a message to 'dir'.
+ * The data is 'val' followed by parameter names and values,
+ * terminated by NULL.
+ */
+int xenbus_message(const char *dir, const char *val, ...)
+{
+        static const char *mid_name = "@mid";
+        va_list args;
+        int err = 0;
+        char *mid_path = NULL; 
+        char *msg_path = NULL;
+        char mid_str[32] = {};
+        long mid = 0;
+        int i;
+
+        va_start(args, val);
+        mid_path = xenbus_path(dir, mid_name);
+        if (!mid_path) {
+                err = -ENOMEM;
+                goto out;
+        }
+        err = xenbus_read_long(dir, mid_name, &mid);
+        if(err != -ENOENT)
+                goto out;
+        mid++;
+        err = xenbus_write_long(dir, mid_name, mid);
+        if(err)
+                goto out;
+        sprintf(mid_str, "%li", mid);
+        msg_path = xenbus_path(dir, mid_str);
+        if (!mid_path) {
+                err = -ENOMEM;
+                goto out;
+        }
+
+        for(i = 0; i < 16; i++){
+                char *k, *v;
+                k = va_arg(args, char *);
+                if(!k)
+                        break;
+                v = va_arg(args, char *);
+                if(!v)
+                        break;
+                err = xenbus_write_string(msg_path, k, v);
+                if(err)
+                        goto out;
+        }
+        err = xenbus_write_string(msg_path, NULL, val);
+
+  out:
+        kfree(msg_path);
+        kfree(mid_path);
+        va_end(args);
+        return err;
+}
+
+/* If something in array of ids matches this device, return it. */
+static const struct xenbus_device_id *
+match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
+{
+       for( ; !streq(arr->devicetype, ""); arr++) {
+               if (!streq(arr->devicetype, dev->devicetype))
+                       continue;
+
+               if (streq(arr->subtype, "")
+                   || streq(arr->subtype, dev->subtype)) {
+                       return arr;
+               }
+       }
+       return NULL;
+}
+
+static int xenbus_match(struct device *_dev, struct device_driver *_drv)
+{
+       struct xenbus_driver *drv = to_xenbus_driver(_drv);
+
+       if (!drv->ids)
+               return 0;
+
+       return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
+}
+
+/* Bus type for frontend drivers. */
+static struct bus_type xenbus_type = {
+       .name  = "xenbus",
+       .match = xenbus_match,
+};
+
+
+/* Bus type for backend drivers. */
+static struct bus_type xenback_type = {
+        .name  = "xenback",
+        .match = xenbus_match,
+};
+
+struct xenbus_for_dev {
+        int (*fn)(struct xenbus_device *, void *);
+        void *data;
+};
+
+static int for_dev(struct device *_dev, void *_data)
+{
+        struct xenbus_device *dev = to_xenbus_device(_dev);
+        struct xenbus_for_dev *data = _data;
+        dev = to_xenbus_device(_dev);
+        return data->fn(dev, data->data);
+}
+
+int xenbus_for_each_dev(struct xenbus_device * start, void * data,
+                        int (*fn)(struct xenbus_device *, void *))
+{
+        struct xenbus_for_dev for_data = {
+                .fn = fn,
+                .data = data,
+        };
+        if(!fn)
+                return -EINVAL;
+        printk("%s> data=%p fn=%p for_data=%p\n", __FUNCTION__,
+               data, fn, &for_data);
+        return bus_for_each_dev(&xenbus_type, 
+                                (start ? &start->dev : NULL),
+                                &for_data, for_dev);
+}
+
+struct xenbus_for_drv {
+        int (*fn)(struct xenbus_driver *, void *);
+        void *data;
+};
+
+static int for_drv(struct device_driver *_drv, void *_data)
+{
+        struct xenbus_driver *drv = to_xenbus_driver(_drv);
+        struct xenbus_for_drv *data = _data;
+        return data->fn(drv, data->data);
+}
+
+int xenbus_for_each_drv(struct xenbus_driver * start, void * data,
+                        int (*fn)(struct xenbus_driver *, void *))
+{
+        struct xenbus_for_drv for_data = {
+                .fn = fn,
+                .data = data,
+        };
+        if(!fn)
+                return -EINVAL;
+        return bus_for_each_drv(&xenbus_type,
+                                (start ? &start->driver: NULL),
+                                &for_data, for_drv);
+}
+
+static int xenbus_dev_probe(struct device *_dev)
+{
+       struct xenbus_device *dev = to_xenbus_device(_dev);
+       struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
+       const struct xenbus_device_id *id;
+
+       if (!drv->probe)
+               return -ENODEV;
+
+       id = match_device(drv->ids, dev);
+       if (!id)
+               return -ENODEV;
+       return drv->probe(dev, id);
+}
+
+static int xenbus_dev_remove(struct device *_dev)
+{
+       struct xenbus_device *dev = to_xenbus_device(_dev);
+       struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
+
+        if(!drv->remove)
+                return 0;
+        return drv->remove(dev);
+}
+
+int xenbus_register_driver(struct xenbus_driver *drv)
+{
+        int err = 0;
+
+        printk("%s> frontend driver %p %s\n", __FUNCTION__,
+               drv, drv->name);
+       drv->driver.name = drv->name;
+       drv->driver.bus = &xenbus_type;
+       drv->driver.owner = drv->owner;
+       drv->driver.probe = xenbus_dev_probe;
+       drv->driver.remove = xenbus_dev_remove;
+
+       err = driver_register(&drv->driver);
+        if(err == 0 && xs_init_done && drv->connect){
+                printk("%s> connecting driver %p %s\n", __FUNCTION__,
+                       drv, drv->name);
+                drv->connect(drv);
+        }
+        return err;
+}
+
+void xenbus_unregister_driver(struct xenbus_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+
+static int xenbus_probe_device(const char *dir, const char *name)
+{
+       int err;
+       struct xenbus_device *xendev;
+       unsigned int xendev_n;
+       long id;
+       char *nodename, *devicetype;
+       unsigned int devicetype_n;
+
+       dprintf("> dir=%s name=%s\n", dir, name);
+       nodename = xenbus_path(dir, name);
+       if (!nodename)
+               return -ENOMEM;
+
+       devicetype = xenbus_read(nodename, XENBUS_DEVICE_TYPE, &devicetype_n);
+       if (IS_ERR(devicetype)) {
+               err = PTR_ERR(devicetype);
+               goto free_nodename;
+       }
+
+       err = xenbus_read_long(nodename, XENBUS_DEVICE_ID, &id);
+       if (err == -ENOENT) {
+               id = 0;
+        } else if (err != 0) {
+               goto free_devicetype;
+        }
+
+       dprintf("> devicetype='%s' name='%s' id=%ld\n", devicetype, name, id);
+        /* FIXME: This could be a rescan. Don't re-register existing devices. 
*/
+
+       /* Add space for the strings. */
+       xendev_n = sizeof(*xendev) + strlen(nodename) + strlen(devicetype) + 2;
+       xendev = kmalloc(xendev_n, GFP_KERNEL);
+       if (!xendev) {
+               err = -ENOMEM;
+               goto free_devicetype;
+       }
+       memset(xendev, 0, xendev_n);
+
+        snprintf(xendev->dev.bus_id, BUS_ID_SIZE, "%s-%s", devicetype, name);
+       xendev->dev.bus = &xenbus_type;
+
+       xendev->id = id;
+
+       /* Copy the strings into the extra space. */
+       xendev->nodename = (char *)(xendev + 1);
+       strcpy(xendev->nodename, nodename);
+       xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1;
+       strcpy(xendev->devicetype, devicetype);
+
+       /* Register with generic device framework. */
+        printk("XENBUS: Registering device %s\n", xendev->dev.bus_id);
+       err = device_register(&xendev->dev);
+        if (err) {
+                printk("XENBUS: Registering device %s: error %i\n",
+                       xendev->dev.bus_id, err);
+        }
+       if (err)
+               kfree(xendev);
+
+free_devicetype:
+       kfree(devicetype);
+free_nodename:
+       kfree(nodename);
+       dprintf("< err=%i\n", err);
+       return err;
+}
+
+static int xenbus_probe_device_type(const char *dirpath, const char *typename)
+{
+       int err = 0;
+       char **dir;
+       char *path;
+       unsigned int dir_n = 0;
+       int i;
+
+       dprintf("> dirpath=%s typename=%s\n", dirpath, typename);
+       path = xenbus_path(dirpath, typename);
+       if (!path)
+               return -ENOMEM;
+
+       dir = xs_directory(path, &dir_n);
+       if (IS_ERR(dir)) {
+               err = PTR_ERR(dir);
+               goto out;
+       }
+
+       for (i = 0; i < dir_n; i++) {
+               err = xenbus_probe_device(path, dir[i]);
+               if (err)
+                       break;
+       }
+       kfree(dir);
+out:
+       kfree(path);
+       dprintf("< err=%i\n", err);
+       return err;
+}
+
+static int xenbus_probe_devices(const char *path)
+{
+       int err = 0;
+       char **dir;
+       unsigned int i, dir_n;
+
+       dprintf("> path=%s\n", path);
+       down(&xs_lock);
+       dir = xs_directory(path, &dir_n);
+       if (IS_ERR(dir)) {
+               err = PTR_ERR(dir);
+               goto unlock;
+       }
+       for (i = 0; i < dir_n; i++) {
+               err = xenbus_probe_device_type(path, dir[i]);
+               if (err)
+                       break;
+       }
+       kfree(dir);
+unlock:
+       up(&xs_lock);
+       dprintf("< err=%i\n", err);
+       return err;
+}
+
+
+static int xenbus_probe_backend(const char *dir, const char *name)
+{
+       int err = 0;
+       struct xenbus_device *xendev = NULL;
+       unsigned int xendev_n = 0;
+       char *nodename = NULL, *devicetype = NULL;
+       unsigned int devicetype_n = 0;
+
+       dprintf("> dir=%s name=%s\n", dir, name);
+       nodename = xenbus_path(dir, name);
+       if (!nodename)
+               return -ENOMEM;
+
+       devicetype = xenbus_read(nodename, XENBUS_DEVICE_TYPE, &devicetype_n);
+       if (IS_ERR(devicetype)) {
+               err = PTR_ERR(devicetype);
+               goto free_nodename;
+       }
+
+       dprintf("> devicetype='%s'\n", devicetype);
+        /* FIXME: This could be a rescan. Don't re-register existing devices. 
*/
+
+       /* Add space for the strings. */
+       xendev_n = sizeof(*xendev) + strlen(nodename) + strlen(devicetype) + 2;
+       xendev = kmalloc(xendev_n, GFP_KERNEL);
+       if (!xendev) {
+               err = -ENOMEM;
+               goto free_devicetype;
+       }
+       memset(xendev, 0, xendev_n);
+
+        snprintf(xendev->dev.bus_id, BUS_ID_SIZE, "%s", devicetype);
+       xendev->dev.bus = &xenback_type;
+
+       /* Copy the strings into the extra space. */
+       xendev->nodename = (char *)(xendev + 1);
+       strcpy(xendev->nodename, nodename);
+       xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1;
+       strcpy(xendev->devicetype, devicetype);
+
+       /* Register with generic device framework. */
+        printk("XENBUS: Registering backend %s\n", xendev->dev.bus_id);
+       err = device_register(&xendev->dev);
+        if (err) {
+                printk("XENBUS: Registering device %s: error %i\n",
+                       xendev->dev.bus_id, err);
+        }
+       if (err)
+               kfree(xendev);
+
+free_devicetype:
+       kfree(devicetype);
+free_nodename:
+       kfree(nodename);
+       dprintf("< err=%i\n", err);
+       return err;
+}
+
+static int xenbus_probe_backends(const char *path)
+{
+       int err = 0;
+       char **dir;
+       unsigned int i, dir_n;
+
+       dprintf("> path=%s\n", path);
+       down(&xs_lock);
+       dir = xs_directory(path, &dir_n);
+       if (IS_ERR(dir)) {
+               err = PTR_ERR(dir);
+               goto unlock;
+       }
+       for (i = 0; i < dir_n; i++) {
+               err = xenbus_probe_backend(path, dir[i]);
+               if (err)
+                       break;
+       }
+       kfree(dir);
+unlock:
+       up(&xs_lock);
+       dprintf("< err=%i\n", err);
+       return err;
+}
+
+int xenbus_register_backend(struct xenbus_driver *drv)
+{
+        int err = 0;
+
+        printk("%s> backend driver %p %s\n", __FUNCTION__,
+               drv, drv->name);
+       drv->driver.name = drv->name;
+       drv->driver.bus = &xenback_type;
+       drv->driver.owner = drv->owner;
+       drv->driver.probe = xenbus_dev_probe;
+       drv->driver.remove = xenbus_dev_remove;
+
+       err = driver_register(&drv->driver);
+        if(err == 0 && xs_init_done && drv->connect){
+                printk("%s> connecting driver %p %s\n", __FUNCTION__,
+                       drv, drv->name);
+                drv->connect(drv);
+        }
+        return err;
+}
+
+void xenbus_unregister_backend(struct xenbus_driver *drv)
+{
+       driver_unregister(&drv->driver);
+}
+
+int xenbus_for_each_backend(struct xenbus_driver * start, void * data,
+                            int (*fn)(struct xenbus_driver *, void *))
+{
+        struct xenbus_for_drv for_data = {
+                .fn = fn,
+                .data = data,
+        };
+        if(!fn)
+                return -EINVAL;
+        return bus_for_each_drv(&xenback_type,
+                                (start ? &start->driver: NULL),
+                                &for_data, for_drv);
+}
+
+static void test_callback(struct xenbus_watch *w, const char *node)
+{
+       printk("test_callback: got watch hit for %s\n", node);
+}
+
+static void test_watch(void)
+{
+        static int init_done = 0;
+       static struct xenbus_watch watch = { .node = "/", 
+                                            .priority = 0, 
+                                            .callback = test_callback };
+
+        if(init_done) return;
+       printk("registering watch %lX = %i\n",
+               (long)&watch,
+              register_xenbus_watch(&watch));
+        init_done = 1;
+}
+
+static int xenbus_driver_connect(struct xenbus_driver *drv, void *data)
+{
+        printk("%s> driver %p %s\n", __FUNCTION__, drv, drv->name);
+        if (drv->connect) {
+                printk("%s> connecting driver %p %s\n", __FUNCTION__,
+                       drv, drv->name);
+                drv->connect(drv);
+        }
+        printk("%s< driver %p %s\n", __FUNCTION__, drv, drv->name);
+        return 0;
+}
+
+int do_xenbus_connect(void *unused)
+{
+       int err = 0;
+
+        printk("%s> xs_init_done=%d\n", __FUNCTION__, xs_init_done);
+       if (xs_init_done)
+                goto exit;
+        /* Initialize xenstore comms unless already done. */
+        printk("store_evtchn = %i\n", xen_start_info.store_evtchn);
+        err = xs_init();
+        if (err) {
+                printk("XENBUS: Error initializing xenstore comms:"
+                       " %i\n", err);
+                goto exit;
+        }
+        xs_init_done = 1;
+
+        /* Notify drivers that xenstore has connected. */
+        test_watch();
+        printk("%s> connect drivers...\n", __FUNCTION__);
+        xenbus_for_each_drv(NULL, NULL, xenbus_driver_connect);
+        printk("%s> connect backends...\n", __FUNCTION__);
+        xenbus_for_each_backend(NULL, NULL, xenbus_driver_connect);
+        
+        /* Enumerate devices and backends in xenstore. */
+       xenbus_probe_devices(XENBUS_DEVICE_DIR);
+        xenbus_probe_backends(XENBUS_BACKEND_DIR);
+
+exit:
+        printk("%s< err=%d\n", __FUNCTION__, err);
+        return err;
+}
+
+static int __init xenbus_probe_init(void)
+{
+        bus_register(&xenbus_type);
+        bus_register(&xenback_type);
+
+       if (!xen_start_info.store_evtchn)
+               return 0;
+
+       do_xenbus_connect(NULL);
+       return 0;
+}
+
+postcore_initcall(xenbus_probe_init);
diff -Nru a/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c 
b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c    2005-06-28 
14:02:15 -04:00
@@ -0,0 +1,488 @@
+/******************************************************************************
+ * xenbus_xs.c
+ *
+ * This is the kernel equivalent of the "xs" library.  We don't need everything
+ * and we use xenbus_comms to communication.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include "xenstore/xenstored.h"
+#include <linux/uio.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/kthread.h>
+#include <asm-xen/xenbus.h>
+#include "xenbus_comms.h"
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+
+static void *xs_in, *xs_out;
+static LIST_HEAD(watches);
+static DECLARE_MUTEX(watches_lock);
+DECLARE_MUTEX(xs_lock);
+
+static int get_error(const char *errorstring)
+{
+       unsigned int i;
+
+       for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
+               if (i == ARRAY_SIZE(xsd_errors) - 1) {
+                       printk(KERN_WARNING "XENBUS xen store gave: unknown 
error %s",
+                              errorstring);
+                       return EINVAL;
+               }
+       }
+       return xsd_errors[i].errnum;
+}
+
+static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
+{
+       struct xsd_sockmsg msg;
+       void *ret;
+       int err;
+
+       err = xb_read(xs_in, &msg, sizeof(msg));
+       if (err)
+               return ERR_PTR(err);
+
+       ret = kmalloc(msg.len + 1, GFP_KERNEL);
+       if (!ret)
+               return ERR_PTR(-ENOMEM);
+
+       err = xb_read(xs_in, ret, msg.len);
+       if (err) {
+               kfree(ret);
+               return ERR_PTR(err);
+       }
+       ((char*)ret)[msg.len] = '\0';
+
+       *type = msg.type;
+       if (len)
+               *len = msg.len;
+       return ret;
+}
+
+/* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
+static void *xs_talkv(enum xsd_sockmsg_type type,
+                     const struct kvec *iovec,
+                     unsigned int num_vecs,
+                     unsigned int *len)
+{
+       struct xsd_sockmsg msg;
+       void *ret = NULL;
+       unsigned int i;
+       int err;
+
+       WARN_ON(down_trylock(&xs_lock) == 0);
+
+       msg.type = type;
+       msg.len = 0;
+       for (i = 0; i < num_vecs; i++)
+               msg.len += iovec[i].iov_len;
+
+       err = xb_write(xs_out, &msg, sizeof(msg));
+       if (err)
+               return ERR_PTR(err);
+
+       for (i = 0; i < num_vecs; i++) {
+               err = xb_write(xs_out, iovec[i].iov_base, iovec[i].iov_len);;
+               if (err)
+                       return ERR_PTR(err);
+       }
+
+       /* Watches can have fired before reply comes: daemon detects
+        * and re-transmits, so we can ignore this. */
+       do {
+               kfree(ret);
+               ret = read_reply(&msg.type, len);
+               if (IS_ERR(ret))
+                       return ret;
+       } while (msg.type == XS_WATCH_EVENT);
+
+       if (msg.type == XS_ERROR) {
+               err = get_error(ret);
+               kfree(ret);
+               return ERR_PTR(-err);
+       }
+
+       BUG_ON(msg.type != type);
+       return ret;
+}
+
+/* Simplified version of xs_talkv: single message. */
+static void *xs_single(enum xsd_sockmsg_type type,
+                      const char *string, unsigned int *len)
+{
+       struct kvec iovec;
+
+       iovec.iov_base = (void *)string;
+       iovec.iov_len = strlen(string) + 1;
+       return xs_talkv(type, &iovec, 1, len);
+}
+
+/* Many commands only need an ack, don't care what it says. */
+static int xs_error(char *reply)
+{
+       if (IS_ERR(reply))
+               return PTR_ERR(reply);
+       kfree(reply);
+       return 0;
+}
+
+static unsigned int count_strings(const char *strings, unsigned int len)
+{
+       unsigned int num;
+       const char *p;
+
+       for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
+               num++;
+
+       return num;
+}
+
+char **xs_directory(const char *path, unsigned int *num)
+{
+       char *strings, *p, **ret;
+       unsigned int len;
+
+       strings = xs_single(XS_DIRECTORY, path, &len);
+       if (IS_ERR(strings))
+               return (char **)strings;
+
+       /* Count the strings. */
+       *num = count_strings(strings, len);
+
+       /* Transfer to one big alloc for easy freeing. */
+       ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
+       if (!ret) {
+               kfree(strings);
+               return ERR_PTR(-ENOMEM);
+       }
+       memcpy(&ret[*num], strings, len);
+       kfree(strings);
+
+       strings = (char *)&ret[*num];
+       for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
+               ret[(*num)++] = p;
+       return ret;
+}
+
+/* Check if a path exists. Return 1 if it does. */
+int xs_exists(const char *path)
+{
+        char **dir;
+        int dir_n;
+
+        dir = xs_directory(path, &dir_n);
+        if(IS_ERR(dir))
+                return 0;
+        kfree(dir);
+        return 1;
+}
+
+/* Make a directory, creating dirs on the path to it if necessary.
+ * Return 0 on success, error code otherwise.
+ */
+int xs_mkdirs(const char *path)
+{
+        int err = 0;
+        char s[strlen(path) + 1], *p = s;
+
+        if(xs_exists(path))
+                goto out;
+        strcpy(p, path);
+        if(*p == '/')
+                p++;
+        for( ; ; ){
+                p = strchr(p, '/');
+                if(p)
+                        *p = '\0';
+                if(!xs_exists(s)){
+                        err = xs_mkdir(s);
+                        if(err)
+                                goto out;
+                        
+                }
+                if(!p)
+                        break;
+                *p++ = '/';
+       }
+  out:
+        return err;
+}
+
+
+/* Get the value of a single file.
+ * Returns a kmalloced value: call free() on it after use.
+ * len indicates length in bytes.
+ */
+void *xs_read(const char *path, unsigned int *len)
+{
+       return xs_single(XS_READ, path, len);
+}
+
+/* Write the value of a single file.
+ * Returns -err on failure.  createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
+ */
+int xs_write(const char *path,
+             const void *data, unsigned int len, int createflags)
+{
+       const char *flags;
+       struct kvec iovec[3];
+
+       /* Format: Flags (as string), path, data. */
+       if (createflags == 0)
+               flags = XS_WRITE_NONE;
+       else if (createflags == O_CREAT)
+               flags = XS_WRITE_CREATE;
+       else if (createflags == (O_CREAT|O_EXCL))
+               flags = XS_WRITE_CREATE_EXCL;
+       else
+               return -EINVAL;
+
+       iovec[0].iov_base = (void *)path;
+       iovec[0].iov_len = strlen(path) + 1;
+       iovec[1].iov_base = (void *)flags;
+       iovec[1].iov_len = strlen(flags) + 1;
+       iovec[2].iov_base = (void *)data;
+       iovec[2].iov_len = len;
+
+       return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
+}
+
+/* Create a new directory. */
+int xs_mkdir(const char *path)
+{
+       return xs_error(xs_single(XS_MKDIR, path, NULL));
+}
+
+/* Destroy a file or directory (directories must be empty). */
+int xs_rm(const char *path)
+{
+       return xs_error(xs_single(XS_RM, path, NULL));
+}
+
+/* Start a transaction: changes by others will not be seen during this
+ * transaction, and changes will not be visible to others until end.
+ * Transaction only applies to the given subtree.
+ * You can only have one transaction at any time.
+ */
+int xs_transaction_start(const char *subtree)
+{
+       return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
+}
+
+/* End a transaction.
+ * If abandon is true, transaction is discarded instead of committed.
+ */
+int xs_transaction_end(int abort)
+{
+       char abortstr[2];
+
+       if (abort)
+               strcpy(abortstr, "F");
+       else
+               strcpy(abortstr, "T");
+       return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
+}
+
+char *xs_get_domain_path(domid_t domid)
+{
+       char domid_str[32];
+
+       sprintf(domid_str, "%u", domid);
+       return xs_single(XS_GETDOMAINPATH, domid_str, NULL);
+}
+
+static int xs_watch(const char *path, const char *token, unsigned int priority)
+{
+       char prio[32];
+       struct kvec iov[3];
+
+       sprintf(prio, "%u", priority);
+       iov[0].iov_base = (void *)path;
+       iov[0].iov_len = strlen(path) + 1;
+       iov[1].iov_base = (void *)token;
+       iov[1].iov_len = strlen(token) + 1;
+       iov[2].iov_base = prio;
+       iov[2].iov_len = strlen(prio) + 1;
+
+       return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+static char *xs_read_watch(char **token)
+{
+       enum xsd_sockmsg_type type;
+       char *ret;
+
+       ret = read_reply(&type, NULL);
+       if (IS_ERR(ret))
+               return ret;
+
+       BUG_ON(type != XS_WATCH_EVENT);
+       *token = ret + strlen(ret) + 1;
+       return ret;
+}
+
+static int xs_acknowledge_watch(const char *token)
+{
+       return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
+}
+
+static int xs_unwatch(const char *path, const char *token)
+{
+       struct kvec iov[2];
+
+       iov[0].iov_base = (char *)path;
+       iov[0].iov_len = strlen(path) + 1;
+       iov[1].iov_base = (char *)token;
+       iov[1].iov_len = strlen(token) + 1;
+
+       return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
+}
+
+/* A little paranoia: we don't just trust token. */
+static struct xenbus_watch *find_watch(const char *token)
+{
+       struct xenbus_watch *i, *cmp;
+
+       cmp = (void *)simple_strtoul(token, NULL, 16);
+
+       list_for_each_entry(i, &watches, list)
+               if (i == cmp)
+                       return i;
+       return NULL;
+}
+
+/* Register callback to watch this node. */
+int register_xenbus_watch(struct xenbus_watch *watch)
+{
+       /* Pointer in ascii is the token. */
+       char token[sizeof(watch) * 2 + 1];
+       int err;
+
+       sprintf(token, "%lX", (long)watch);
+       down(&watches_lock);
+       BUG_ON(find_watch(token));
+
+       down(&xs_lock);
+       err = xs_watch(watch->node, token, watch->priority);
+       up(&xs_lock);
+       if (!err)
+               list_add(&watch->list, &watches);
+       up(&watches_lock);
+       return err;
+}
+
+void unregister_xenbus_watch(struct xenbus_watch *watch)
+{
+       char token[sizeof(watch) * 2 + 1];
+       int err;
+
+       sprintf(token, "%lX", (long)watch);
+       down(&watches_lock);
+       BUG_ON(!find_watch(token));
+
+       down(&xs_lock);
+       err = xs_unwatch(watch->node, token);
+       up(&xs_lock);
+       list_del(&watch->list);
+       up(&watches_lock);
+
+       if (err)
+               printk(KERN_WARNING "XENBUS Failed to release watch %s: %i\n",
+                      watch->node, err);
+}
+
+static int watch_thread(void *unused)
+{
+       int err;
+       unsigned long mtu;
+
+       set_current_state(TASK_INTERRUPTIBLE);
+       schedule_timeout(HZ*10);
+       printk("watch_thread, doing read\n");
+       down(&xs_lock);
+       err = xenbus_read_long("", "mtu", &mtu);
+       up(&xs_lock);
+       printk("fake field read: %i (%lu)\n", err, mtu);
+
+       for (;;) {
+               char *token;
+               char *node = NULL;
+
+               wait_event(xb_waitq, xs_input_avail(xs_in));
+
+               /* If this is a spurious wakeup caused by someone
+                * doing an op, they'll hold the lock and the buffer
+                * will be empty by the time we get there.               
+                */
+               down(&xs_lock);
+               if (xs_input_avail(xs_in))
+                       node = xs_read_watch(&token);
+               /* Release lock before calling callback. */
+               up(&xs_lock);
+               if (node && !IS_ERR(node)) {
+                       struct xenbus_watch *w;
+                       int err;
+
+                       down(&watches_lock);
+                       w = find_watch(token);
+                       BUG_ON(!w);
+                       w->callback(w, node);
+                       up(&watches_lock);
+                       down(&xs_lock);
+                       err = xs_acknowledge_watch(token);
+                       if (err)
+                               printk(KERN_WARNING
+                                      "XENBUS acknowledge %s failed %i\n",
+                                      node, err);
+                       up(&xs_lock);
+                       kfree(node);
+               } else
+                       printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
+                              PTR_ERR(node));
+       }
+}
+
+int xs_init(void)
+{
+       int err;
+       struct task_struct *watcher;
+
+       err = xb_init_comms(&xs_in, &xs_out);
+       if (err)
+               return err;
+       
+       watcher = kthread_run(watch_thread, NULL, "kxbwatch");
+       if (IS_ERR(watcher))
+               return PTR_ERR(watcher);
+       return 0;
+}
diff -Nru a/linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h 
b/linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h  2005-06-28 14:02:15 
-04:00
@@ -0,0 +1,143 @@
+#ifndef _ASM_XEN_XENBUS_H
+#define _ASM_XEN_XENBUS_H
+/******************************************************************************
+ * xenbus.h
+ *
+ * Talks to Xen Store to figure out what devices we have.
+ *
+ * Copyright (C) 2005 Rusty Russell, IBM Corporation
+ * 
+ * This file may be distributed separately from the Linux kernel, or
+ * incorporated into other software packages, subject to the following license:
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/device.h>
+#include <asm/semaphore.h>
+
+/* A xenbus device. */
+struct xenbus_device {
+       char *devicetype;
+       char *subtype;
+       char *nodename;
+       int id;
+       struct device dev;
+};
+
+static inline struct xenbus_device *to_xenbus_device(struct device *dev)
+{
+       return container_of(dev, struct xenbus_device, dev);
+}
+
+struct xenbus_device_id
+{
+       /* .../device/<device_type>/<identifier> */
+       char devicetype[32];    /* General class of device. */
+       char subtype[32];       /* Contents of "subtype" for this device */
+};
+
+/* A xenbus driver. */
+struct xenbus_driver {
+       char *name;
+       struct module *owner;
+       const struct xenbus_device_id *ids;
+        /* Called when xenstore is connected. */
+        int  (*connect) (struct xenbus_driver * drv);
+
+       int  (*probe)    (struct xenbus_device * dev, const struct 
xenbus_device_id * id);
+        int  (*remove)   (struct xenbus_device * dev);
+        int  (*configure)(struct xenbus_device * dev);
+
+       struct device_driver driver;
+};
+
+struct xenbus_evtchn {
+        unsigned long dom1;
+        unsigned long port1;
+        unsigned long dom2;
+        unsigned long port2;
+};
+
+static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
+{
+       return container_of(drv, struct xenbus_driver, driver);
+}
+
+int xenbus_register_driver(struct xenbus_driver *drv);
+void xenbus_unregister_driver(struct xenbus_driver *drv);
+
+int xenbus_register_backend(struct xenbus_driver *drv);
+void xenbus_unregister_backend(struct xenbus_driver *drv);
+
+/* Iterator over xenbus devices (frontend). */
+int xenbus_for_each_dev(struct xenbus_device * start, void * data,
+                        int (*fn)(struct xenbus_device *, void *));
+
+/* Iterator over xenbus drivers (frontend). */
+int xenbus_for_each_drv(struct xenbus_driver * start, void * data,
+                        int (*fn)(struct xenbus_driver *, void *));
+
+/* Iterator over xenbus drivers (backend). */
+int xenbus_for_each_backend(struct xenbus_driver * start, void * data,
+                            int (*fn)(struct xenbus_driver *, void *));
+
+/* Caller must hold this lock to call these functions. */
+extern struct semaphore xs_lock;
+
+char **xs_directory(const char *path, unsigned int *num);
+void *xs_read(const char *path, unsigned int *len);
+int xs_write(const char *path,
+            const void *data, unsigned int len, int createflags);
+int xs_mkdir(const char *path);
+int xs_exists(const char *path);
+int xs_mkdirs(const char *path);
+int xs_rm(const char *path);
+int xs_transaction_start(const char *subtree);
+int xs_transaction_end(int abort);
+char *xs_get_domain_path(domid_t domid);
+
+/* Register callback to watch this node. */
+struct xenbus_watch
+{
+       struct list_head list;
+       char *node;
+       unsigned int priority;
+       void (*callback)(struct xenbus_watch *, const char *node);
+};
+
+int register_xenbus_watch(struct xenbus_watch *watch);
+void unregister_xenbus_watch(struct xenbus_watch *watch);
+
+char *xenbus_path(const char *dir, const char *name);
+char *xenbus_read(const char *dir, const char *name, unsigned int *data_n);
+int xenbus_write(const char *dir, const char *name,
+                 const char *data, int data_n);
+
+int xenbus_read_string(const char *dir, const char *name, char **val);
+int xenbus_write_string(const char *dir, const char *name, const char *val);
+int xenbus_read_ulong(const char *dir, const char *name, unsigned long *val);
+int xenbus_write_ulong(const char *dir, const char *name, unsigned long val);
+int xenbus_read_long(const char *dir, const char *name, long *val);
+int xenbus_write_long(const char *dir, const char *name, long val);
+int xenbus_read_mac(const char *dir, const char *name, unsigned char mac[6]);
+int xenbus_write_mac(const char *dir, const char *name, const unsigned char 
mac[6]);
+int xenbus_read_evtchn(const char *dir, const char *name, struct xenbus_evtchn 
*evtchn);
+int xenbus_message(const char *dir, const char *val, ...);
+
+#endif /* _ASM_XEN_XENBUS_H */
diff -Nru a/tools/python/xen/xend/XendDomainInfo.py 
b/tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   2005-06-28 14:02:15 -04:00
+++ b/tools/python/xen/xend/XendDomainInfo.py   2005-06-28 14:02:15 -04:00
@@ -565,10 +565,10 @@
         self.create_channel()
         self.image.createImage()
         self.exportToDB()
-        #if self.store_channel:
-        #    self.db.introduceDomain(self.id,
-        #                            self.store_mfn,
-        #                            self.store_channel)
+        if self.store_channel:
+            self.db.introduceDomain(self.id,
+                                    self.store_mfn,
+                                    self.store_channel)
 
     def delete(self):
         """Delete the vm's db.
@@ -615,11 +615,11 @@
                 self.store_channel = None
             except:
                 pass
-            #try:
-            #    self.db.releaseDomain(self.id)
-            #except Exception, ex:
-            #    log.warning("error in domain release on xenstore: %s", ex)
-            #    pass
+            try:
+                self.db.releaseDomain(self.id)
+            except Exception, ex:
+                log.warning("error in domain release on xenstore: %s", ex)
+                pass
         if self.image:
             try:
                 self.image.destroy()

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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