ia64/xen-unstable

changeset 5598:864b050694f8

bitkeeper revision 1.1766 (42c17071SPDLo7qPlXAiQzrKjMu6Mw)

Add xenbus driver.
XendDomainInfo.py:
Connect/Disconnect domains to/from store.
Signed-off-by: Rusty Russel <rusty@rustcorp.com.au> (authored)
Signed-off-by: Mike Wray <mike.wray@hp.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Jun 28 15:44:49 2005 +0000 (2005-06-28)
parents a81dabf6ba10
children 348b774a8f97
files .rootkeys linux-2.6.11-xen-sparse/drivers/xen/Makefile linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h tools/python/xen/xend/XendDomainInfo.py
line diff
     1.1 --- a/.rootkeys	Tue Jun 28 15:35:45 2005 +0000
     1.2 +++ b/.rootkeys	Tue Jun 28 15:44:49 2005 +0000
     1.3 @@ -346,6 +346,11 @@ 41ee5e8bSs3BGC7yegM_ek2Tn0Ahvw linux-2.6
     1.4  41ee5e8bglvqKvZSY5uJ5JGQejEwyQ linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c
     1.5  41ee5e8ckZ9xVNvu9NHIZDK7JqApmQ linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c
     1.6  41ee5e8ck9scpGirfqEZRARbGDyTXA linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h
     1.7 +42c16ff4NMHjAt9hJHldXC-4_A6HRw linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile
     1.8 +42c16ff4IWzDjvg0o08Nt-JrmuoJsA linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
     1.9 +42c16ff4DukLxK4_pUAN0Gv0jLNaZQ linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h
    1.10 +42c16ff4fR8SNUirS3q19HNzTVoDXw linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
    1.11 +42c16ff4goC8GfJvEqNFgE1Y8fNs5g linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
    1.12  412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.11-xen-sparse/include/asm-generic/pgtable.h
    1.13  42400318xlBIV46qyxLTaDepPLNyhg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/agp.h
    1.14  40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/desc.h
    1.15 @@ -420,6 +425,7 @@ 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6
    1.16  4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.11-xen-sparse/include/asm-xen/queues.h
    1.17  42a885cawNQ18_b7i5-G7ekMsZ48hw linux-2.6.11-xen-sparse/include/asm-xen/synch_bitops.h
    1.18  3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.11-xen-sparse/include/asm-xen/xen_proc.h
    1.19 +42c16ff4t7djt61KEsejdrL8gNfQSA linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h
    1.20  419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.11-xen-sparse/include/linux/gfp.h
    1.21  42305f545Vc5SLCUewZ2-n-P9JJhEQ linux-2.6.11-xen-sparse/include/linux/highmem.h
    1.22  419dfc609zbti8rqL60tL2dHXQ_rvQ linux-2.6.11-xen-sparse/include/linux/irq.h
     2.1 --- a/linux-2.6.11-xen-sparse/drivers/xen/Makefile	Tue Jun 28 15:35:45 2005 +0000
     2.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/Makefile	Tue Jun 28 15:44:49 2005 +0000
     2.3 @@ -4,6 +4,7 @@ obj-y	+= console/
     2.4  obj-y	+= evtchn/
     2.5  obj-y	+= balloon/
     2.6  obj-y	+= privcmd/
     2.7 +obj-y	+= xenbus/
     2.8  
     2.9  obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
    2.10  obj-$(CONFIG_XEN_NETDEV_BACKEND)	+= netback/
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/Makefile	Tue Jun 28 15:44:49 2005 +0000
     3.3 @@ -0,0 +1,10 @@
     3.4 +obj-y	+= xenbus.o
     3.5 +
     3.6 +xenbus-objs =
     3.7 +xenbus-objs += xenbus_comms.o
     3.8 +xenbus-objs += xenbus_xs.o
     3.9 +xenbus-objs += xenbus_probe.o 
    3.10 +
    3.11 +XEN_TOOLS_DIR := "../tools"
    3.12 +vpath %.h $(XEN_TOOLS_DIR)
    3.13 +EXTRA_CFLAGS += -I $(XEN_TOOLS_DIR)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Tue Jun 28 15:44:49 2005 +0000
     4.3 @@ -0,0 +1,208 @@
     4.4 +/******************************************************************************
     4.5 + * xenbus_comms.c
     4.6 + *
     4.7 + * Low level code to talks to Xen Store: ringbuffer and event channel.
     4.8 + *
     4.9 + * Copyright (C) 2005 Rusty Russell, IBM Corporation
    4.10 + * 
    4.11 + * This file may be distributed separately from the Linux kernel, or
    4.12 + * incorporated into other software packages, subject to the following license:
    4.13 + * 
    4.14 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    4.15 + * of this source file (the "Software"), to deal in the Software without
    4.16 + * restriction, including without limitation the rights to use, copy, modify,
    4.17 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    4.18 + * and to permit persons to whom the Software is furnished to do so, subject to
    4.19 + * the following conditions:
    4.20 + * 
    4.21 + * The above copyright notice and this permission notice shall be included in
    4.22 + * all copies or substantial portions of the Software.
    4.23 + * 
    4.24 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    4.25 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    4.26 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    4.27 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    4.28 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    4.29 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    4.30 + * IN THE SOFTWARE.
    4.31 + */
    4.32 +//#define DEBUG
    4.33 +
    4.34 +#include <asm-xen/hypervisor.h>
    4.35 +#include <asm-xen/evtchn.h>
    4.36 +#include <linux/wait.h>
    4.37 +#include <linux/interrupt.h>
    4.38 +#include <linux/sched.h>
    4.39 +#include <linux/err.h>
    4.40 +#include "xenbus_comms.h"
    4.41 +
    4.42 +#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
    4.43 +struct ringbuf_head
    4.44 +{
    4.45 +	u32 write; /* Next place to write to */
    4.46 +	u32 read; /* Next place to read from */
    4.47 +	u8 flags;
    4.48 +	char buf[0];
    4.49 +} __attribute__((packed));
    4.50 +
    4.51 +DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
    4.52 +
    4.53 +static irqreturn_t wake_waiting(int irq, void *unused, struct pt_regs *regs)
    4.54 +{
    4.55 +	wake_up(&xb_waitq);
    4.56 +	return IRQ_HANDLED;
    4.57 +}
    4.58 +
    4.59 +static int check_buffer(const struct ringbuf_head *h)
    4.60 +{
    4.61 +	return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
    4.62 +}
    4.63 +
    4.64 +/* We can't fill last byte: would look like empty buffer. */
    4.65 +static void *get_output_chunk(const struct ringbuf_head *h,
    4.66 +			      void *buf, u32 *len)
    4.67 +{
    4.68 +	u32 read_mark;
    4.69 +
    4.70 +	if (h->read == 0)
    4.71 +		read_mark = RINGBUF_DATASIZE - 1;
    4.72 +	else
    4.73 +		read_mark = h->read - 1;
    4.74 +
    4.75 +	/* Here to the end of buffer, unless they haven't read some out. */
    4.76 +	*len = RINGBUF_DATASIZE - h->write;
    4.77 +	if (read_mark >= h->write)
    4.78 +		*len = read_mark - h->write;
    4.79 +	return buf + h->write;
    4.80 +}
    4.81 +
    4.82 +static const void *get_input_chunk(const struct ringbuf_head *h,
    4.83 +				   const void *buf, u32 *len)
    4.84 +{
    4.85 +	/* Here to the end of buffer, unless they haven't written some. */
    4.86 +	*len = RINGBUF_DATASIZE - h->read;
    4.87 +	if (h->write >= h->read)
    4.88 +		*len = h->write - h->read;
    4.89 +	return buf + h->read;
    4.90 +}
    4.91 +
    4.92 +static void update_output_chunk(struct ringbuf_head *h, u32 len)
    4.93 +{
    4.94 +	h->write += len;
    4.95 +	if (h->write == RINGBUF_DATASIZE)
    4.96 +		h->write = 0;
    4.97 +}
    4.98 +
    4.99 +static void update_input_chunk(struct ringbuf_head *h, u32 len)
   4.100 +{
   4.101 +	h->read += len;
   4.102 +	if (h->read == RINGBUF_DATASIZE)
   4.103 +		h->read = 0;
   4.104 +}
   4.105 +
   4.106 +static int output_avail(struct ringbuf_head *out)
   4.107 +{
   4.108 +	unsigned int avail;
   4.109 +
   4.110 +	get_output_chunk(out, out->buf, &avail);
   4.111 +	return avail != 0;
   4.112 +}
   4.113 +
   4.114 +int xb_write(struct ringbuf_head *out, const void *data, unsigned len)
   4.115 +{
   4.116 +	struct ringbuf_head h;
   4.117 +
   4.118 +	do {
   4.119 +		void *dst;
   4.120 +		unsigned int avail;
   4.121 +
   4.122 +		wait_event(xb_waitq, output_avail(out));
   4.123 +
   4.124 +		/* Read, then check: not that we don't trust store.
   4.125 +		 * Hell, some of my best friends are daemons.  But,
   4.126 +		 * in this post-911 world... */
   4.127 +		h = *out;
   4.128 +		mb();
   4.129 +		if (!check_buffer(&h)) {
   4.130 +			set_current_state(TASK_RUNNING);
   4.131 +			return -EIO; /* ETERRORIST! */
   4.132 +		}
   4.133 +
   4.134 +		dst = get_output_chunk(&h, out->buf, &avail);
   4.135 +		if (avail > len)
   4.136 +			avail = len;
   4.137 +		memcpy(dst, data, avail);
   4.138 +		data += avail;
   4.139 +		len -= avail;
   4.140 +		update_output_chunk(out, avail);
   4.141 +		notify_via_evtchn(xen_start_info.store_evtchn);
   4.142 +	} while (len != 0);
   4.143 +
   4.144 +	return 0;
   4.145 +}
   4.146 +
   4.147 +int xs_input_avail(struct ringbuf_head *in)
   4.148 +{
   4.149 +	unsigned int avail;
   4.150 +
   4.151 +	get_input_chunk(in, in->buf, &avail);
   4.152 +	return avail != 0;
   4.153 +}
   4.154 +
   4.155 +int xb_read(struct ringbuf_head *in, void *data, unsigned len)
   4.156 +{
   4.157 +	struct ringbuf_head h;
   4.158 +	int was_full;
   4.159 +
   4.160 +	while (len != 0) {
   4.161 +		unsigned int avail;
   4.162 +		const char *src;
   4.163 +
   4.164 +		wait_event(xb_waitq, xs_input_avail(in));
   4.165 +		h = *in;
   4.166 +		mb();
   4.167 +		if (!check_buffer(&h)) {
   4.168 +			set_current_state(TASK_RUNNING);
   4.169 +			return -EIO;
   4.170 +		}
   4.171 +
   4.172 +		src = get_input_chunk(&h, in->buf, &avail);
   4.173 +		if (avail > len)
   4.174 +			avail = len;
   4.175 +		was_full = !output_avail(&h);
   4.176 +
   4.177 +		memcpy(data, src, avail);
   4.178 +		data += avail;
   4.179 +		len -= avail;
   4.180 +		update_input_chunk(in, avail);
   4.181 +		pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
   4.182 +		/* If it was full, tell them we've taken some. */
   4.183 +		if (was_full)
   4.184 +			notify_via_evtchn(xen_start_info.store_evtchn);
   4.185 +	}
   4.186 +
   4.187 +	/* If we left something, wake watch thread to deal with it. */
   4.188 +	if (xs_input_avail(in))
   4.189 +		wake_up(&xb_waitq);
   4.190 +
   4.191 +	return 0;
   4.192 +}
   4.193 +
   4.194 +/* Set up interrpt handler off store event channel. */
   4.195 +int xb_init_comms(void **in, void **out)
   4.196 +{
   4.197 +	int err, irq;
   4.198 +
   4.199 +	irq = bind_evtchn_to_irq(xen_start_info.store_evtchn);
   4.200 +
   4.201 +	err = request_irq(irq, wake_waiting, SA_SHIRQ, "xenbus", &xb_waitq);
   4.202 +	if (err) {
   4.203 +		printk(KERN_ERR "XENBUS request irq failed %i\n", err);
   4.204 +		unbind_evtchn_from_irq(xen_start_info.store_evtchn);
   4.205 +		return err;
   4.206 +	}
   4.207 +
   4.208 +	*out = (void *)xen_start_info.store_page;
   4.209 +	*in = (void *)xen_start_info.store_page + PAGE_SIZE/2;
   4.210 +	return 0;
   4.211 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_comms.h	Tue Jun 28 15:44:49 2005 +0000
     5.3 @@ -0,0 +1,14 @@
     5.4 +/* Private include for xenbus communications. */
     5.5 +#ifndef _XENBUS_COMMS_H
     5.6 +#define _XENBUS_COMMS_H
     5.7 +int xs_init(void);
     5.8 +int xb_init_comms(void **in, void **out);
     5.9 +
    5.10 +/* Low level routines. */
    5.11 +struct ringbuf_head;
    5.12 +int xb_write(struct ringbuf_head *out, const void *data, unsigned len);
    5.13 +int xb_read(struct ringbuf_head *in, void *data, unsigned len);
    5.14 +int xs_input_avail(struct ringbuf_head *in);
    5.15 +extern wait_queue_head_t xb_waitq;
    5.16 +
    5.17 +#endif /* _XENBUS_COMMS_H */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Tue Jun 28 15:44:49 2005 +0000
     6.3 @@ -0,0 +1,870 @@
     6.4 +/******************************************************************************
     6.5 + * Talks to Xen Store to figure out what devices we have.
     6.6 + * Currently experiment code, but when I grow up I'll be a bus driver!
     6.7 + *
     6.8 + * Copyright (C) 2005 Rusty Russell, IBM Corporation
     6.9 + * Copyright (C) 2005 Mike Wray, Hewlett-Packard
    6.10 + * 
    6.11 + * This file may be distributed separately from the Linux kernel, or
    6.12 + * incorporated into other software packages, subject to the following license:
    6.13 + * 
    6.14 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    6.15 + * of this source file (the "Software"), to deal in the Software without
    6.16 + * restriction, including without limitation the rights to use, copy, modify,
    6.17 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    6.18 + * and to permit persons to whom the Software is furnished to do so, subject to
    6.19 + * the following conditions:
    6.20 + * 
    6.21 + * The above copyright notice and this permission notice shall be included in
    6.22 + * all copies or substantial portions of the Software.
    6.23 + * 
    6.24 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    6.25 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    6.26 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    6.27 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    6.28 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    6.29 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    6.30 + * IN THE SOFTWARE.
    6.31 + */
    6.32 +#include <asm-xen/hypervisor.h>
    6.33 +#include <asm-xen/xenbus.h>
    6.34 +#include <linux/kernel.h>
    6.35 +#include <linux/err.h>
    6.36 +#include <linux/string.h>
    6.37 +#include <linux/ctype.h>
    6.38 +#include <linux/fcntl.h>
    6.39 +#include <stdarg.h>
    6.40 +#include "xenbus_comms.h"
    6.41 +
    6.42 +/* Directory inside a domain containing devices. */
    6.43 +#define XENBUS_DEVICE_DIR  "device"
    6.44 +
    6.45 +/* Directory inside a domain containing backends. */
    6.46 +#define XENBUS_BACKEND_DIR  "backend"
    6.47 +
    6.48 +/* Name of field containing device id. */
    6.49 +#define XENBUS_DEVICE_ID   "id"
    6.50 +
    6.51 +/* Name of field containing device type. */
    6.52 +#define XENBUS_DEVICE_TYPE "type"
    6.53 +
    6.54 +//#define DEBUG
    6.55 +
    6.56 +#ifdef DEBUG
    6.57 +#define dprintf(_fmt, _args...) \
    6.58 +printk(KERN_INFO __stringify(KBUILD_MODNAME) " [DBG] %s"    _fmt, __FUNCTION__, ##_args)
    6.59 +#else
    6.60 +#define dprintf(_fmt, _args...) do { } while(0)
    6.61 +#endif
    6.62 +
    6.63 +static int xs_init_done = 0;
    6.64 +
    6.65 +/* Return the path to dir with /name appended.
    6.66 + * If name is null or empty returns a copy of dir.
    6.67 + */ 
    6.68 +char *xenbus_path(const char *dir, const char *name)
    6.69 +{
    6.70 +	char *ret;
    6.71 +        if(name && strlen(name)){
    6.72 +                ret = kmalloc(strlen(dir) + 1 + strlen(name) + 1, GFP_KERNEL);
    6.73 +                if (!ret)
    6.74 +                        return NULL;
    6.75 +                strcpy(ret, dir);
    6.76 +		strcat(ret, "/");
    6.77 +		strcat(ret, name);
    6.78 +	} else {
    6.79 +                ret = kmalloc(strlen(dir) + 1, GFP_KERNEL);
    6.80 +                if (!ret)
    6.81 +                        return NULL;
    6.82 +                strcpy(ret, dir);
    6.83 +        }
    6.84 +	return ret;
    6.85 +}
    6.86 +
    6.87 +#define streq(a, b) (strcmp((a), (b)) == 0)
    6.88 +
    6.89 +char *xenbus_read(const char *dir, const char *name, unsigned int *data_n)
    6.90 +{
    6.91 +        int err = 0;
    6.92 +	char *data = NULL;
    6.93 +	char *path = xenbus_path(dir, name);
    6.94 +        int n = 0;
    6.95 +
    6.96 +	if (!path) {
    6.97 +                err = -ENOMEM;
    6.98 +                goto out;
    6.99 +        }
   6.100 +	data = xs_read(path, &n);
   6.101 +	if (IS_ERR(data)){
   6.102 +                err = PTR_ERR(data);
   6.103 +                if(err == -EISDIR){
   6.104 +                        err = -ENOENT;
   6.105 +                }
   6.106 +        } else if(n == 0){
   6.107 +                err = -ENOENT;
   6.108 +                kfree(data);
   6.109 +        } else if(data[n - 1] != '\0') {
   6.110 +                /* This shouldn't happen: everything is supposed to be a string. */
   6.111 +		printk("XENBUS: Reading path %s: missing null terminator len=%i\n", path, n); 
   6.112 +                err = -EINVAL;
   6.113 +                kfree(data);
   6.114 +                n = 0;
   6.115 +        }
   6.116 +        kfree(path);
   6.117 +  out:
   6.118 +        if(data_n)
   6.119 +                *data_n = n;
   6.120 +	return (err ? ERR_PTR(err) : data);
   6.121 +}
   6.122 +
   6.123 +int xenbus_write(const char *dir, const char *name, const char *data, int data_n)
   6.124 +{
   6.125 +        int err = 0;
   6.126 +	char *path = xenbus_path(dir, name);
   6.127 +
   6.128 +	if (!path)
   6.129 +		return -ENOMEM;
   6.130 +        err = xs_write(path, data, data_n, O_CREAT);
   6.131 +	kfree(path);
   6.132 +        return err;
   6.133 +}
   6.134 +
   6.135 +int xenbus_read_string(const char *dir, const char *name, char **val)
   6.136 +{
   6.137 +        int err = 0;
   6.138 +
   6.139 +        *val = xenbus_read(dir, name, NULL);
   6.140 +        if (IS_ERR(*val)) {
   6.141 +                err = PTR_ERR(*val);
   6.142 +                *val = NULL;
   6.143 +        }
   6.144 +        return err;
   6.145 +}
   6.146 +
   6.147 +int xenbus_write_string(const char *dir, const char *name, const char *val)
   6.148 +{
   6.149 +        return xenbus_write(dir, name, val, strlen(val) + 1);
   6.150 +}
   6.151 +
   6.152 +int xenbus_read_ulong(const char *dir, const char *name, unsigned long *val)
   6.153 +{
   6.154 +	int err = 0;
   6.155 +	char *data = NULL, *end = NULL;
   6.156 +	unsigned int data_n = 0;
   6.157 +
   6.158 +	data = xenbus_read(dir, name, &data_n);
   6.159 +	if (IS_ERR(data)) {
   6.160 +		err = PTR_ERR(data);
   6.161 +                goto out;
   6.162 +        }
   6.163 +        if (data_n <= 1) {
   6.164 +                err = -ENOENT;
   6.165 +                goto free_data;
   6.166 +        }
   6.167 +        *val = simple_strtoul(data, &end, 10);
   6.168 +        if (end != data + data_n - 1) {
   6.169 +                printk("XENBUS: Path %s/%s, bad parse of '%s' as ulong\n",
   6.170 +                       dir, name, data);
   6.171 +                err = -EINVAL;
   6.172 +	}
   6.173 +  free_data:
   6.174 +	kfree(data);
   6.175 +  out:
   6.176 +        if (err)
   6.177 +                *val = 0;
   6.178 +	return err;
   6.179 +}
   6.180 +
   6.181 +int xenbus_write_ulong(const char *dir, const char *name, unsigned long val)
   6.182 +{
   6.183 +	char data[32] = {};
   6.184 +
   6.185 +        snprintf(data, sizeof(data), "%lu", val);
   6.186 +	return xenbus_write(dir, name, data, strlen(data) + 1);
   6.187 +}
   6.188 +
   6.189 +int xenbus_read_long(const char *dir, const char *name, long *val)
   6.190 +{
   6.191 +	int err = 0;
   6.192 +	char *data = NULL, *end = NULL;
   6.193 +	unsigned int data_n = 0;
   6.194 +
   6.195 +	data = xenbus_read(dir, name, &data_n);
   6.196 +	if (IS_ERR(data)) {
   6.197 +		err = PTR_ERR(data);
   6.198 +                goto out;
   6.199 +        }
   6.200 +        if (data_n <= 1) {
   6.201 +                err = -ENOENT;
   6.202 +                goto free_data;
   6.203 +        }
   6.204 +        *val = simple_strtol(data, &end, 10);
   6.205 +        if (end != data + data_n - 1) {
   6.206 +                printk("XENBUS: Path %s/%s, bad parse of '%s' as long\n",
   6.207 +                       dir, name, data);
   6.208 +                err = -EINVAL;
   6.209 +        }
   6.210 +  free_data:
   6.211 +	kfree(data);
   6.212 +  out:
   6.213 +        if (err)
   6.214 +                *val = 0;
   6.215 +	return err;
   6.216 +}
   6.217 +
   6.218 +int xenbus_write_long(const char *dir, const char *name, long val)
   6.219 +{
   6.220 +	char data[32] = {};
   6.221 +
   6.222 +        snprintf(data, sizeof(data), "%li", val);
   6.223 +	return xenbus_write(dir, name, data, strlen(data) + 1);
   6.224 +}
   6.225 +
   6.226 +/* Number of characters in string form of a MAC address. */
   6.227 +#define MAC_LENGTH    17
   6.228 +
   6.229 +/** Convert a mac address from a string of the form
   6.230 + * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
   6.231 + * Each X denotes a hex digit: 0..9, a..f, A..F.
   6.232 + * Also supports using '-' as the separator instead of ':'.
   6.233 + */
   6.234 +static int mac_aton(const char *macstr, unsigned int n, unsigned char mac[6]){
   6.235 +        int err = -EINVAL;
   6.236 +        int i, j;
   6.237 +        const char *p;
   6.238 +        char sep = 0;
   6.239 +        
   6.240 +        if(!macstr || n != MAC_LENGTH){
   6.241 +                goto exit;
   6.242 +        }
   6.243 +        for(i = 0, p = macstr; i < 6; i++){
   6.244 +                unsigned char d = 0;
   6.245 +                if(i){
   6.246 +                        if(!sep){
   6.247 +                                if(*p == ':' || *p == '-') sep = *p;
   6.248 +                        }
   6.249 +                        if(sep && *p == sep){
   6.250 +                                p++;
   6.251 +                        } else {
   6.252 +                                goto exit;
   6.253 +                        }
   6.254 +                }
   6.255 +                for(j = 0; j < 2; j++, p++){
   6.256 +                        if(j) d <<= 4;
   6.257 +                        if(isdigit(*p)){
   6.258 +                                d += *p - '0';
   6.259 +                        } else if(isxdigit(*p)){
   6.260 +                                d += toupper(*p) - 'A' + 10;
   6.261 +                        } else {
   6.262 +                                goto exit;
   6.263 +                        }
   6.264 +                }
   6.265 +                mac[i] = d;
   6.266 +        }
   6.267 +        err = 0;
   6.268 +  exit:
   6.269 +        return err;
   6.270 +}
   6.271 +
   6.272 +int xenbus_read_mac(const char *dir, const char *name, unsigned char mac[6])
   6.273 +{
   6.274 +	int err = 0;
   6.275 +	char *data = 0;
   6.276 +	unsigned int data_n = 0;
   6.277 +
   6.278 +	data = xenbus_read(dir, name, &data_n);
   6.279 +	if (IS_ERR(data)) {
   6.280 +		err = PTR_ERR(data);
   6.281 +                goto out;
   6.282 +        }
   6.283 +        if (data_n <= 1) {
   6.284 +                err = -ENOENT;
   6.285 +                goto free_data;
   6.286 +        }
   6.287 +        err = mac_aton(data, data_n - 1, mac);
   6.288 +        if (err) {
   6.289 +                printk("XENBUS: Path %s/%s, bad parse of '%s' as mac\n",
   6.290 +                       dir, name, data);
   6.291 +                err = -EINVAL;
   6.292 +        }
   6.293 +  free_data:
   6.294 +        kfree(data);
   6.295 +  out:
   6.296 +        if(err)
   6.297 +                memset(mac, 0, sizeof(mac));
   6.298 +        return err;
   6.299 +}
   6.300 +
   6.301 +int xenbus_write_mac(const char *dir, const char *name, const unsigned char mac[6])
   6.302 +{
   6.303 +        char buf[MAC_LENGTH + 1] = {};
   6.304 +        int buf_n = sizeof(buf);
   6.305 +        
   6.306 +        snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
   6.307 +                 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
   6.308 +        buf[buf_n - 1] = '\0';
   6.309 +        return xenbus_write(dir, name, buf, buf_n);
   6.310 +}
   6.311 +
   6.312 +/* Read event channel information from xenstore.
   6.313 + *
   6.314 + * Event channel xenstore fields:
   6.315 + * dom1		- backend domain id (int)
   6.316 + * port1	- backend port (int)
   6.317 + * dom2		- frontend domain id (int)
   6.318 + * port2	- frontend port (int)
   6.319 + */
   6.320 +int xenbus_read_evtchn(const char *dir, const char *name, struct xenbus_evtchn *evtchn)
   6.321 +{
   6.322 +        int err = 0;
   6.323 +        char *evtchn_path = xenbus_path(dir, name);
   6.324 +
   6.325 +        if (!evtchn_path) {
   6.326 +                err = -ENOMEM;
   6.327 +                goto out;
   6.328 +        }
   6.329 +        err = xenbus_read_ulong(evtchn_path, "dom1",  &evtchn->dom1);
   6.330 +        if(err)
   6.331 +                goto free_evtchn_path;
   6.332 +        err = xenbus_read_ulong(evtchn_path, "port1", &evtchn->port1);
   6.333 +        if(err)
   6.334 +                goto free_evtchn_path;
   6.335 +        err = xenbus_read_ulong(evtchn_path, "dom2",  &evtchn->dom2);
   6.336 +        if(err)
   6.337 +                goto free_evtchn_path;
   6.338 +        err = xenbus_read_ulong(evtchn_path, "port2", &evtchn->port2);
   6.339 +
   6.340 +  free_evtchn_path:
   6.341 +        kfree(evtchn_path);
   6.342 +  out:
   6.343 +        if (err)
   6.344 +                *evtchn = (struct xenbus_evtchn){};
   6.345 +        return err;
   6.346 +}
   6.347 +
   6.348 +/* Write a message to 'dir'.
   6.349 + * The data is 'val' followed by parameter names and values,
   6.350 + * terminated by NULL.
   6.351 + */
   6.352 +int xenbus_message(const char *dir, const char *val, ...)
   6.353 +{
   6.354 +        static const char *mid_name = "@mid";
   6.355 +        va_list args;
   6.356 +        int err = 0;
   6.357 +        char *mid_path = NULL; 
   6.358 +        char *msg_path = NULL;
   6.359 +        char mid_str[32] = {};
   6.360 +        long mid = 0;
   6.361 +        int i;
   6.362 +
   6.363 +        va_start(args, val);
   6.364 +        mid_path = xenbus_path(dir, mid_name);
   6.365 +        if (!mid_path) {
   6.366 +                err = -ENOMEM;
   6.367 +                goto out;
   6.368 +        }
   6.369 +        err = xenbus_read_long(dir, mid_name, &mid);
   6.370 +        if(err != -ENOENT)
   6.371 +                goto out;
   6.372 +        mid++;
   6.373 +        err = xenbus_write_long(dir, mid_name, mid);
   6.374 +        if(err)
   6.375 +                goto out;
   6.376 +        sprintf(mid_str, "%li", mid);
   6.377 +        msg_path = xenbus_path(dir, mid_str);
   6.378 +        if (!mid_path) {
   6.379 +                err = -ENOMEM;
   6.380 +                goto out;
   6.381 +        }
   6.382 +
   6.383 +        for(i = 0; i < 16; i++){
   6.384 +                char *k, *v;
   6.385 +                k = va_arg(args, char *);
   6.386 +                if(!k)
   6.387 +                        break;
   6.388 +                v = va_arg(args, char *);
   6.389 +                if(!v)
   6.390 +                        break;
   6.391 +                err = xenbus_write_string(msg_path, k, v);
   6.392 +                if(err)
   6.393 +                        goto out;
   6.394 +        }
   6.395 +        err = xenbus_write_string(msg_path, NULL, val);
   6.396 +
   6.397 +  out:
   6.398 +        kfree(msg_path);
   6.399 +        kfree(mid_path);
   6.400 +        va_end(args);
   6.401 +        return err;
   6.402 +}
   6.403 +
   6.404 +/* If something in array of ids matches this device, return it. */
   6.405 +static const struct xenbus_device_id *
   6.406 +match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
   6.407 +{
   6.408 +	for( ; !streq(arr->devicetype, ""); arr++) {
   6.409 +		if (!streq(arr->devicetype, dev->devicetype))
   6.410 +			continue;
   6.411 +
   6.412 +		if (streq(arr->subtype, "")
   6.413 +		    || streq(arr->subtype, dev->subtype)) {
   6.414 +			return arr;
   6.415 +		}
   6.416 +	}
   6.417 +	return NULL;
   6.418 +}
   6.419 +
   6.420 +static int xenbus_match(struct device *_dev, struct device_driver *_drv)
   6.421 +{
   6.422 +	struct xenbus_driver *drv = to_xenbus_driver(_drv);
   6.423 +
   6.424 +	if (!drv->ids)
   6.425 +		return 0;
   6.426 +
   6.427 +	return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
   6.428 +}
   6.429 +
   6.430 +/* Bus type for frontend drivers. */
   6.431 +static struct bus_type xenbus_type = {
   6.432 +	.name  = "xenbus",
   6.433 +	.match = xenbus_match,
   6.434 +};
   6.435 +
   6.436 +
   6.437 +/* Bus type for backend drivers. */
   6.438 +static struct bus_type xenback_type = {
   6.439 +        .name  = "xenback",
   6.440 +        .match = xenbus_match,
   6.441 +};
   6.442 +
   6.443 +struct xenbus_for_dev {
   6.444 +        int (*fn)(struct xenbus_device *, void *);
   6.445 +        void *data;
   6.446 +};
   6.447 +
   6.448 +static int for_dev(struct device *_dev, void *_data)
   6.449 +{
   6.450 +        struct xenbus_device *dev = to_xenbus_device(_dev);
   6.451 +        struct xenbus_for_dev *data = _data;
   6.452 +        dev = to_xenbus_device(_dev);
   6.453 +        return data->fn(dev, data->data);
   6.454 +}
   6.455 +
   6.456 +int xenbus_for_each_dev(struct xenbus_device * start, void * data,
   6.457 +                        int (*fn)(struct xenbus_device *, void *))
   6.458 +{
   6.459 +        struct xenbus_for_dev for_data = {
   6.460 +                .fn = fn,
   6.461 +                .data = data,
   6.462 +        };
   6.463 +        if(!fn)
   6.464 +                return -EINVAL;
   6.465 +        printk("%s> data=%p fn=%p for_data=%p\n", __FUNCTION__,
   6.466 +               data, fn, &for_data);
   6.467 +        return bus_for_each_dev(&xenbus_type, 
   6.468 +                                (start ? &start->dev : NULL),
   6.469 +                                &for_data, for_dev);
   6.470 +}
   6.471 +
   6.472 +struct xenbus_for_drv {
   6.473 +        int (*fn)(struct xenbus_driver *, void *);
   6.474 +        void *data;
   6.475 +};
   6.476 +
   6.477 +static int for_drv(struct device_driver *_drv, void *_data)
   6.478 +{
   6.479 +        struct xenbus_driver *drv = to_xenbus_driver(_drv);
   6.480 +        struct xenbus_for_drv *data = _data;
   6.481 +        return data->fn(drv, data->data);
   6.482 +}
   6.483 +
   6.484 +int xenbus_for_each_drv(struct xenbus_driver * start, void * data,
   6.485 +                        int (*fn)(struct xenbus_driver *, void *))
   6.486 +{
   6.487 +        struct xenbus_for_drv for_data = {
   6.488 +                .fn = fn,
   6.489 +                .data = data,
   6.490 +        };
   6.491 +        if(!fn)
   6.492 +                return -EINVAL;
   6.493 +        return bus_for_each_drv(&xenbus_type,
   6.494 +                                (start ? &start->driver: NULL),
   6.495 +                                &for_data, for_drv);
   6.496 +}
   6.497 +
   6.498 +static int xenbus_dev_probe(struct device *_dev)
   6.499 +{
   6.500 +	struct xenbus_device *dev = to_xenbus_device(_dev);
   6.501 +	struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
   6.502 +	const struct xenbus_device_id *id;
   6.503 +
   6.504 +	if (!drv->probe)
   6.505 +		return -ENODEV;
   6.506 +
   6.507 +	id = match_device(drv->ids, dev);
   6.508 +	if (!id)
   6.509 +		return -ENODEV;
   6.510 +	return drv->probe(dev, id);
   6.511 +}
   6.512 +
   6.513 +static int xenbus_dev_remove(struct device *_dev)
   6.514 +{
   6.515 +	struct xenbus_device *dev = to_xenbus_device(_dev);
   6.516 +	struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
   6.517 +
   6.518 +        if(!drv->remove)
   6.519 +                return 0;
   6.520 +        return drv->remove(dev);
   6.521 +}
   6.522 +
   6.523 +int xenbus_register_driver(struct xenbus_driver *drv)
   6.524 +{
   6.525 +        int err = 0;
   6.526 +
   6.527 +        printk("%s> frontend driver %p %s\n", __FUNCTION__,
   6.528 +               drv, drv->name);
   6.529 +	drv->driver.name = drv->name;
   6.530 +	drv->driver.bus = &xenbus_type;
   6.531 +	drv->driver.owner = drv->owner;
   6.532 +	drv->driver.probe = xenbus_dev_probe;
   6.533 +	drv->driver.remove = xenbus_dev_remove;
   6.534 +
   6.535 +	err = driver_register(&drv->driver);
   6.536 +        if(err == 0 && xs_init_done && drv->connect){
   6.537 +                printk("%s> connecting driver %p %s\n", __FUNCTION__,
   6.538 +                       drv, drv->name);
   6.539 +                drv->connect(drv);
   6.540 +        }
   6.541 +        return err;
   6.542 +}
   6.543 +
   6.544 +void xenbus_unregister_driver(struct xenbus_driver *drv)
   6.545 +{
   6.546 +	driver_unregister(&drv->driver);
   6.547 +}
   6.548 +
   6.549 +static int xenbus_probe_device(const char *dir, const char *name)
   6.550 +{
   6.551 +	int err;
   6.552 +	struct xenbus_device *xendev;
   6.553 +	unsigned int xendev_n;
   6.554 +	long id;
   6.555 +	char *nodename, *devicetype;
   6.556 +	unsigned int devicetype_n;
   6.557 +
   6.558 +	dprintf("> dir=%s name=%s\n", dir, name);
   6.559 +	nodename = xenbus_path(dir, name);
   6.560 +	if (!nodename)
   6.561 +		return -ENOMEM;
   6.562 +
   6.563 +	devicetype = xenbus_read(nodename, XENBUS_DEVICE_TYPE, &devicetype_n);
   6.564 +	if (IS_ERR(devicetype)) {
   6.565 +		err = PTR_ERR(devicetype);
   6.566 +		goto free_nodename;
   6.567 +	}
   6.568 +
   6.569 +	err = xenbus_read_long(nodename, XENBUS_DEVICE_ID, &id);
   6.570 +	if (err == -ENOENT) {
   6.571 +		id = 0;
   6.572 +        } else if (err != 0) {
   6.573 +		goto free_devicetype;
   6.574 +        }
   6.575 +
   6.576 +	dprintf("> devicetype='%s' name='%s' id=%ld\n", devicetype, name, id);
   6.577 +        /* FIXME: This could be a rescan. Don't re-register existing devices. */
   6.578 +
   6.579 +	/* Add space for the strings. */
   6.580 +	xendev_n = sizeof(*xendev) + strlen(nodename) + strlen(devicetype) + 2;
   6.581 +	xendev = kmalloc(xendev_n, GFP_KERNEL);
   6.582 +	if (!xendev) {
   6.583 +		err = -ENOMEM;
   6.584 +		goto free_devicetype;
   6.585 +	}
   6.586 +	memset(xendev, 0, xendev_n);
   6.587 +
   6.588 +        snprintf(xendev->dev.bus_id, BUS_ID_SIZE, "%s-%s", devicetype, name);
   6.589 +	xendev->dev.bus = &xenbus_type;
   6.590 +
   6.591 +	xendev->id = id;
   6.592 +
   6.593 +	/* Copy the strings into the extra space. */
   6.594 +	xendev->nodename = (char *)(xendev + 1);
   6.595 +	strcpy(xendev->nodename, nodename);
   6.596 +	xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1;
   6.597 +	strcpy(xendev->devicetype, devicetype);
   6.598 +
   6.599 +	/* Register with generic device framework. */
   6.600 +        printk("XENBUS: Registering device %s\n", xendev->dev.bus_id);
   6.601 +	err = device_register(&xendev->dev);
   6.602 +        if (err) {
   6.603 +                printk("XENBUS: Registering device %s: error %i\n",
   6.604 +                       xendev->dev.bus_id, err);
   6.605 +        }
   6.606 +	if (err)
   6.607 +		kfree(xendev);
   6.608 +
   6.609 +free_devicetype:
   6.610 +	kfree(devicetype);
   6.611 +free_nodename:
   6.612 +	kfree(nodename);
   6.613 +	dprintf("< err=%i\n", err);
   6.614 +	return err;
   6.615 +}
   6.616 +
   6.617 +static int xenbus_probe_device_type(const char *dirpath, const char *typename)
   6.618 +{
   6.619 +	int err = 0;
   6.620 +	char **dir;
   6.621 +	char *path;
   6.622 +	unsigned int dir_n = 0;
   6.623 +	int i;
   6.624 +
   6.625 +	dprintf("> dirpath=%s typename=%s\n", dirpath, typename);
   6.626 +	path = xenbus_path(dirpath, typename);
   6.627 +	if (!path)
   6.628 +		return -ENOMEM;
   6.629 +
   6.630 +	dir = xs_directory(path, &dir_n);
   6.631 +	if (IS_ERR(dir)) {
   6.632 +		err = PTR_ERR(dir);
   6.633 +		goto out;
   6.634 +	}
   6.635 +
   6.636 +	for (i = 0; i < dir_n; i++) {
   6.637 +		err = xenbus_probe_device(path, dir[i]);
   6.638 +		if (err)
   6.639 +			break;
   6.640 +	}
   6.641 +	kfree(dir);
   6.642 +out:
   6.643 +	kfree(path);
   6.644 +	dprintf("< err=%i\n", err);
   6.645 +	return err;
   6.646 +}
   6.647 +
   6.648 +static int xenbus_probe_devices(const char *path)
   6.649 +{
   6.650 +	int err = 0;
   6.651 +	char **dir;
   6.652 +	unsigned int i, dir_n;
   6.653 +
   6.654 +	dprintf("> path=%s\n", path);
   6.655 +	down(&xs_lock);
   6.656 +	dir = xs_directory(path, &dir_n);
   6.657 +	if (IS_ERR(dir)) {
   6.658 +		err = PTR_ERR(dir);
   6.659 +		goto unlock;
   6.660 +	}
   6.661 +	for (i = 0; i < dir_n; i++) {
   6.662 +		err = xenbus_probe_device_type(path, dir[i]);
   6.663 +		if (err)
   6.664 +			break;
   6.665 +	}
   6.666 +	kfree(dir);
   6.667 +unlock:
   6.668 +	up(&xs_lock);
   6.669 +	dprintf("< err=%i\n", err);
   6.670 +	return err;
   6.671 +}
   6.672 +
   6.673 +
   6.674 +static int xenbus_probe_backend(const char *dir, const char *name)
   6.675 +{
   6.676 +	int err = 0;
   6.677 +	struct xenbus_device *xendev = NULL;
   6.678 +	unsigned int xendev_n = 0;
   6.679 +	char *nodename = NULL, *devicetype = NULL;
   6.680 +	unsigned int devicetype_n = 0;
   6.681 +
   6.682 +	dprintf("> dir=%s name=%s\n", dir, name);
   6.683 +	nodename = xenbus_path(dir, name);
   6.684 +	if (!nodename)
   6.685 +		return -ENOMEM;
   6.686 +
   6.687 +	devicetype = xenbus_read(nodename, XENBUS_DEVICE_TYPE, &devicetype_n);
   6.688 +	if (IS_ERR(devicetype)) {
   6.689 +		err = PTR_ERR(devicetype);
   6.690 +		goto free_nodename;
   6.691 +	}
   6.692 +
   6.693 +	dprintf("> devicetype='%s'\n", devicetype);
   6.694 +        /* FIXME: This could be a rescan. Don't re-register existing devices. */
   6.695 +
   6.696 +	/* Add space for the strings. */
   6.697 +	xendev_n = sizeof(*xendev) + strlen(nodename) + strlen(devicetype) + 2;
   6.698 +	xendev = kmalloc(xendev_n, GFP_KERNEL);
   6.699 +	if (!xendev) {
   6.700 +		err = -ENOMEM;
   6.701 +		goto free_devicetype;
   6.702 +	}
   6.703 +	memset(xendev, 0, xendev_n);
   6.704 +
   6.705 +        snprintf(xendev->dev.bus_id, BUS_ID_SIZE, "%s", devicetype);
   6.706 +	xendev->dev.bus = &xenback_type;
   6.707 +
   6.708 +	/* Copy the strings into the extra space. */
   6.709 +	xendev->nodename = (char *)(xendev + 1);
   6.710 +	strcpy(xendev->nodename, nodename);
   6.711 +	xendev->devicetype = xendev->nodename + strlen(xendev->nodename) + 1;
   6.712 +	strcpy(xendev->devicetype, devicetype);
   6.713 +
   6.714 +	/* Register with generic device framework. */
   6.715 +        printk("XENBUS: Registering backend %s\n", xendev->dev.bus_id);
   6.716 +	err = device_register(&xendev->dev);
   6.717 +        if (err) {
   6.718 +                printk("XENBUS: Registering device %s: error %i\n",
   6.719 +                       xendev->dev.bus_id, err);
   6.720 +        }
   6.721 +	if (err)
   6.722 +		kfree(xendev);
   6.723 +
   6.724 +free_devicetype:
   6.725 +	kfree(devicetype);
   6.726 +free_nodename:
   6.727 +	kfree(nodename);
   6.728 +	dprintf("< err=%i\n", err);
   6.729 +	return err;
   6.730 +}
   6.731 +
   6.732 +static int xenbus_probe_backends(const char *path)
   6.733 +{
   6.734 +	int err = 0;
   6.735 +	char **dir;
   6.736 +	unsigned int i, dir_n;
   6.737 +
   6.738 +	dprintf("> path=%s\n", path);
   6.739 +	down(&xs_lock);
   6.740 +	dir = xs_directory(path, &dir_n);
   6.741 +	if (IS_ERR(dir)) {
   6.742 +		err = PTR_ERR(dir);
   6.743 +		goto unlock;
   6.744 +	}
   6.745 +	for (i = 0; i < dir_n; i++) {
   6.746 +		err = xenbus_probe_backend(path, dir[i]);
   6.747 +		if (err)
   6.748 +			break;
   6.749 +	}
   6.750 +	kfree(dir);
   6.751 +unlock:
   6.752 +	up(&xs_lock);
   6.753 +	dprintf("< err=%i\n", err);
   6.754 +	return err;
   6.755 +}
   6.756 +
   6.757 +int xenbus_register_backend(struct xenbus_driver *drv)
   6.758 +{
   6.759 +        int err = 0;
   6.760 +
   6.761 +        printk("%s> backend driver %p %s\n", __FUNCTION__,
   6.762 +               drv, drv->name);
   6.763 +	drv->driver.name = drv->name;
   6.764 +	drv->driver.bus = &xenback_type;
   6.765 +	drv->driver.owner = drv->owner;
   6.766 +	drv->driver.probe = xenbus_dev_probe;
   6.767 +	drv->driver.remove = xenbus_dev_remove;
   6.768 +
   6.769 +	err = driver_register(&drv->driver);
   6.770 +        if(err == 0 && xs_init_done && drv->connect){
   6.771 +                printk("%s> connecting driver %p %s\n", __FUNCTION__,
   6.772 +                       drv, drv->name);
   6.773 +                drv->connect(drv);
   6.774 +        }
   6.775 +        return err;
   6.776 +}
   6.777 +
   6.778 +void xenbus_unregister_backend(struct xenbus_driver *drv)
   6.779 +{
   6.780 +	driver_unregister(&drv->driver);
   6.781 +}
   6.782 +
   6.783 +int xenbus_for_each_backend(struct xenbus_driver * start, void * data,
   6.784 +                            int (*fn)(struct xenbus_driver *, void *))
   6.785 +{
   6.786 +        struct xenbus_for_drv for_data = {
   6.787 +                .fn = fn,
   6.788 +                .data = data,
   6.789 +        };
   6.790 +        if(!fn)
   6.791 +                return -EINVAL;
   6.792 +        return bus_for_each_drv(&xenback_type,
   6.793 +                                (start ? &start->driver: NULL),
   6.794 +                                &for_data, for_drv);
   6.795 +}
   6.796 +
   6.797 +static void test_callback(struct xenbus_watch *w, const char *node)
   6.798 +{
   6.799 +	printk("test_callback: got watch hit for %s\n", node);
   6.800 +}
   6.801 +
   6.802 +static void test_watch(void)
   6.803 +{
   6.804 +        static int init_done = 0;
   6.805 +	static struct xenbus_watch watch = { .node = "/", 
   6.806 +					     .priority = 0, 
   6.807 +					     .callback = test_callback };
   6.808 +
   6.809 +        if(init_done) return;
   6.810 +	printk("registering watch %lX = %i\n",
   6.811 +               (long)&watch,
   6.812 +	       register_xenbus_watch(&watch));
   6.813 +        init_done = 1;
   6.814 +}
   6.815 +
   6.816 +static int xenbus_driver_connect(struct xenbus_driver *drv, void *data)
   6.817 +{
   6.818 +        printk("%s> driver %p %s\n", __FUNCTION__, drv, drv->name);
   6.819 +        if (drv->connect) {
   6.820 +                printk("%s> connecting driver %p %s\n", __FUNCTION__,
   6.821 +                       drv, drv->name);
   6.822 +                drv->connect(drv);
   6.823 +        }
   6.824 +        printk("%s< driver %p %s\n", __FUNCTION__, drv, drv->name);
   6.825 +        return 0;
   6.826 +}
   6.827 +
   6.828 +int do_xenbus_connect(void *unused)
   6.829 +{
   6.830 +	int err = 0;
   6.831 +
   6.832 +        printk("%s> xs_init_done=%d\n", __FUNCTION__, xs_init_done);
   6.833 +	if (xs_init_done)
   6.834 +                goto exit;
   6.835 +        /* Initialize xenstore comms unless already done. */
   6.836 +        printk("store_evtchn = %i\n", xen_start_info.store_evtchn);
   6.837 +        err = xs_init();
   6.838 +        if (err) {
   6.839 +                printk("XENBUS: Error initializing xenstore comms:"
   6.840 +                       " %i\n", err);
   6.841 +                goto exit;
   6.842 +        }
   6.843 +        xs_init_done = 1;
   6.844 +
   6.845 +        /* Notify drivers that xenstore has connected. */
   6.846 +        test_watch();
   6.847 +        printk("%s> connect drivers...\n", __FUNCTION__);
   6.848 +        xenbus_for_each_drv(NULL, NULL, xenbus_driver_connect);
   6.849 +        printk("%s> connect backends...\n", __FUNCTION__);
   6.850 +        xenbus_for_each_backend(NULL, NULL, xenbus_driver_connect);
   6.851 +        
   6.852 +        /* Enumerate devices and backends in xenstore. */
   6.853 +	xenbus_probe_devices(XENBUS_DEVICE_DIR);
   6.854 +        xenbus_probe_backends(XENBUS_BACKEND_DIR);
   6.855 +
   6.856 +exit:
   6.857 +        printk("%s< err=%d\n", __FUNCTION__, err);
   6.858 +        return err;
   6.859 +}
   6.860 +
   6.861 +static int __init xenbus_probe_init(void)
   6.862 +{
   6.863 +        bus_register(&xenbus_type);
   6.864 +        bus_register(&xenback_type);
   6.865 +
   6.866 +	if (!xen_start_info.store_evtchn)
   6.867 +		return 0;
   6.868 +
   6.869 +	do_xenbus_connect(NULL);
   6.870 +	return 0;
   6.871 +}
   6.872 +
   6.873 +postcore_initcall(xenbus_probe_init);
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Tue Jun 28 15:44:49 2005 +0000
     7.3 @@ -0,0 +1,488 @@
     7.4 +/******************************************************************************
     7.5 + * xenbus_xs.c
     7.6 + *
     7.7 + * This is the kernel equivalent of the "xs" library.  We don't need everything
     7.8 + * and we use xenbus_comms to communication.
     7.9 + *
    7.10 + * Copyright (C) 2005 Rusty Russell, IBM Corporation
    7.11 + * 
    7.12 + * This file may be distributed separately from the Linux kernel, or
    7.13 + * incorporated into other software packages, subject to the following license:
    7.14 + * 
    7.15 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    7.16 + * of this source file (the "Software"), to deal in the Software without
    7.17 + * restriction, including without limitation the rights to use, copy, modify,
    7.18 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    7.19 + * and to permit persons to whom the Software is furnished to do so, subject to
    7.20 + * the following conditions:
    7.21 + * 
    7.22 + * The above copyright notice and this permission notice shall be included in
    7.23 + * all copies or substantial portions of the Software.
    7.24 + * 
    7.25 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    7.26 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    7.27 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    7.28 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    7.29 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    7.30 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    7.31 + * IN THE SOFTWARE.
    7.32 + */
    7.33 +
    7.34 +#include <linux/errno.h>
    7.35 +#include <linux/types.h>
    7.36 +#include "xenstore/xenstored.h"
    7.37 +#include <linux/uio.h>
    7.38 +#include <linux/kernel.h>
    7.39 +#include <linux/string.h>
    7.40 +#include <linux/err.h>
    7.41 +#include <linux/slab.h>
    7.42 +#include <linux/fcntl.h>
    7.43 +#include <linux/kthread.h>
    7.44 +#include <asm-xen/xenbus.h>
    7.45 +#include "xenbus_comms.h"
    7.46 +
    7.47 +#define streq(a, b) (strcmp((a), (b)) == 0)
    7.48 +
    7.49 +static void *xs_in, *xs_out;
    7.50 +static LIST_HEAD(watches);
    7.51 +static DECLARE_MUTEX(watches_lock);
    7.52 +DECLARE_MUTEX(xs_lock);
    7.53 +
    7.54 +static int get_error(const char *errorstring)
    7.55 +{
    7.56 +	unsigned int i;
    7.57 +
    7.58 +	for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
    7.59 +		if (i == ARRAY_SIZE(xsd_errors) - 1) {
    7.60 +			printk(KERN_WARNING "XENBUS xen store gave: unknown error %s",
    7.61 +			       errorstring);
    7.62 +			return EINVAL;
    7.63 +		}
    7.64 +	}
    7.65 +	return xsd_errors[i].errnum;
    7.66 +}
    7.67 +
    7.68 +static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
    7.69 +{
    7.70 +	struct xsd_sockmsg msg;
    7.71 +	void *ret;
    7.72 +	int err;
    7.73 +
    7.74 +	err = xb_read(xs_in, &msg, sizeof(msg));
    7.75 +	if (err)
    7.76 +		return ERR_PTR(err);
    7.77 +
    7.78 +	ret = kmalloc(msg.len + 1, GFP_KERNEL);
    7.79 +	if (!ret)
    7.80 +		return ERR_PTR(-ENOMEM);
    7.81 +
    7.82 +	err = xb_read(xs_in, ret, msg.len);
    7.83 +	if (err) {
    7.84 +		kfree(ret);
    7.85 +		return ERR_PTR(err);
    7.86 +	}
    7.87 +	((char*)ret)[msg.len] = '\0';
    7.88 +
    7.89 +	*type = msg.type;
    7.90 +	if (len)
    7.91 +		*len = msg.len;
    7.92 +	return ret;
    7.93 +}
    7.94 +
    7.95 +/* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
    7.96 +static void *xs_talkv(enum xsd_sockmsg_type type,
    7.97 +		      const struct kvec *iovec,
    7.98 +		      unsigned int num_vecs,
    7.99 +		      unsigned int *len)
   7.100 +{
   7.101 +	struct xsd_sockmsg msg;
   7.102 +	void *ret = NULL;
   7.103 +	unsigned int i;
   7.104 +	int err;
   7.105 +
   7.106 +	WARN_ON(down_trylock(&xs_lock) == 0);
   7.107 +
   7.108 +	msg.type = type;
   7.109 +	msg.len = 0;
   7.110 +	for (i = 0; i < num_vecs; i++)
   7.111 +		msg.len += iovec[i].iov_len;
   7.112 +
   7.113 +	err = xb_write(xs_out, &msg, sizeof(msg));
   7.114 +	if (err)
   7.115 +		return ERR_PTR(err);
   7.116 +
   7.117 +	for (i = 0; i < num_vecs; i++) {
   7.118 +		err = xb_write(xs_out, iovec[i].iov_base, iovec[i].iov_len);;
   7.119 +		if (err)
   7.120 +			return ERR_PTR(err);
   7.121 +	}
   7.122 +
   7.123 +	/* Watches can have fired before reply comes: daemon detects
   7.124 +	 * and re-transmits, so we can ignore this. */
   7.125 +	do {
   7.126 +		kfree(ret);
   7.127 +		ret = read_reply(&msg.type, len);
   7.128 +		if (IS_ERR(ret))
   7.129 +			return ret;
   7.130 +	} while (msg.type == XS_WATCH_EVENT);
   7.131 +
   7.132 +	if (msg.type == XS_ERROR) {
   7.133 +		err = get_error(ret);
   7.134 +		kfree(ret);
   7.135 +		return ERR_PTR(-err);
   7.136 +	}
   7.137 +
   7.138 +	BUG_ON(msg.type != type);
   7.139 +	return ret;
   7.140 +}
   7.141 +
   7.142 +/* Simplified version of xs_talkv: single message. */
   7.143 +static void *xs_single(enum xsd_sockmsg_type type,
   7.144 +		       const char *string, unsigned int *len)
   7.145 +{
   7.146 +	struct kvec iovec;
   7.147 +
   7.148 +	iovec.iov_base = (void *)string;
   7.149 +	iovec.iov_len = strlen(string) + 1;
   7.150 +	return xs_talkv(type, &iovec, 1, len);
   7.151 +}
   7.152 +
   7.153 +/* Many commands only need an ack, don't care what it says. */
   7.154 +static int xs_error(char *reply)
   7.155 +{
   7.156 +	if (IS_ERR(reply))
   7.157 +		return PTR_ERR(reply);
   7.158 +	kfree(reply);
   7.159 +	return 0;
   7.160 +}
   7.161 +
   7.162 +static unsigned int count_strings(const char *strings, unsigned int len)
   7.163 +{
   7.164 +	unsigned int num;
   7.165 +	const char *p;
   7.166 +
   7.167 +	for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
   7.168 +		num++;
   7.169 +
   7.170 +	return num;
   7.171 +}
   7.172 +
   7.173 +char **xs_directory(const char *path, unsigned int *num)
   7.174 +{
   7.175 +	char *strings, *p, **ret;
   7.176 +	unsigned int len;
   7.177 +
   7.178 +	strings = xs_single(XS_DIRECTORY, path, &len);
   7.179 +	if (IS_ERR(strings))
   7.180 +		return (char **)strings;
   7.181 +
   7.182 +	/* Count the strings. */
   7.183 +	*num = count_strings(strings, len);
   7.184 +
   7.185 +	/* Transfer to one big alloc for easy freeing. */
   7.186 +	ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
   7.187 +	if (!ret) {
   7.188 +		kfree(strings);
   7.189 +		return ERR_PTR(-ENOMEM);
   7.190 +	}
   7.191 +	memcpy(&ret[*num], strings, len);
   7.192 +	kfree(strings);
   7.193 +
   7.194 +	strings = (char *)&ret[*num];
   7.195 +	for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
   7.196 +		ret[(*num)++] = p;
   7.197 +	return ret;
   7.198 +}
   7.199 +
   7.200 +/* Check if a path exists. Return 1 if it does. */
   7.201 +int xs_exists(const char *path)
   7.202 +{
   7.203 +        char **dir;
   7.204 +        int dir_n;
   7.205 +
   7.206 +        dir = xs_directory(path, &dir_n);
   7.207 +        if(IS_ERR(dir))
   7.208 +                return 0;
   7.209 +        kfree(dir);
   7.210 +        return 1;
   7.211 +}
   7.212 +
   7.213 +/* Make a directory, creating dirs on the path to it if necessary.
   7.214 + * Return 0 on success, error code otherwise.
   7.215 + */
   7.216 +int xs_mkdirs(const char *path)
   7.217 +{
   7.218 +        int err = 0;
   7.219 +        char s[strlen(path) + 1], *p = s;
   7.220 +
   7.221 +        if(xs_exists(path))
   7.222 +                goto out;
   7.223 +        strcpy(p, path);
   7.224 +        if(*p == '/')
   7.225 +                p++;
   7.226 +        for( ; ; ){
   7.227 +                p = strchr(p, '/');
   7.228 +                if(p)
   7.229 +                        *p = '\0';
   7.230 +                if(!xs_exists(s)){
   7.231 +                        err = xs_mkdir(s);
   7.232 +                        if(err)
   7.233 +                                goto out;
   7.234 +                        
   7.235 +                }
   7.236 +                if(!p)
   7.237 +                        break;
   7.238 +                *p++ = '/';
   7.239 +       }
   7.240 +  out:
   7.241 +        return err;
   7.242 +}
   7.243 +
   7.244 +
   7.245 +/* Get the value of a single file.
   7.246 + * Returns a kmalloced value: call free() on it after use.
   7.247 + * len indicates length in bytes.
   7.248 + */
   7.249 +void *xs_read(const char *path, unsigned int *len)
   7.250 +{
   7.251 +	return xs_single(XS_READ, path, len);
   7.252 +}
   7.253 +
   7.254 +/* Write the value of a single file.
   7.255 + * Returns -err on failure.  createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
   7.256 + */
   7.257 +int xs_write(const char *path,
   7.258 +	      const void *data, unsigned int len, int createflags)
   7.259 +{
   7.260 +	const char *flags;
   7.261 +	struct kvec iovec[3];
   7.262 +
   7.263 +	/* Format: Flags (as string), path, data. */
   7.264 +	if (createflags == 0)
   7.265 +		flags = XS_WRITE_NONE;
   7.266 +	else if (createflags == O_CREAT)
   7.267 +		flags = XS_WRITE_CREATE;
   7.268 +	else if (createflags == (O_CREAT|O_EXCL))
   7.269 +		flags = XS_WRITE_CREATE_EXCL;
   7.270 +	else
   7.271 +		return -EINVAL;
   7.272 +
   7.273 +	iovec[0].iov_base = (void *)path;
   7.274 +	iovec[0].iov_len = strlen(path) + 1;
   7.275 +	iovec[1].iov_base = (void *)flags;
   7.276 +	iovec[1].iov_len = strlen(flags) + 1;
   7.277 +	iovec[2].iov_base = (void *)data;
   7.278 +	iovec[2].iov_len = len;
   7.279 +
   7.280 +	return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
   7.281 +}
   7.282 +
   7.283 +/* Create a new directory. */
   7.284 +int xs_mkdir(const char *path)
   7.285 +{
   7.286 +	return xs_error(xs_single(XS_MKDIR, path, NULL));
   7.287 +}
   7.288 +
   7.289 +/* Destroy a file or directory (directories must be empty). */
   7.290 +int xs_rm(const char *path)
   7.291 +{
   7.292 +	return xs_error(xs_single(XS_RM, path, NULL));
   7.293 +}
   7.294 +
   7.295 +/* Start a transaction: changes by others will not be seen during this
   7.296 + * transaction, and changes will not be visible to others until end.
   7.297 + * Transaction only applies to the given subtree.
   7.298 + * You can only have one transaction at any time.
   7.299 + */
   7.300 +int xs_transaction_start(const char *subtree)
   7.301 +{
   7.302 +	return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
   7.303 +}
   7.304 +
   7.305 +/* End a transaction.
   7.306 + * If abandon is true, transaction is discarded instead of committed.
   7.307 + */
   7.308 +int xs_transaction_end(int abort)
   7.309 +{
   7.310 +	char abortstr[2];
   7.311 +
   7.312 +	if (abort)
   7.313 +		strcpy(abortstr, "F");
   7.314 +	else
   7.315 +		strcpy(abortstr, "T");
   7.316 +	return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
   7.317 +}
   7.318 +
   7.319 +char *xs_get_domain_path(domid_t domid)
   7.320 +{
   7.321 +	char domid_str[32];
   7.322 +
   7.323 +	sprintf(domid_str, "%u", domid);
   7.324 +	return xs_single(XS_GETDOMAINPATH, domid_str, NULL);
   7.325 +}
   7.326 +
   7.327 +static int xs_watch(const char *path, const char *token, unsigned int priority)
   7.328 +{
   7.329 +	char prio[32];
   7.330 +	struct kvec iov[3];
   7.331 +
   7.332 +	sprintf(prio, "%u", priority);
   7.333 +	iov[0].iov_base = (void *)path;
   7.334 +	iov[0].iov_len = strlen(path) + 1;
   7.335 +	iov[1].iov_base = (void *)token;
   7.336 +	iov[1].iov_len = strlen(token) + 1;
   7.337 +	iov[2].iov_base = prio;
   7.338 +	iov[2].iov_len = strlen(prio) + 1;
   7.339 +
   7.340 +	return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
   7.341 +}
   7.342 +
   7.343 +static char *xs_read_watch(char **token)
   7.344 +{
   7.345 +	enum xsd_sockmsg_type type;
   7.346 +	char *ret;
   7.347 +
   7.348 +	ret = read_reply(&type, NULL);
   7.349 +	if (IS_ERR(ret))
   7.350 +		return ret;
   7.351 +
   7.352 +	BUG_ON(type != XS_WATCH_EVENT);
   7.353 +	*token = ret + strlen(ret) + 1;
   7.354 +	return ret;
   7.355 +}
   7.356 +
   7.357 +static int xs_acknowledge_watch(const char *token)
   7.358 +{
   7.359 +	return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
   7.360 +}
   7.361 +
   7.362 +static int xs_unwatch(const char *path, const char *token)
   7.363 +{
   7.364 +	struct kvec iov[2];
   7.365 +
   7.366 +	iov[0].iov_base = (char *)path;
   7.367 +	iov[0].iov_len = strlen(path) + 1;
   7.368 +	iov[1].iov_base = (char *)token;
   7.369 +	iov[1].iov_len = strlen(token) + 1;
   7.370 +
   7.371 +	return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
   7.372 +}
   7.373 +
   7.374 +/* A little paranoia: we don't just trust token. */
   7.375 +static struct xenbus_watch *find_watch(const char *token)
   7.376 +{
   7.377 +	struct xenbus_watch *i, *cmp;
   7.378 +
   7.379 +	cmp = (void *)simple_strtoul(token, NULL, 16);
   7.380 +
   7.381 +	list_for_each_entry(i, &watches, list)
   7.382 +		if (i == cmp)
   7.383 +			return i;
   7.384 +	return NULL;
   7.385 +}
   7.386 +
   7.387 +/* Register callback to watch this node. */
   7.388 +int register_xenbus_watch(struct xenbus_watch *watch)
   7.389 +{
   7.390 +	/* Pointer in ascii is the token. */
   7.391 +	char token[sizeof(watch) * 2 + 1];
   7.392 +	int err;
   7.393 +
   7.394 +	sprintf(token, "%lX", (long)watch);
   7.395 +	down(&watches_lock);
   7.396 +	BUG_ON(find_watch(token));
   7.397 +
   7.398 +	down(&xs_lock);
   7.399 +	err = xs_watch(watch->node, token, watch->priority);
   7.400 +	up(&xs_lock);
   7.401 +	if (!err)
   7.402 +		list_add(&watch->list, &watches);
   7.403 +	up(&watches_lock);
   7.404 +	return err;
   7.405 +}
   7.406 +
   7.407 +void unregister_xenbus_watch(struct xenbus_watch *watch)
   7.408 +{
   7.409 +	char token[sizeof(watch) * 2 + 1];
   7.410 +	int err;
   7.411 +
   7.412 +	sprintf(token, "%lX", (long)watch);
   7.413 +	down(&watches_lock);
   7.414 +	BUG_ON(!find_watch(token));
   7.415 +
   7.416 +	down(&xs_lock);
   7.417 +	err = xs_unwatch(watch->node, token);
   7.418 +	up(&xs_lock);
   7.419 +	list_del(&watch->list);
   7.420 +	up(&watches_lock);
   7.421 +
   7.422 +	if (err)
   7.423 +		printk(KERN_WARNING "XENBUS Failed to release watch %s: %i\n",
   7.424 +		       watch->node, err);
   7.425 +}
   7.426 +
   7.427 +static int watch_thread(void *unused)
   7.428 +{
   7.429 +	int err;
   7.430 +	unsigned long mtu;
   7.431 +
   7.432 +	set_current_state(TASK_INTERRUPTIBLE);
   7.433 +	schedule_timeout(HZ*10);
   7.434 +	printk("watch_thread, doing read\n");
   7.435 +	down(&xs_lock);
   7.436 +	err = xenbus_read_long("", "mtu", &mtu);
   7.437 +	up(&xs_lock);
   7.438 +	printk("fake field read: %i (%lu)\n", err, mtu);
   7.439 +
   7.440 +	for (;;) {
   7.441 +		char *token;
   7.442 +		char *node = NULL;
   7.443 +
   7.444 +		wait_event(xb_waitq, xs_input_avail(xs_in));
   7.445 +
   7.446 +		/* If this is a spurious wakeup caused by someone
   7.447 +		 * doing an op, they'll hold the lock and the buffer
   7.448 +		 * will be empty by the time we get there.		 
   7.449 +		 */
   7.450 +		down(&xs_lock);
   7.451 +		if (xs_input_avail(xs_in))
   7.452 +			node = xs_read_watch(&token);
   7.453 +		/* Release lock before calling callback. */
   7.454 +		up(&xs_lock);
   7.455 +		if (node && !IS_ERR(node)) {
   7.456 +			struct xenbus_watch *w;
   7.457 +			int err;
   7.458 +
   7.459 +			down(&watches_lock);
   7.460 +			w = find_watch(token);
   7.461 +			BUG_ON(!w);
   7.462 +			w->callback(w, node);
   7.463 +			up(&watches_lock);
   7.464 +			down(&xs_lock);
   7.465 +			err = xs_acknowledge_watch(token);
   7.466 +			if (err)
   7.467 +				printk(KERN_WARNING
   7.468 +				       "XENBUS acknowledge %s failed %i\n",
   7.469 +				       node, err);
   7.470 +			up(&xs_lock);
   7.471 +			kfree(node);
   7.472 +		} else
   7.473 +			printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
   7.474 +			       PTR_ERR(node));
   7.475 +	}
   7.476 +}
   7.477 +
   7.478 +int xs_init(void)
   7.479 +{
   7.480 +	int err;
   7.481 +	struct task_struct *watcher;
   7.482 +
   7.483 +	err = xb_init_comms(&xs_in, &xs_out);
   7.484 +	if (err)
   7.485 +		return err;
   7.486 +	
   7.487 +	watcher = kthread_run(watch_thread, NULL, "kxbwatch");
   7.488 +	if (IS_ERR(watcher))
   7.489 +		return PTR_ERR(watcher);
   7.490 +	return 0;
   7.491 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/linux-2.6.11-xen-sparse/include/asm-xen/xenbus.h	Tue Jun 28 15:44:49 2005 +0000
     8.3 @@ -0,0 +1,143 @@
     8.4 +#ifndef _ASM_XEN_XENBUS_H
     8.5 +#define _ASM_XEN_XENBUS_H
     8.6 +/******************************************************************************
     8.7 + * xenbus.h
     8.8 + *
     8.9 + * Talks to Xen Store to figure out what devices we have.
    8.10 + *
    8.11 + * Copyright (C) 2005 Rusty Russell, IBM Corporation
    8.12 + * 
    8.13 + * This file may be distributed separately from the Linux kernel, or
    8.14 + * incorporated into other software packages, subject to the following license:
    8.15 + * 
    8.16 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    8.17 + * of this source file (the "Software"), to deal in the Software without
    8.18 + * restriction, including without limitation the rights to use, copy, modify,
    8.19 + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
    8.20 + * and to permit persons to whom the Software is furnished to do so, subject to
    8.21 + * the following conditions:
    8.22 + * 
    8.23 + * The above copyright notice and this permission notice shall be included in
    8.24 + * all copies or substantial portions of the Software.
    8.25 + * 
    8.26 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    8.27 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    8.28 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    8.29 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    8.30 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    8.31 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
    8.32 + * IN THE SOFTWARE.
    8.33 + */
    8.34 +#include <linux/device.h>
    8.35 +#include <asm/semaphore.h>
    8.36 +
    8.37 +/* A xenbus device. */
    8.38 +struct xenbus_device {
    8.39 +	char *devicetype;
    8.40 +	char *subtype;
    8.41 +	char *nodename;
    8.42 +	int id;
    8.43 +	struct device dev;
    8.44 +};
    8.45 +
    8.46 +static inline struct xenbus_device *to_xenbus_device(struct device *dev)
    8.47 +{
    8.48 +	return container_of(dev, struct xenbus_device, dev);
    8.49 +}
    8.50 +
    8.51 +struct xenbus_device_id
    8.52 +{
    8.53 +	/* .../device/<device_type>/<identifier> */
    8.54 +	char devicetype[32]; 	/* General class of device. */
    8.55 +	char subtype[32];	/* Contents of "subtype" for this device */
    8.56 +};
    8.57 +
    8.58 +/* A xenbus driver. */
    8.59 +struct xenbus_driver {
    8.60 +	char *name;
    8.61 +	struct module *owner;
    8.62 +	const struct xenbus_device_id *ids;
    8.63 +        /* Called when xenstore is connected. */
    8.64 +        int  (*connect) (struct xenbus_driver * drv);
    8.65 +
    8.66 +	int  (*probe)    (struct xenbus_device * dev, const struct xenbus_device_id * id);
    8.67 +        int  (*remove)   (struct xenbus_device * dev);
    8.68 +        int  (*configure)(struct xenbus_device * dev);
    8.69 +
    8.70 +	struct device_driver driver;
    8.71 +};
    8.72 +
    8.73 +struct xenbus_evtchn {
    8.74 +        unsigned long dom1;
    8.75 +        unsigned long port1;
    8.76 +        unsigned long dom2;
    8.77 +        unsigned long port2;
    8.78 +};
    8.79 +
    8.80 +static inline struct xenbus_driver *to_xenbus_driver(struct device_driver *drv)
    8.81 +{
    8.82 +	return container_of(drv, struct xenbus_driver, driver);
    8.83 +}
    8.84 +
    8.85 +int xenbus_register_driver(struct xenbus_driver *drv);
    8.86 +void xenbus_unregister_driver(struct xenbus_driver *drv);
    8.87 +
    8.88 +int xenbus_register_backend(struct xenbus_driver *drv);
    8.89 +void xenbus_unregister_backend(struct xenbus_driver *drv);
    8.90 +
    8.91 +/* Iterator over xenbus devices (frontend). */
    8.92 +int xenbus_for_each_dev(struct xenbus_device * start, void * data,
    8.93 +                        int (*fn)(struct xenbus_device *, void *));
    8.94 +
    8.95 +/* Iterator over xenbus drivers (frontend). */
    8.96 +int xenbus_for_each_drv(struct xenbus_driver * start, void * data,
    8.97 +                        int (*fn)(struct xenbus_driver *, void *));
    8.98 +
    8.99 +/* Iterator over xenbus drivers (backend). */
   8.100 +int xenbus_for_each_backend(struct xenbus_driver * start, void * data,
   8.101 +                            int (*fn)(struct xenbus_driver *, void *));
   8.102 +
   8.103 +/* Caller must hold this lock to call these functions. */
   8.104 +extern struct semaphore xs_lock;
   8.105 +
   8.106 +char **xs_directory(const char *path, unsigned int *num);
   8.107 +void *xs_read(const char *path, unsigned int *len);
   8.108 +int xs_write(const char *path,
   8.109 +	     const void *data, unsigned int len, int createflags);
   8.110 +int xs_mkdir(const char *path);
   8.111 +int xs_exists(const char *path);
   8.112 +int xs_mkdirs(const char *path);
   8.113 +int xs_rm(const char *path);
   8.114 +int xs_transaction_start(const char *subtree);
   8.115 +int xs_transaction_end(int abort);
   8.116 +char *xs_get_domain_path(domid_t domid);
   8.117 +
   8.118 +/* Register callback to watch this node. */
   8.119 +struct xenbus_watch
   8.120 +{
   8.121 +	struct list_head list;
   8.122 +	char *node;
   8.123 +	unsigned int priority;
   8.124 +	void (*callback)(struct xenbus_watch *, const char *node);
   8.125 +};
   8.126 +
   8.127 +int register_xenbus_watch(struct xenbus_watch *watch);
   8.128 +void unregister_xenbus_watch(struct xenbus_watch *watch);
   8.129 +
   8.130 +char *xenbus_path(const char *dir, const char *name);
   8.131 +char *xenbus_read(const char *dir, const char *name, unsigned int *data_n);
   8.132 +int xenbus_write(const char *dir, const char *name,
   8.133 +                 const char *data, int data_n);
   8.134 +
   8.135 +int xenbus_read_string(const char *dir, const char *name, char **val);
   8.136 +int xenbus_write_string(const char *dir, const char *name, const char *val);
   8.137 +int xenbus_read_ulong(const char *dir, const char *name, unsigned long *val);
   8.138 +int xenbus_write_ulong(const char *dir, const char *name, unsigned long val);
   8.139 +int xenbus_read_long(const char *dir, const char *name, long *val);
   8.140 +int xenbus_write_long(const char *dir, const char *name, long val);
   8.141 +int xenbus_read_mac(const char *dir, const char *name, unsigned char mac[6]);
   8.142 +int xenbus_write_mac(const char *dir, const char *name, const unsigned char mac[6]);
   8.143 +int xenbus_read_evtchn(const char *dir, const char *name, struct xenbus_evtchn *evtchn);
   8.144 +int xenbus_message(const char *dir, const char *val, ...);
   8.145 +
   8.146 +#endif /* _ASM_XEN_XENBUS_H */
     9.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Jun 28 15:35:45 2005 +0000
     9.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Jun 28 15:44:49 2005 +0000
     9.3 @@ -565,10 +565,10 @@ class XendDomainInfo:
     9.4          self.create_channel()
     9.5          self.image.createImage()
     9.6          self.exportToDB()
     9.7 -        #if self.store_channel:
     9.8 -        #    self.db.introduceDomain(self.id,
     9.9 -        #                            self.store_mfn,
    9.10 -        #                            self.store_channel)
    9.11 +        if self.store_channel:
    9.12 +            self.db.introduceDomain(self.id,
    9.13 +                                    self.store_mfn,
    9.14 +                                    self.store_channel)
    9.15  
    9.16      def delete(self):
    9.17          """Delete the vm's db.
    9.18 @@ -615,11 +615,11 @@ class XendDomainInfo:
    9.19                  self.store_channel = None
    9.20              except:
    9.21                  pass
    9.22 -            #try:
    9.23 -            #    self.db.releaseDomain(self.id)
    9.24 -            #except Exception, ex:
    9.25 -            #    log.warning("error in domain release on xenstore: %s", ex)
    9.26 -            #    pass
    9.27 +            try:
    9.28 +                self.db.releaseDomain(self.id)
    9.29 +            except Exception, ex:
    9.30 +                log.warning("error in domain release on xenstore: %s", ex)
    9.31 +                pass
    9.32          if self.image:
    9.33              try:
    9.34                  self.image.destroy()