direct-io.hg

changeset 8284:7557f0b4098c

Merge in the newer Xenbus implementation from Linux to the Mini-OS. The new
version compiles and starts up, but I'm not really sure how to test the new
xenbus implementation.

* Added unbind_evtchn
* Copied parts of the Linux spinlock implementation to make the changes to
xenbus compared to Linux smaller. Also added a dummy rwsem implementation.
* Updated the xenbus-files

Signed-off-by: Simon Kagstrom <simon.kagstrom@bth.se>
author kaf24@firebug.cl.cam.ac.uk
date Thu Dec 08 15:24:02 2005 +0100 (2005-12-08)
parents 5f7398785e02
children 89a223305611
files extras/mini-os/events.c extras/mini-os/include/events.h extras/mini-os/include/os.h extras/mini-os/include/semaphore.h extras/mini-os/include/spinlock.h extras/mini-os/include/wait.h extras/mini-os/include/xenbus.h extras/mini-os/include/xmalloc.h extras/mini-os/kernel.c extras/mini-os/xenbus/xenbus_comms.c extras/mini-os/xenbus/xenbus_comms.h extras/mini-os/xenbus/xenbus_xs.c
line diff
     1.1 --- a/extras/mini-os/events.c	Thu Dec 08 15:21:36 2005 +0100
     1.2 +++ b/extras/mini-os/events.c	Thu Dec 08 15:24:02 2005 +0100
     1.3 @@ -56,7 +56,7 @@ int do_event(u32 port, struct pt_regs *r
     1.4  
     1.5  }
     1.6  
     1.7 -void bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
     1.8 +int bind_evtchn( u32 port, void (*handler)(int, struct pt_regs *) )
     1.9  {
    1.10   	if(ev_actions[port].handler)
    1.11          printk("WARN: Handler for port %d already registered, replacing\n",
    1.12 @@ -67,6 +67,16 @@ void bind_evtchn( u32 port, void (*handl
    1.13   
    1.14  	/* Finally unmask the port */
    1.15  	unmask_evtchn(port);
    1.16 +
    1.17 +	return port;
    1.18 +}
    1.19 +
    1.20 +void unbind_evtchn( u32 port )
    1.21 +{
    1.22 +	if (!ev_actions[port].handler)
    1.23 +		printk("WARN: No handler for port %d when unbinding\n", port);
    1.24 +	ev_actions[port].handler = NULL;
    1.25 +	ev_actions[port].status |= EVS_DISABLED;
    1.26  }
    1.27  
    1.28  int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) )
    1.29 @@ -90,6 +100,10 @@ out:
    1.30  	return ret;
    1.31  }
    1.32  
    1.33 +void unbind_virq( u32 port )
    1.34 +{
    1.35 +	unbind_evtchn(port);
    1.36 +}
    1.37  
    1.38  
    1.39  /*
     2.1 --- a/extras/mini-os/include/events.h	Thu Dec 08 15:21:36 2005 +0100
     2.2 +++ b/extras/mini-os/include/events.h	Thu Dec 08 15:24:02 2005 +0100
     2.3 @@ -40,10 +40,12 @@ typedef struct _ev_action_t {
     2.4  /* prototypes */
     2.5  int do_event(u32 port, struct pt_regs *regs);
     2.6  int bind_virq( u32 virq, void (*handler)(int, struct pt_regs *) );
     2.7 -void bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
     2.8 +int bind_evtchn( u32 virq, void (*handler)(int, struct pt_regs *) );
     2.9 +void unbind_evtchn( u32 port );
    2.10  void init_events(void);
    2.11 +void unbind_virq( u32 port );
    2.12  
    2.13 -static inline int notify_via_evtchn(int port)
    2.14 +static inline int notify_remote_via_evtchn(int port)
    2.15  {
    2.16      evtchn_op_t op;
    2.17      op.cmd = EVTCHNOP_send;
     3.1 --- a/extras/mini-os/include/os.h	Thu Dec 08 15:21:36 2005 +0100
     3.2 +++ b/extras/mini-os/include/os.h	Thu Dec 08 15:24:02 2005 +0100
     3.3 @@ -131,9 +131,11 @@ do {									\
     3.4  #if defined(__i386__)
     3.5  #define mb()    __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
     3.6  #define rmb()   __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
     3.7 +#define wmb()	__asm__ __volatile__ ("": : :"memory")
     3.8  #elif defined(__x86_64__)
     3.9  #define mb()    __asm__ __volatile__ ("mfence":::"memory")
    3.10  #define rmb()   __asm__ __volatile__ ("lfence":::"memory")
    3.11 +#define wmb()	__asm__ __volatile__ ("sfence" ::: "memory") /* From CONFIG_UNORDERED_IO (linux) */
    3.12  #endif
    3.13  
    3.14  
     4.1 --- a/extras/mini-os/include/semaphore.h	Thu Dec 08 15:21:36 2005 +0100
     4.2 +++ b/extras/mini-os/include/semaphore.h	Thu Dec 08 15:24:02 2005 +0100
     4.3 @@ -2,6 +2,7 @@
     4.4  #define _SEMAPHORE_H_
     4.5  
     4.6  #include <wait.h>
     4.7 +#include <spinlock.h>
     4.8  
     4.9  /*
    4.10   * Implementation of semaphore in Mini-os is simple, because 
    4.11 @@ -14,6 +15,15 @@ struct semaphore
    4.12  	struct wait_queue_head wait;
    4.13  };
    4.14  
    4.15 +/*
    4.16 + * the semaphore definition
    4.17 + */
    4.18 +struct rw_semaphore {
    4.19 +	signed long		count;
    4.20 +	spinlock_t		wait_lock;
    4.21 +	struct list_head	wait_list;
    4.22 +	int			debug;
    4.23 +};
    4.24  
    4.25  #define __SEMAPHORE_INITIALIZER(name, n)                            \
    4.26  {                                                                   \
    4.27 @@ -31,6 +41,12 @@ struct semaphore
    4.28  
    4.29  #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
    4.30  
    4.31 +static inline void init_MUTEX(struct semaphore *sem)
    4.32 +{
    4.33 +  sem->count = 1;
    4.34 +  init_waitqueue_head(&sem->wait);
    4.35 +}
    4.36 +
    4.37  static void inline down(struct semaphore *sem)
    4.38  {
    4.39      wait_event(sem->wait, sem->count > 0);
    4.40 @@ -43,4 +59,27 @@ static void inline up(struct semaphore *
    4.41      wake_up(&sem->wait);
    4.42  }
    4.43  
    4.44 +/* FIXME! Thre read/write semaphores are unimplemented! */
    4.45 +static inline void init_rwsem(struct rw_semaphore *sem)
    4.46 +{
    4.47 +  sem->count = 1;
    4.48 +}
    4.49 +
    4.50 +static inline void down_read(struct rw_semaphore *sem)
    4.51 +{
    4.52 +}
    4.53 +
    4.54 +
    4.55 +static inline void up_read(struct rw_semaphore *sem)
    4.56 +{
    4.57 +}
    4.58 +
    4.59 +static inline void up_write(struct rw_semaphore *sem)
    4.60 +{
    4.61 +}
    4.62 +
    4.63 +static inline void down_write(struct rw_semaphore *sem)
    4.64 +{
    4.65 +}
    4.66 +
    4.67  #endif /* _SEMAPHORE_H */
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/extras/mini-os/include/spinlock.h	Thu Dec 08 15:24:02 2005 +0100
     5.3 @@ -0,0 +1,121 @@
     5.4 +#ifndef __ASM_SPINLOCK_H
     5.5 +#define __ASM_SPINLOCK_H
     5.6 +
     5.7 +#include <lib.h>
     5.8 +
     5.9 +/*
    5.10 + * Your basic SMP spinlocks, allowing only a single CPU anywhere
    5.11 + */
    5.12 +
    5.13 +typedef struct {
    5.14 +	volatile unsigned int slock;
    5.15 +} spinlock_t;
    5.16 +
    5.17 +#define SPINLOCK_MAGIC	0xdead4ead
    5.18 +
    5.19 +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 }
    5.20 +
    5.21 +#define spin_lock_init(x)	do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
    5.22 +
    5.23 +/*
    5.24 + * Simple spin lock operations.  There are two variants, one clears IRQ's
    5.25 + * on the local processor, one does not.
    5.26 + *
    5.27 + * We make no fairness assumptions. They have a cost.
    5.28 + */
    5.29 +
    5.30 +#define spin_is_locked(x)	(*(volatile signed char *)(&(x)->slock) <= 0)
    5.31 +#define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
    5.32 +
    5.33 +#define spin_lock_string \
    5.34 +        "1:\n" \
    5.35 +	LOCK \
    5.36 +	"decb %0\n\t" \
    5.37 +	"jns 3f\n" \
    5.38 +	"2:\t" \
    5.39 +	"rep;nop\n\t" \
    5.40 +	"cmpb $0,%0\n\t" \
    5.41 +	"jle 2b\n\t" \
    5.42 +	"jmp 1b\n" \
    5.43 +	"3:\n\t"
    5.44 +
    5.45 +#define spin_lock_string_flags \
    5.46 +        "1:\n" \
    5.47 +	LOCK \
    5.48 +	"decb %0\n\t" \
    5.49 +	"jns 4f\n\t" \
    5.50 +	"2:\t" \
    5.51 +	"testl $0x200, %1\n\t" \
    5.52 +	"jz 3f\n\t" \
    5.53 +	"#sti\n\t" \
    5.54 +	"3:\t" \
    5.55 +	"rep;nop\n\t" \
    5.56 +	"cmpb $0, %0\n\t" \
    5.57 +	"jle 3b\n\t" \
    5.58 +	"#cli\n\t" \
    5.59 +	"jmp 1b\n" \
    5.60 +	"4:\n\t"
    5.61 +
    5.62 +/*
    5.63 + * This works. Despite all the confusion.
    5.64 + * (except on PPro SMP or if we are using OOSTORE)
    5.65 + * (PPro errata 66, 92)
    5.66 + */
    5.67 +
    5.68 +#define spin_unlock_string \
    5.69 +	"xchgb %b0, %1" \
    5.70 +		:"=q" (oldval), "=m" (lock->slock) \
    5.71 +		:"0" (oldval) : "memory"
    5.72 +
    5.73 +static inline void _raw_spin_unlock(spinlock_t *lock)
    5.74 +{
    5.75 +	char oldval = 1;
    5.76 +	__asm__ __volatile__(
    5.77 +		spin_unlock_string
    5.78 +	);
    5.79 +}
    5.80 +
    5.81 +static inline int _raw_spin_trylock(spinlock_t *lock)
    5.82 +{
    5.83 +	char oldval;
    5.84 +	__asm__ __volatile__(
    5.85 +		"xchgb %b0,%1\n"
    5.86 +		:"=q" (oldval), "=m" (lock->slock)
    5.87 +		:"0" (0) : "memory");
    5.88 +	return oldval > 0;
    5.89 +}
    5.90 +
    5.91 +static inline void _raw_spin_lock(spinlock_t *lock)
    5.92 +{
    5.93 +	__asm__ __volatile__(
    5.94 +		spin_lock_string
    5.95 +		:"=m" (lock->slock) : : "memory");
    5.96 +}
    5.97 +
    5.98 +static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
    5.99 +{
   5.100 +	__asm__ __volatile__(
   5.101 +		spin_lock_string_flags
   5.102 +		:"=m" (lock->slock) : "r" (flags) : "memory");
   5.103 +}
   5.104 +
   5.105 +#define _spin_trylock(lock)     ({_raw_spin_trylock(lock) ? \
   5.106 +                                1 : ({ 0;});})
   5.107 +
   5.108 +#define _spin_lock(lock)        \
   5.109 +do {                            \
   5.110 +        _raw_spin_lock(lock);   \
   5.111 +} while(0)
   5.112 +
   5.113 +#define _spin_unlock(lock)      \
   5.114 +do {                            \
   5.115 +        _raw_spin_unlock(lock); \
   5.116 +} while (0)
   5.117 +
   5.118 +
   5.119 +#define spin_lock(lock)       _spin_lock(lock)
   5.120 +#define spin_unlock(lock)       _spin_unlock(lock)
   5.121 +
   5.122 +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
   5.123 +
   5.124 +#endif
     6.1 --- a/extras/mini-os/include/wait.h	Thu Dec 08 15:21:36 2005 +0100
     6.2 +++ b/extras/mini-os/include/wait.h	Thu Dec 08 15:24:02 2005 +0100
     6.3 @@ -33,6 +33,10 @@ struct wait_queue name = {              
     6.4  }
     6.5  
     6.6  
     6.7 +static inline void init_waitqueue_head(struct wait_queue_head *h)
     6.8 +{
     6.9 +  INIT_LIST_HEAD(&h->thread_list);
    6.10 +}
    6.11  
    6.12  static inline void init_waitqueue_entry(struct wait_queue *q, struct thread *thread)
    6.13  {
     7.1 --- a/extras/mini-os/include/xenbus.h	Thu Dec 08 15:21:36 2005 +0100
     7.2 +++ b/extras/mini-os/include/xenbus.h	Thu Dec 08 15:24:02 2005 +0100
     7.3 @@ -4,6 +4,7 @@
     7.4   * Talks to Xen Store to figure out what devices we have.
     7.5   *
     7.6   * Copyright (C) 2005 Rusty Russell, IBM Corporation
     7.7 + * Copyright (C) 2005 XenSource Ltd.
     7.8   * 
     7.9   * This file may be distributed separately from the Linux kernel, or
    7.10   * incorporated into other software packages, subject to the following license:
    7.11 @@ -30,45 +31,98 @@
    7.12  #ifndef _ASM_XEN_XENBUS_H
    7.13  #define _ASM_XEN_XENBUS_H
    7.14  
    7.15 -
    7.16 -/* Caller must hold this lock to call these functions: it's also held
    7.17 - * across watch callbacks. */
    7.18 -// TODO
    7.19 -//extern struct semaphore xenbus_lock;
    7.20 -
    7.21 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
    7.22 -void *xenbus_read(const char *dir, const char *node, unsigned int *len);
    7.23 -int xenbus_write(const char *dir, const char *node,
    7.24 -		 const char *string, int createflags);
    7.25 -int xenbus_mkdir(const char *dir, const char *node);
    7.26 -int xenbus_exists(const char *dir, const char *node);
    7.27 -int xenbus_rm(const char *dir, const char *node);
    7.28 -int xenbus_transaction_start(const char *subtree);
    7.29 -int xenbus_transaction_end(int abort);
    7.30 -
    7.31 -/* Single read and scanf: returns -errno or num scanned if > 0. */
    7.32 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
    7.33 -	__attribute__((format(scanf, 3, 4)));
    7.34 -
    7.35 -/* Single printf and write: returns -errno or 0. */
    7.36 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
    7.37 -	__attribute__((format(printf, 3, 4)));
    7.38 -
    7.39 -/* Generic read function: NULL-terminated triples of name,
    7.40 - * sprintf-style type string, and pointer. Returns 0 or errno.*/
    7.41 -int xenbus_gather(const char *dir, ...);
    7.42 +#include <errno.h>
    7.43 +#include <xen/io/xenbus.h>
    7.44 +#include <xen/io/xs_wire.h>
    7.45  
    7.46  /* Register callback to watch this node. */
    7.47  struct xenbus_watch
    7.48  {
    7.49  	struct list_head list;
    7.50 -	char *node;
    7.51 -	void (*callback)(struct xenbus_watch *, const char *node);
    7.52 +
    7.53 +	/* Path being watched. */
    7.54 +	const char *node;
    7.55 +
    7.56 +	/* Callback (executed in a process context with no locks held). */
    7.57 +	void (*callback)(struct xenbus_watch *,
    7.58 +			 const char **vec, unsigned int len);
    7.59 +};
    7.60 +
    7.61 +
    7.62 +/* A xenbus device. */
    7.63 +struct xenbus_device {
    7.64 +	const char *devicetype;
    7.65 +	const char *nodename;
    7.66 +	const char *otherend;
    7.67 +	int otherend_id;
    7.68 +	struct xenbus_watch otherend_watch;
    7.69 +	int has_error;
    7.70 +	void *data;
    7.71 +};
    7.72 +
    7.73 +struct xenbus_device_id
    7.74 +{
    7.75 +	/* .../device/<device_type>/<identifier> */
    7.76 +	char devicetype[32]; 	/* General class of device. */
    7.77  };
    7.78  
    7.79 +/* A xenbus driver. */
    7.80 +struct xenbus_driver {
    7.81 +	char *name;
    7.82 +	struct module *owner;
    7.83 +	const struct xenbus_device_id *ids;
    7.84 +	int (*probe)(struct xenbus_device *dev,
    7.85 +		     const struct xenbus_device_id *id);
    7.86 +	void (*otherend_changed)(struct xenbus_device *dev,
    7.87 +				 XenbusState backend_state);
    7.88 +	int (*remove)(struct xenbus_device *dev);
    7.89 +	int (*suspend)(struct xenbus_device *dev);
    7.90 +	int (*resume)(struct xenbus_device *dev);
    7.91 +	int (*hotplug)(struct xenbus_device *, char **, int, char *, int);
    7.92 +	int (*read_otherend_details)(struct xenbus_device *dev);
    7.93 +};
    7.94 +
    7.95 +int xenbus_register_frontend(struct xenbus_driver *drv);
    7.96 +int xenbus_register_backend(struct xenbus_driver *drv);
    7.97 +void xenbus_unregister_driver(struct xenbus_driver *drv);
    7.98 +
    7.99 +struct xenbus_transaction;
   7.100 +
   7.101 +char **xenbus_directory(struct xenbus_transaction *t,
   7.102 +			const char *dir, const char *node, unsigned int *num);
   7.103 +void *xenbus_read(struct xenbus_transaction *t,
   7.104 +		  const char *dir, const char *node, unsigned int *len);
   7.105 +int xenbus_write(struct xenbus_transaction *t,
   7.106 +		 const char *dir, const char *node, const char *string);
   7.107 +int xenbus_mkdir(struct xenbus_transaction *t,
   7.108 +		 const char *dir, const char *node);
   7.109 +int xenbus_exists(struct xenbus_transaction *t,
   7.110 +		  const char *dir, const char *node);
   7.111 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node);
   7.112 +struct xenbus_transaction *xenbus_transaction_start(void);
   7.113 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort);
   7.114 +
   7.115 +/* Single read and scanf: returns -errno or num scanned if > 0. */
   7.116 +int xenbus_scanf(struct xenbus_transaction *t,
   7.117 +		 const char *dir, const char *node, const char *fmt, ...)
   7.118 +	__attribute__((format(scanf, 4, 5)));
   7.119 +
   7.120 +/* Single printf and write: returns -errno or 0. */
   7.121 +int xenbus_printf(struct xenbus_transaction *t,
   7.122 +		  const char *dir, const char *node, const char *fmt, ...)
   7.123 +	__attribute__((format(printf, 4, 5)));
   7.124 +
   7.125 +/* Generic read function: NULL-terminated triples of name,
   7.126 + * sprintf-style type string, and pointer. Returns 0 or errno.*/
   7.127 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...);
   7.128 +
   7.129  int register_xenbus_watch(struct xenbus_watch *watch);
   7.130  void unregister_xenbus_watch(struct xenbus_watch *watch);
   7.131 -void reregister_xenbus_watches(void);
   7.132 +void xs_suspend(void);
   7.133 +void xs_resume(void);
   7.134 +
   7.135 +/* Used by xenbus_dev to borrow kernel's store connection. */
   7.136 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
   7.137  
   7.138  /* Called from xen core code. */
   7.139  void xenbus_suspend(void);
   7.140 @@ -84,6 +138,87 @@ void xenbus_resume(void);
   7.141  
   7.142  #define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
   7.143  
   7.144 -int xs_init(void);
   7.145 +
   7.146 +/**
   7.147 + * Register a watch on the given path, using the given xenbus_watch structure
   7.148 + * for storage, and the given callback function as the callback.  Return 0 on
   7.149 + * success, or -errno on error.  On success, the given path will be saved as
   7.150 + * watch->node, and remains the caller's to free.  On error, watch->node will
   7.151 + * be NULL, the device will switch to XenbusStateClosing, and the error will
   7.152 + * be saved in the store.
   7.153 + */
   7.154 +int xenbus_watch_path(struct xenbus_device *dev, const char *path,
   7.155 +		      struct xenbus_watch *watch, 
   7.156 +		      void (*callback)(struct xenbus_watch *,
   7.157 +				       const char **, unsigned int));
   7.158 +
   7.159 +
   7.160 +/**
   7.161 + * Register a watch on the given path/path2, using the given xenbus_watch
   7.162 + * structure for storage, and the given callback function as the callback.
   7.163 + * Return 0 on success, or -errno on error.  On success, the watched path
   7.164 + * (path/path2) will be saved as watch->node, and becomes the caller's to
   7.165 + * kfree().  On error, watch->node will be NULL, so the caller has nothing to
   7.166 + * free, the device will switch to XenbusStateClosing, and the error will be
   7.167 + * saved in the store.
   7.168 + */
   7.169 +int xenbus_watch_path2(struct xenbus_device *dev, const char *path,
   7.170 +		       const char *path2, struct xenbus_watch *watch, 
   7.171 +		       void (*callback)(struct xenbus_watch *,
   7.172 +					const char **, unsigned int));
   7.173 +
   7.174 +
   7.175 +/**
   7.176 + * Advertise in the store a change of the given driver to the given new_state.
   7.177 + * Perform the change inside the given transaction xbt.  xbt may be NULL, in
   7.178 + * which case this is performed inside its own transaction.  Return 0 on
   7.179 + * success, or -errno on error.  On error, the device will switch to
   7.180 + * XenbusStateClosing, and the error will be saved in the store.
   7.181 + */
   7.182 +int xenbus_switch_state(struct xenbus_device *dev,
   7.183 +			struct xenbus_transaction *xbt,
   7.184 +			XenbusState new_state);
   7.185 +
   7.186 +
   7.187 +/**
   7.188 + * Grant access to the given ring_mfn to the peer of the given device.  Return
   7.189 + * 0 on success, or -errno on error.  On error, the device will switch to
   7.190 + * XenbusStateClosing, and the error will be saved in the store.
   7.191 + */
   7.192 +int xenbus_grant_ring(struct xenbus_device *dev, unsigned long ring_mfn);
   7.193 +
   7.194 +
   7.195 +/**
   7.196 + * Allocate an event channel for the given xenbus_device, assigning the newly
   7.197 + * created local port to *port.  Return 0 on success, or -errno on error.  On
   7.198 + * error, the device will switch to XenbusStateClosing, and the error will be
   7.199 + * saved in the store.
   7.200 + */
   7.201 +int xenbus_alloc_evtchn(struct xenbus_device *dev, int *port);
   7.202 +
   7.203 +
   7.204 +/**
   7.205 + * Return the state of the driver rooted at the given store path, or
   7.206 + * XenbusStateClosed if no state can be read.
   7.207 + */
   7.208 +XenbusState xenbus_read_driver_state(const char *path);
   7.209 +
   7.210 +
   7.211 +/***
   7.212 + * Report the given negative errno into the store, along with the given
   7.213 + * formatted message.
   7.214 + */
   7.215 +void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,
   7.216 +		      ...);
   7.217 +
   7.218 +
   7.219 +/***
   7.220 + * Equivalent to xenbus_dev_error(dev, err, fmt, args), followed by
   7.221 + * xenbus_switch_state(dev, NULL, XenbusStateClosing) to schedule an orderly
   7.222 + * closedown of this driver and its peer.
   7.223 + */
   7.224 +void xenbus_dev_fatal(struct xenbus_device *dev, int err, const char *fmt,
   7.225 +		      ...);
   7.226 +
   7.227  
   7.228  #endif /* _ASM_XEN_XENBUS_H */
     8.1 --- a/extras/mini-os/include/xmalloc.h	Thu Dec 08 15:21:36 2005 +0100
     8.2 +++ b/extras/mini-os/include/xmalloc.h	Thu Dec 08 15:24:02 2005 +0100
     8.3 @@ -7,6 +7,9 @@
     8.4  /* Allocate space for array of typed objects. */
     8.5  #define xmalloc_array(_type, _num) ((_type *)_xmalloc_array(sizeof(_type), __alignof__(_type), _num))
     8.6  
     8.7 +#define malloc(size) _xmalloc(size, 4)
     8.8 +#define free(ptr) xfree(ptr)
     8.9 +
    8.10  /* Free any of the above. */
    8.11  extern void xfree(const void *);
    8.12  
     9.1 --- a/extras/mini-os/kernel.c	Thu Dec 08 15:21:36 2005 +0100
     9.2 +++ b/extras/mini-os/kernel.c	Thu Dec 08 15:24:02 2005 +0100
     9.3 @@ -35,6 +35,7 @@
     9.4  #include <lib.h>
     9.5  #include <sched.h>
     9.6  #include <xenbus.h>
     9.7 +#include "xenbus/xenbus_comms.h"
     9.8  
     9.9  /*
    9.10   * Shared page for communicating with the hypervisor.
    10.1 --- a/extras/mini-os/xenbus/xenbus_comms.c	Thu Dec 08 15:21:36 2005 +0100
    10.2 +++ b/extras/mini-os/xenbus/xenbus_comms.c	Thu Dec 08 15:24:02 2005 +0100
    10.3 @@ -33,199 +33,152 @@
    10.4  #include <events.h>
    10.5  #include <os.h>
    10.6  #include <lib.h>
    10.7 -
    10.8 -
    10.9 -#ifdef XENBUS_COMMS_DEBUG
   10.10 -#define DEBUG(_f, _a...) \
   10.11 -    printk("MINI_OS(file=xenbus_comms.c, line=%d) " _f "\n", __LINE__, ## _a)
   10.12 -#else
   10.13 -#define DEBUG(_f, _a...)    ((void)0)
   10.14 -#endif
   10.15 +#include <xenbus.h>
   10.16 +#include "xenbus_comms.h"
   10.17  
   10.18 +static int xenbus_irq;
   10.19  
   10.20 -#define RINGBUF_DATASIZE ((PAGE_SIZE / 2) - sizeof(struct ringbuf_head))
   10.21 -struct ringbuf_head
   10.22 -{
   10.23 -	u32 write; /* Next place to write to */
   10.24 -	u32 read; /* Next place to read from */
   10.25 -	u8 flags;
   10.26 -	char buf[0];
   10.27 -} __attribute__((packed));
   10.28 +extern void xenbus_probe(void *);
   10.29 +extern int xenstored_ready;
   10.30  
   10.31  DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
   10.32  
   10.33 -static inline struct ringbuf_head *outbuf(void)
   10.34 +static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
   10.35  {
   10.36  	return mfn_to_virt(start_info.store_mfn);
   10.37  }
   10.38  
   10.39 -static inline struct ringbuf_head *inbuf(void)
   10.40 -{
   10.41 -	return (struct ringbuf_head *)((char *)mfn_to_virt(start_info.store_mfn) + PAGE_SIZE/2);
   10.42 -}
   10.43 -
   10.44  static void wake_waiting(int port, struct pt_regs *regs)
   10.45  {
   10.46  	wake_up(&xb_waitq);
   10.47  }
   10.48  
   10.49 -static int check_buffer(const struct ringbuf_head *h)
   10.50 -{
   10.51 -	return (h->write < RINGBUF_DATASIZE && h->read < RINGBUF_DATASIZE);
   10.52 -}
   10.53 -
   10.54 -/* We can't fill last byte: would look like empty buffer. */
   10.55 -static void *get_output_chunk(const struct ringbuf_head *h,
   10.56 -			      void *buf, u32 *len)
   10.57 +static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
   10.58  {
   10.59 -	u32 read_mark;
   10.60 -
   10.61 -	if (h->read == 0)
   10.62 -		read_mark = RINGBUF_DATASIZE - 1;
   10.63 -	else
   10.64 -		read_mark = h->read - 1;
   10.65 -
   10.66 -	/* Here to the end of buffer, unless they haven't read some out. */
   10.67 -	*len = RINGBUF_DATASIZE - h->write;
   10.68 -	if (read_mark >= h->write)
   10.69 -		*len = read_mark - h->write;
   10.70 -	return (void *)((char *)buf + h->write);
   10.71 +	return ((prod - cons) <= XENSTORE_RING_SIZE);
   10.72  }
   10.73  
   10.74 -static const void *get_input_chunk(const struct ringbuf_head *h,
   10.75 -				   const void *buf, u32 *len)
   10.76 +static void *get_output_chunk(XENSTORE_RING_IDX cons,
   10.77 +			      XENSTORE_RING_IDX prod,
   10.78 +			      char *buf, uint32_t *len)
   10.79  {
   10.80 -	/* Here to the end of buffer, unless they haven't written some. */
   10.81 -	*len = RINGBUF_DATASIZE - h->read;
   10.82 -	if (h->write >= h->read)
   10.83 -		*len = h->write - h->read;
   10.84 -	return (void *)((char *)buf + h->read);
   10.85 +	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
   10.86 +	if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
   10.87 +		*len = XENSTORE_RING_SIZE - (prod - cons);
   10.88 +	return buf + MASK_XENSTORE_IDX(prod);
   10.89  }
   10.90  
   10.91 -static void update_output_chunk(struct ringbuf_head *h, u32 len)
   10.92 -{
   10.93 -	h->write += len;
   10.94 -	if (h->write == RINGBUF_DATASIZE)
   10.95 -		h->write = 0;
   10.96 -}
   10.97 -
   10.98 -static void update_input_chunk(struct ringbuf_head *h, u32 len)
   10.99 +static const void *get_input_chunk(XENSTORE_RING_IDX cons,
  10.100 +				   XENSTORE_RING_IDX prod,
  10.101 +				   const char *buf, uint32_t *len)
  10.102  {
  10.103 -	h->read += len;
  10.104 -	if (h->read == RINGBUF_DATASIZE)
  10.105 -		h->read = 0;
  10.106 -}
  10.107 -
  10.108 -static int output_avail(struct ringbuf_head *out)
  10.109 -{
  10.110 -	unsigned int avail;
  10.111 -
  10.112 -	get_output_chunk(out, out->buf, &avail);
  10.113 -	return avail != 0;
  10.114 +	*len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
  10.115 +	if ((prod - cons) < *len)
  10.116 +		*len = prod - cons;
  10.117 +	return buf + MASK_XENSTORE_IDX(cons);
  10.118  }
  10.119  
  10.120  int xb_write(const void *data, unsigned len)
  10.121  {
  10.122 -	struct ringbuf_head h;
  10.123 -	struct ringbuf_head *out = outbuf();
  10.124 +	struct xenstore_domain_interface *intf = xenstore_domain_interface();
  10.125 +	XENSTORE_RING_IDX cons, prod;
  10.126  
  10.127 -	do {
  10.128 +	while (len != 0) {
  10.129  		void *dst;
  10.130  		unsigned int avail;
  10.131  
  10.132 -		wait_event(xb_waitq, output_avail(out));
  10.133 +		wait_event(xb_waitq, (intf->req_prod - intf->req_cons) !=
  10.134 +			   XENSTORE_RING_SIZE);
  10.135  
  10.136 -		/* Read, then check: not that we don't trust store.
  10.137 -		 * Hell, some of my best friends are daemons.  But,
  10.138 -		 * in this post-911 world... */
  10.139 -		h = *out;
  10.140 +		/* Read indexes, then verify. */
  10.141 +		cons = intf->req_cons;
  10.142 +		prod = intf->req_prod;
  10.143  		mb();
  10.144 -		if (!check_buffer(&h)) {
  10.145 -			return -1; /* ETERRORIST! */
  10.146 -		}
  10.147 +		if (!check_indexes(cons, prod))
  10.148 +			return -EIO;
  10.149  
  10.150 -		dst = get_output_chunk(&h, out->buf, &avail);
  10.151 +		dst = get_output_chunk(cons, prod, intf->req, &avail);
  10.152 +		if (avail == 0)
  10.153 +			continue;
  10.154  		if (avail > len)
  10.155  			avail = len;
  10.156 +
  10.157  		memcpy(dst, data, avail);
  10.158 -		data = (void *)((char *)data + avail);
  10.159 +		data = (void*) ( (unsigned long)data + avail );
  10.160  		len -= avail;
  10.161 -		update_output_chunk(out, avail);
  10.162 -		notify_via_evtchn(start_info.store_evtchn);
  10.163 -	} while (len != 0);
  10.164 +
  10.165 +		/* Other side must not see new header until data is there. */
  10.166 +		wmb();
  10.167 +		intf->req_prod += avail;
  10.168 +
  10.169 +		/* This implies mb() before other side sees interrupt. */
  10.170 +		notify_remote_via_evtchn(start_info.store_evtchn);
  10.171 +	}
  10.172  
  10.173  	return 0;
  10.174  }
  10.175  
  10.176 -int xs_input_avail(void)
  10.177 -{
  10.178 -	unsigned int avail;
  10.179 -	struct ringbuf_head *in = inbuf();
  10.180 -
  10.181 -	get_input_chunk(in, in->buf, &avail);
  10.182 -	return avail != 0;
  10.183 -}
  10.184 -
  10.185  int xb_read(void *data, unsigned len)
  10.186  {
  10.187 -	struct ringbuf_head h;
  10.188 -	struct ringbuf_head *in = inbuf();
  10.189 -	int was_full;
  10.190 +	struct xenstore_domain_interface *intf = xenstore_domain_interface();
  10.191 +	XENSTORE_RING_IDX cons, prod;
  10.192  
  10.193  	while (len != 0) {
  10.194  		unsigned int avail;
  10.195  		const char *src;
  10.196  
  10.197 -		wait_event(xb_waitq, xs_input_avail());
  10.198 -		h = *in;
  10.199 +		wait_event(xb_waitq,
  10.200 +			   intf->rsp_cons != intf->rsp_prod);
  10.201 +
  10.202 +		/* Read indexes, then verify. */
  10.203 +		cons = intf->rsp_cons;
  10.204 +		prod = intf->rsp_prod;
  10.205  		mb();
  10.206 -		if (!check_buffer(&h)) {
  10.207 -			return -1;
  10.208 -		}
  10.209 +		if (!check_indexes(cons, prod))
  10.210 +			return -EIO;
  10.211  
  10.212 -		src = get_input_chunk(&h, in->buf, &avail);
  10.213 +		src = get_input_chunk(cons, prod, intf->rsp, &avail);
  10.214 +		if (avail == 0)
  10.215 +			continue;
  10.216  		if (avail > len)
  10.217  			avail = len;
  10.218 -		was_full = !output_avail(&h);
  10.219 +
  10.220 +		/* We must read header before we read data. */
  10.221 +		rmb();
  10.222  
  10.223  		memcpy(data, src, avail);
  10.224 -		data = (void *)((char *)data + avail);
  10.225 +		data = (void*) ( (unsigned long)data + avail );
  10.226  		len -= avail;
  10.227 -		update_input_chunk(in, avail);
  10.228 -		DEBUG("Finished read of %i bytes (%i to go)\n", avail, len);
  10.229 -		/* If it was full, tell them we've taken some. */
  10.230 -		if (was_full)
  10.231 -			notify_via_evtchn(start_info.store_evtchn);
  10.232 +
  10.233 +		/* Other side must not see free space until we've copied out */
  10.234 +		mb();
  10.235 +		intf->rsp_cons += avail;
  10.236 +
  10.237 +		printk("Finished read of %i bytes (%i to go)\n", avail, len);
  10.238 +
  10.239 +		/* Implies mb(): they will see new header. */
  10.240 +		notify_remote_via_evtchn(start_info.store_evtchn);
  10.241  	}
  10.242  
  10.243 -	/* If we left something, wake watch thread to deal with it. */
  10.244 -	if (xs_input_avail())
  10.245 -		wake_up(&xb_waitq);
  10.246 -
  10.247  	return 0;
  10.248  }
  10.249  
  10.250  /* Set up interrupt handler off store event channel. */
  10.251  int xb_init_comms(void)
  10.252  {
  10.253 -    printk("Init xenbus comms, store event channel %d\n", start_info.store_evtchn);
  10.254 -	if (!start_info.store_evtchn)
  10.255 -		return 0;
  10.256 -    printk("Binding virq\n");
  10.257 -	bind_evtchn(start_info.store_evtchn, &wake_waiting);
  10.258 +	int err;
  10.259 +
  10.260 +	if (xenbus_irq)
  10.261 +		unbind_evtchn(xenbus_irq);
  10.262  
  10.263 -	/* FIXME zero out page -- domain builder should probably do this*/
  10.264 -	memset(mfn_to_virt(start_info.store_mfn), 0, PAGE_SIZE);
  10.265 -    notify_via_evtchn(start_info.store_evtchn);
  10.266 +	err = bind_evtchn(
  10.267 +		start_info.store_evtchn, wake_waiting);
  10.268 +	if (err <= 0) {
  10.269 +		printk("XENBUS request irq failed %i\n", err);
  10.270 +		return err;
  10.271 +	}
  10.272 +
  10.273 +	xenbus_irq = err;
  10.274 +
  10.275  	return 0;
  10.276  }
  10.277 -
  10.278 -void xb_suspend_comms(void)
  10.279 -{
  10.280 -
  10.281 -	if (!start_info.store_evtchn)
  10.282 -		return;
  10.283 -
  10.284 -    // TODO
  10.285 -	//unbind_evtchn_from_irqhandler(xen_start_info.store_evtchn, &xb_waitq);
  10.286 -}
    11.1 --- a/extras/mini-os/xenbus/xenbus_comms.h	Thu Dec 08 15:21:36 2005 +0100
    11.2 +++ b/extras/mini-os/xenbus/xenbus_comms.h	Thu Dec 08 15:24:02 2005 +0100
    11.3 @@ -28,8 +28,8 @@
    11.4  #ifndef _XENBUS_COMMS_H
    11.5  #define _XENBUS_COMMS_H
    11.6  
    11.7 +int xs_init(void);
    11.8  int xb_init_comms(void);
    11.9 -void xb_suspend_comms(void);
   11.10  
   11.11  /* Low level routines. */
   11.12  int xb_write(const void *data, unsigned len);
    12.1 --- a/extras/mini-os/xenbus/xenbus_xs.c	Thu Dec 08 15:21:36 2005 +0100
    12.2 +++ b/extras/mini-os/xenbus/xenbus_xs.c	Thu Dec 08 15:24:02 2005 +0100
    12.3 @@ -39,15 +39,63 @@
    12.4  #include <wait.h>
    12.5  #include <sched.h>
    12.6  #include <semaphore.h>
    12.7 +#include <spinlock.h>
    12.8  #include <xen/io/xs_wire.h>
    12.9  #include "xenbus_comms.h"
   12.10  
   12.11  #define streq(a, b) (strcmp((a), (b)) == 0)
   12.12  
   12.13 -static char printf_buffer[4096];
   12.14 +struct xs_stored_msg {
   12.15 +	struct list_head list;
   12.16 +
   12.17 +	struct xsd_sockmsg hdr;
   12.18 +
   12.19 +	union {
   12.20 +		/* Queued replies. */
   12.21 +		struct {
   12.22 +			char *body;
   12.23 +		} reply;
   12.24 +
   12.25 +		/* Queued watch events. */
   12.26 +		struct {
   12.27 +			struct xenbus_watch *handle;
   12.28 +			char **vec;
   12.29 +			unsigned int vec_size;
   12.30 +		} watch;
   12.31 +	} u;
   12.32 +};
   12.33 +
   12.34 +struct xs_handle {
   12.35 +	/* A list of replies. Currently only one will ever be outstanding. */
   12.36 +	struct list_head reply_list;
   12.37 +	spinlock_t reply_lock;
   12.38 +	struct wait_queue_head reply_waitq;
   12.39 +
   12.40 +	/* One request at a time. */
   12.41 +	struct semaphore request_mutex;
   12.42 +
   12.43 +	/* Protect transactions against save/restore. */
   12.44 +	struct rw_semaphore suspend_mutex;
   12.45 +};
   12.46 +
   12.47 +static struct xs_handle xs_state;
   12.48 +
   12.49 +/* List of registered watches, and a lock to protect it. */
   12.50  static LIST_HEAD(watches);
   12.51 -//TODO
   12.52 -DECLARE_MUTEX(xenbus_lock);
   12.53 +static DEFINE_SPINLOCK(watches_lock);
   12.54 +
   12.55 +/* List of pending watch callback events, and a lock to protect it. */
   12.56 +static LIST_HEAD(watch_events);
   12.57 +static DEFINE_SPINLOCK(watch_events_lock);
   12.58 +
   12.59 +/*
   12.60 + * Details of the xenwatch callback kernel thread. The thread waits on the
   12.61 + * watch_events_waitq for work to do (queued on watch_events list). When it
   12.62 + * wakes up it acquires the xenwatch_mutex before reading the list and
   12.63 + * carrying out work.
   12.64 + */
   12.65 +/* static */ DECLARE_MUTEX(xenwatch_mutex);
   12.66 +static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);
   12.67  
   12.68  static int get_error(const char *errorstring)
   12.69  {
   12.70 @@ -65,47 +113,82 @@ static int get_error(const char *errorst
   12.71  
   12.72  static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
   12.73  {
   12.74 -	struct xsd_sockmsg msg;
   12.75 -	void *ret;
   12.76 -	int err;
   12.77 +	struct xs_stored_msg *msg;
   12.78 +	char *body;
   12.79 +
   12.80 +	spin_lock(&xs_state.reply_lock);
   12.81  
   12.82 -	err = xb_read(&msg, sizeof(msg));
   12.83 -	if (err)
   12.84 -		return ERR_PTR(err);
   12.85 -
   12.86 -	ret = xmalloc_array(char, msg.len + 1);
   12.87 -	if (!ret)
   12.88 -		return ERR_PTR(-ENOMEM);
   12.89 +	while (list_empty(&xs_state.reply_list)) {
   12.90 +		spin_unlock(&xs_state.reply_lock);
   12.91 +		wait_event(xs_state.reply_waitq,
   12.92 +			   !list_empty(&xs_state.reply_list));
   12.93 +		spin_lock(&xs_state.reply_lock);
   12.94 +	}
   12.95  
   12.96 -	err = xb_read(ret, msg.len);
   12.97 -	if (err) {
   12.98 -		xfree(ret);
   12.99 -		return ERR_PTR(err);
  12.100 -	}
  12.101 -	((char*)ret)[msg.len] = '\0';
  12.102 +	msg = list_entry(xs_state.reply_list.next,
  12.103 +			 struct xs_stored_msg, list);
  12.104 +	list_del(&msg->list);
  12.105 +
  12.106 +	spin_unlock(&xs_state.reply_lock);
  12.107  
  12.108 -	*type = msg.type;
  12.109 +	*type = msg->hdr.type;
  12.110  	if (len)
  12.111 -		*len = msg.len;
  12.112 -	return ret;
  12.113 +		*len = msg->hdr.len;
  12.114 +	body = msg->u.reply.body;
  12.115 +
  12.116 +	free(msg);
  12.117 +
  12.118 +	return body;
  12.119  }
  12.120  
  12.121  /* Emergency write. */
  12.122  void xenbus_debug_write(const char *str, unsigned int count)
  12.123  {
  12.124 -	struct xsd_sockmsg msg;
  12.125 +	struct xsd_sockmsg msg = { 0 };
  12.126  
  12.127  	msg.type = XS_DEBUG;
  12.128  	msg.len = sizeof("print") + count + 1;
  12.129  
  12.130 +	down(&xs_state.request_mutex);
  12.131  	xb_write(&msg, sizeof(msg));
  12.132  	xb_write("print", sizeof("print"));
  12.133  	xb_write(str, count);
  12.134  	xb_write("", 1);
  12.135 +	up(&xs_state.request_mutex);
  12.136 +}
  12.137 +
  12.138 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
  12.139 +{
  12.140 +	void *ret;
  12.141 +	struct xsd_sockmsg req_msg = *msg;
  12.142 +	int err;
  12.143 +
  12.144 +	if (req_msg.type == XS_TRANSACTION_START)
  12.145 +		down_read(&xs_state.suspend_mutex);
  12.146 +
  12.147 +	down(&xs_state.request_mutex);
  12.148 +
  12.149 +	err = xb_write(msg, sizeof(*msg) + msg->len);
  12.150 +	if (err) {
  12.151 +		msg->type = XS_ERROR;
  12.152 +		ret = ERR_PTR(err);
  12.153 +	} else {
  12.154 +		ret = read_reply(&msg->type, &msg->len);
  12.155 +	}
  12.156 +
  12.157 +	up(&xs_state.request_mutex);
  12.158 +
  12.159 +	if ((msg->type == XS_TRANSACTION_END) ||
  12.160 +	    ((req_msg.type == XS_TRANSACTION_START) &&
  12.161 +	     (msg->type == XS_ERROR)))
  12.162 +		up_read(&xs_state.suspend_mutex);
  12.163 +
  12.164 +	return ret;
  12.165  }
  12.166  
  12.167  /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
  12.168 -static void *xs_talkv(enum xsd_sockmsg_type type,
  12.169 +static void *xs_talkv(struct xenbus_transaction *t,
  12.170 +		      enum xsd_sockmsg_type type,
  12.171  		      const struct kvec *iovec,
  12.172  		      unsigned int num_vecs,
  12.173  		      unsigned int *len)
  12.174 @@ -115,51 +198,57 @@ static void *xs_talkv(enum xsd_sockmsg_t
  12.175  	unsigned int i;
  12.176  	int err;
  12.177  
  12.178 -	//WARN_ON(down_trylock(&xenbus_lock) == 0);
  12.179 -
  12.180 +	msg.tx_id = (u32)(unsigned long)t;
  12.181 +	msg.req_id = 0;
  12.182  	msg.type = type;
  12.183  	msg.len = 0;
  12.184  	for (i = 0; i < num_vecs; i++)
  12.185  		msg.len += iovec[i].iov_len;
  12.186  
  12.187 +	down(&xs_state.request_mutex);
  12.188 +
  12.189  	err = xb_write(&msg, sizeof(msg));
  12.190 -	if (err)
  12.191 +	if (err) {
  12.192 +		up(&xs_state.request_mutex);
  12.193  		return ERR_PTR(err);
  12.194 +	}
  12.195  
  12.196  	for (i = 0; i < num_vecs; i++) {
  12.197 -		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);
  12.198 -		if (err)
  12.199 +		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
  12.200 +		if (err) {
  12.201 +			up(&xs_state.request_mutex);
  12.202  			return ERR_PTR(err);
  12.203 +		}
  12.204  	}
  12.205  
  12.206 -	/* Watches can have fired before reply comes: daemon detects
  12.207 -	 * and re-transmits, so we can ignore this. */
  12.208 -	do {
  12.209 -		xfree(ret);
  12.210 -		ret = read_reply(&msg.type, len);
  12.211 -		if (IS_ERR(ret))
  12.212 -			return ret;
  12.213 -	} while (msg.type == XS_WATCH_EVENT);
  12.214 +	ret = read_reply(&msg.type, len);
  12.215 +
  12.216 +	up(&xs_state.request_mutex);
  12.217 +
  12.218 +	if (IS_ERR(ret))
  12.219 +		return ret;
  12.220  
  12.221  	if (msg.type == XS_ERROR) {
  12.222  		err = get_error(ret);
  12.223 -		xfree(ret);
  12.224 +		free(ret);
  12.225  		return ERR_PTR(-err);
  12.226  	}
  12.227  
  12.228 -	//BUG_ON(msg.type != type);
  12.229 +	//	BUG_ON(msg.type != type);
  12.230  	return ret;
  12.231  }
  12.232  
  12.233  /* Simplified version of xs_talkv: single message. */
  12.234 -static void *xs_single(enum xsd_sockmsg_type type,
  12.235 -		       const char *string, unsigned int *len)
  12.236 +static void *xs_single(struct xenbus_transaction *t,
  12.237 +		       enum xsd_sockmsg_type type,
  12.238 +		       const char *string,
  12.239 +		       unsigned int *len)
  12.240  {
  12.241  	struct kvec iovec;
  12.242  
  12.243  	iovec.iov_base = (void *)string;
  12.244  	iovec.iov_len = strlen(string) + 1;
  12.245 -	return xs_talkv(type, &iovec, 1, len);
  12.246 +	return xs_talkv(t, type, &iovec, 1, len);
  12.247  }
  12.248  
  12.249  /* Many commands only need an ack, don't care what it says. */
  12.250 @@ -167,7 +256,7 @@ static int xs_error(char *reply)
  12.251  {
  12.252  	if (IS_ERR(reply))
  12.253  		return PTR_ERR(reply);
  12.254 -	xfree(reply);
  12.255 +	free(reply);
  12.256  	return 0;
  12.257  }
  12.258  
  12.259 @@ -182,60 +271,76 @@ static unsigned int count_strings(const 
  12.260  	return num;
  12.261  }
  12.262  
  12.263 -/* Return the path to dir with /name appended. */ 
  12.264 +/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ 
  12.265  static char *join(const char *dir, const char *name)
  12.266  {
  12.267 -	static char buffer[4096];
  12.268 +	char *buffer;
  12.269  
  12.270 -	//BUG_ON(down_trylock(&xenbus_lock) == 0);
  12.271 -	/* XXX FIXME: might not be correct if name == "" */
  12.272 -	//BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
  12.273 +	buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1);
  12.274 +	if (buffer == NULL)
  12.275 +		return ERR_PTR(-ENOMEM);
  12.276  
  12.277  	strcpy(buffer, dir);
  12.278  	if (!streq(name, "")) {
  12.279  		strcat(buffer, "/");
  12.280  		strcat(buffer, name);
  12.281  	}
  12.282 +
  12.283  	return buffer;
  12.284  }
  12.285  
  12.286 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
  12.287 +static char **split(char *strings, unsigned int len, unsigned int *num)
  12.288  {
  12.289 -	char *strings, *p, **ret;
  12.290 -	unsigned int len;
  12.291 -
  12.292 -	strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
  12.293 -	if (IS_ERR(strings))
  12.294 -		return (char **)strings;
  12.295 +	char *p, **ret;
  12.296  
  12.297  	/* Count the strings. */
  12.298  	*num = count_strings(strings, len);
  12.299  
  12.300  	/* Transfer to one big alloc for easy freeing. */
  12.301 -	ret = (char **)xmalloc_array(char, *num * sizeof(char *) + len);
  12.302 +	ret = malloc(*num * sizeof(char *) + len);
  12.303  	if (!ret) {
  12.304 -		xfree(strings);
  12.305 +		free(strings);
  12.306  		return ERR_PTR(-ENOMEM);
  12.307  	}
  12.308  	memcpy(&ret[*num], strings, len);
  12.309 -	xfree(strings);
  12.310 +	free(strings);
  12.311  
  12.312  	strings = (char *)&ret[*num];
  12.313  	for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
  12.314  		ret[(*num)++] = p;
  12.315 +
  12.316  	return ret;
  12.317  }
  12.318  
  12.319 +char **xenbus_directory(struct xenbus_transaction *t,
  12.320 +			const char *dir, const char *node, unsigned int *num)
  12.321 +{
  12.322 +	char *strings, *path;
  12.323 +	unsigned int len;
  12.324 +
  12.325 +	path = join(dir, node);
  12.326 +	if (IS_ERR(path))
  12.327 +		return (char **)path;
  12.328 +
  12.329 +	strings = xs_single(t, XS_DIRECTORY, path, &len);
  12.330 +	free(path);
  12.331 +	if (IS_ERR(strings))
  12.332 +		return (char **)strings;
  12.333 +
  12.334 +	return split(strings, len, num);
  12.335 +}
  12.336 +
  12.337  /* Check if a path exists. Return 1 if it does. */
  12.338 -int xenbus_exists(const char *dir, const char *node)
  12.339 +int xenbus_exists(struct xenbus_transaction *t,
  12.340 +		  const char *dir, const char *node)
  12.341  {
  12.342  	char **d;
  12.343  	int dir_n;
  12.344  
  12.345 -	d = xenbus_directory(dir, node, &dir_n);
  12.346 +	d = xenbus_directory(t, dir, node, &dir_n);
  12.347  	if (IS_ERR(d))
  12.348  		return 0;
  12.349 -	xfree(d);
  12.350 +	free(d);
  12.351  	return 1;
  12.352  }
  12.353  
  12.354 @@ -243,92 +348,134 @@ int xenbus_exists(const char *dir, const
  12.355   * Returns a kmalloced value: call free() on it after use.
  12.356   * len indicates length in bytes.
  12.357   */
  12.358 -void *xenbus_read(const char *dir, const char *node, unsigned int *len)
  12.359 +void *xenbus_read(struct xenbus_transaction *t,
  12.360 +		  const char *dir, const char *node, unsigned int *len)
  12.361  {
  12.362 -	return xs_single(XS_READ, join(dir, node), len);
  12.363 +	char *path;
  12.364 +	void *ret;
  12.365 +
  12.366 +	path = join(dir, node);
  12.367 +	if (IS_ERR(path))
  12.368 +		return (void *)path;
  12.369 +
  12.370 +	ret = xs_single(t, XS_READ, path, len);
  12.371 +	free(path);
  12.372 +	return ret;
  12.373  }
  12.374  
  12.375  /* Write the value of a single file.
  12.376 - * Returns -err on failure.  createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
  12.377 + * Returns -err on failure.
  12.378   */
  12.379 -int xenbus_write(const char *dir, const char *node,
  12.380 -		 const char *string, int createflags)
  12.381 +int xenbus_write(struct xenbus_transaction *t,
  12.382 +		 const char *dir, const char *node, const char *string)
  12.383  {
  12.384 -	const char *flags, *path;
  12.385 -	struct kvec iovec[3];
  12.386 +	const char *path;
  12.387 +	struct kvec iovec[2];
  12.388 +	int ret;
  12.389  
  12.390  	path = join(dir, node);
  12.391 -	/* Format: Flags (as string), path, data. */
  12.392 -	if (createflags == 0)
  12.393 -		flags = XS_WRITE_NONE;
  12.394 -	else if (createflags == O_CREAT)
  12.395 -		flags = XS_WRITE_CREATE;
  12.396 -	else if (createflags == (O_CREAT|O_EXCL))
  12.397 -		flags = XS_WRITE_CREATE_EXCL;
  12.398 -	else
  12.399 -		return -EINVAL;
  12.400 +	if (IS_ERR(path))
  12.401 +		return PTR_ERR(path);
  12.402  
  12.403  	iovec[0].iov_base = (void *)path;
  12.404  	iovec[0].iov_len = strlen(path) + 1;
  12.405 -	iovec[1].iov_base = (void *)flags;
  12.406 -	iovec[1].iov_len = strlen(flags) + 1;
  12.407 -	iovec[2].iov_base = (void *)string;
  12.408 -	iovec[2].iov_len = strlen(string);
  12.409 +	iovec[1].iov_base = (void *)string;
  12.410 +	iovec[1].iov_len = strlen(string);
  12.411  
  12.412 -	return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
  12.413 +	ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
  12.414 +	free(path);
  12.415 +	return ret;
  12.416  }
  12.417  
  12.418  /* Create a new directory. */
  12.419 -int xenbus_mkdir(const char *dir, const char *node)
  12.420 +int xenbus_mkdir(struct xenbus_transaction *t,
  12.421 +		 const char *dir, const char *node)
  12.422  {
  12.423 -	return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
  12.424 +	char *path;
  12.425 +	int ret;
  12.426 +
  12.427 +	path = join(dir, node);
  12.428 +	if (IS_ERR(path))
  12.429 +		return PTR_ERR(path);
  12.430 +
  12.431 +	ret = xs_error(xs_single(t, XS_MKDIR, path, NULL));
  12.432 +	free(path);
  12.433 +	return ret;
  12.434  }
  12.435  
  12.436  /* Destroy a file or directory (directories must be empty). */
  12.437 -int xenbus_rm(const char *dir, const char *node)
  12.438 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
  12.439  {
  12.440 -	return xs_error(xs_single(XS_RM, join(dir, node), NULL));
  12.441 +	char *path;
  12.442 +	int ret;
  12.443 +
  12.444 +	path = join(dir, node);
  12.445 +	if (IS_ERR(path))
  12.446 +		return PTR_ERR(path);
  12.447 +
  12.448 +	ret = xs_error(xs_single(t, XS_RM, path, NULL));
  12.449 +	free(path);
  12.450 +	return ret;
  12.451  }
  12.452  
  12.453  /* Start a transaction: changes by others will not be seen during this
  12.454   * transaction, and changes will not be visible to others until end.
  12.455 - * Transaction only applies to the given subtree.
  12.456 - * You can only have one transaction at any time.
  12.457   */
  12.458 -int xenbus_transaction_start(const char *subtree)
  12.459 +struct xenbus_transaction *xenbus_transaction_start(void)
  12.460  {
  12.461 -	return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
  12.462 +	char *id_str;
  12.463 +	unsigned long id;
  12.464 +
  12.465 +	down_read(&xs_state.suspend_mutex);
  12.466 +
  12.467 +	id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL);
  12.468 +	if (IS_ERR(id_str)) {
  12.469 +		up_read(&xs_state.suspend_mutex);
  12.470 +		return (struct xenbus_transaction *)id_str;
  12.471 +	}
  12.472 +
  12.473 +	id = simple_strtoul(id_str, NULL, 0);
  12.474 +	free(id_str);
  12.475 +
  12.476 +	return (struct xenbus_transaction *)id;
  12.477  }
  12.478  
  12.479  /* End a transaction.
  12.480   * If abandon is true, transaction is discarded instead of committed.
  12.481   */
  12.482 -int xenbus_transaction_end(int abort)
  12.483 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort)
  12.484  {
  12.485  	char abortstr[2];
  12.486 +	int err;
  12.487  
  12.488  	if (abort)
  12.489  		strcpy(abortstr, "F");
  12.490  	else
  12.491  		strcpy(abortstr, "T");
  12.492 -	return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
  12.493 +
  12.494 +	err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
  12.495 +
  12.496 +	up_read(&xs_state.suspend_mutex);
  12.497 +
  12.498 +	return err;
  12.499  }
  12.500  
  12.501  /* Single read and scanf: returns -errno or num scanned. */
  12.502 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
  12.503 +int xenbus_scanf(struct xenbus_transaction *t,
  12.504 +		 const char *dir, const char *node, const char *fmt, ...)
  12.505  {
  12.506  	va_list ap;
  12.507  	int ret;
  12.508  	char *val;
  12.509  
  12.510 -	val = xenbus_read(dir, node, NULL);
  12.511 +	val = xenbus_read(t, dir, node, NULL);
  12.512  	if (IS_ERR(val))
  12.513  		return PTR_ERR(val);
  12.514  
  12.515  	va_start(ap, fmt);
  12.516  	ret = vsscanf(val, fmt, ap);
  12.517  	va_end(ap);
  12.518 -	xfree(val);
  12.519 +	free(val);
  12.520  	/* Distinctive errno. */
  12.521  	if (ret == 0)
  12.522  		return -ERANGE;
  12.523 @@ -336,23 +483,32 @@ int xenbus_scanf(const char *dir, const 
  12.524  }
  12.525  
  12.526  /* Single printf and write: returns -errno or 0. */
  12.527 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
  12.528 +int xenbus_printf(struct xenbus_transaction *t,
  12.529 +		  const char *dir, const char *node, const char *fmt, ...)
  12.530  {
  12.531  	va_list ap;
  12.532  	int ret;
  12.533 +#define PRINTF_BUFFER_SIZE 4096
  12.534 +	char *printf_buffer;
  12.535  
  12.536 -	//BUG_ON(down_trylock(&xenbus_lock) == 0);
  12.537 +	printf_buffer = malloc(PRINTF_BUFFER_SIZE);
  12.538 +	if (printf_buffer == NULL)
  12.539 +		return -ENOMEM;
  12.540 +
  12.541  	va_start(ap, fmt);
  12.542 -	ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
  12.543 +	ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
  12.544  	va_end(ap);
  12.545  
  12.546 -	//BUG_ON(ret > sizeof(printf_buffer)-1);
  12.547 -	return xenbus_write(dir, node, printf_buffer, O_CREAT);
  12.548 +	//	BUG_ON(ret > PRINTF_BUFFER_SIZE-1);
  12.549 +	ret = xenbus_write(t, dir, node, printf_buffer);
  12.550 +
  12.551 +	free(printf_buffer);
  12.552 +
  12.553 +	return ret;
  12.554  }
  12.555  
  12.556 -	
  12.557  /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
  12.558 -int xenbus_gather(const char *dir, ...)
  12.559 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...)
  12.560  {
  12.561  	va_list ap;
  12.562  	const char *name;
  12.563 @@ -364,7 +520,7 @@ int xenbus_gather(const char *dir, ...)
  12.564  		void *result = va_arg(ap, void *);
  12.565  		char *p;
  12.566  
  12.567 -		p = xenbus_read(dir, name, NULL);
  12.568 +		p = xenbus_read(t, dir, name, NULL);
  12.569  		if (IS_ERR(p)) {
  12.570  			ret = PTR_ERR(p);
  12.571  			break;
  12.572 @@ -372,7 +528,7 @@ int xenbus_gather(const char *dir, ...)
  12.573  		if (fmt) {
  12.574  			if (sscanf(p, fmt, result) == 0)
  12.575  				ret = -EINVAL;
  12.576 -			xfree(p);
  12.577 +			free(p);
  12.578  		} else
  12.579  			*(char **)result = p;
  12.580  	}
  12.581 @@ -389,31 +545,8 @@ static int xs_watch(const char *path, co
  12.582  	iov[1].iov_base = (void *)token;
  12.583  	iov[1].iov_len = strlen(token) + 1;
  12.584  
  12.585 -	return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
  12.586 -}
  12.587 -
  12.588 -static char *xs_read_watch(char **token)
  12.589 -{
  12.590 -	enum xsd_sockmsg_type type;
  12.591 -	char *ret;
  12.592 -
  12.593 -	ret = read_reply(&type, NULL);
  12.594 -	if (IS_ERR(ret))
  12.595 -		return ret;
  12.596 -
  12.597 -	//BUG_ON(type != XS_WATCH_EVENT);
  12.598 -	*token = ret + strlen(ret) + 1;
  12.599 -	return ret;
  12.600 -}
  12.601 -
  12.602 -static int xs_acknowledge_watch(const char *token)
  12.603 -{
  12.604 -#if 0
  12.605 -	return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
  12.606 -#else
  12.607 -	/* XS_WATCH_ACK is no longer available */
  12.608 -	return 0;
  12.609 -#endif
  12.610 +	return xs_error(xs_talkv(NULL, XS_WATCH, iov,
  12.611 +				 ARRAY_SIZE(iov), NULL));
  12.612  }
  12.613  
  12.614  static int xs_unwatch(const char *path, const char *token)
  12.615 @@ -425,10 +558,10 @@ static int xs_unwatch(const char *path, 
  12.616  	iov[1].iov_base = (char *)token;
  12.617  	iov[1].iov_len = strlen(token) + 1;
  12.618  
  12.619 -	return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
  12.620 +	return xs_error(xs_talkv(NULL, XS_UNWATCH, iov,
  12.621 +				 ARRAY_SIZE(iov), NULL));
  12.622  }
  12.623  
  12.624 -/* A little paranoia: we don't just trust token. */
  12.625  static struct xenbus_watch *find_watch(const char *token)
  12.626  {
  12.627  	struct xenbus_watch *i, *cmp;
  12.628 @@ -438,6 +571,7 @@ static struct xenbus_watch *find_watch(c
  12.629  	list_for_each_entry(i, &watches, list)
  12.630  		if (i == cmp)
  12.631  			return i;
  12.632 +
  12.633  	return NULL;
  12.634  }
  12.635  
  12.636 @@ -449,111 +583,214 @@ int register_xenbus_watch(struct xenbus_
  12.637  	int err;
  12.638  
  12.639  	sprintf(token, "%lX", (long)watch);
  12.640 -	//BUG_ON(find_watch(token));
  12.641 -printk("Registered watch for: %s\n", token);
  12.642 +
  12.643 +	down_read(&xs_state.suspend_mutex);
  12.644 +
  12.645 +	spin_lock(&watches_lock);
  12.646 +	//	BUG_ON(find_watch(token));
  12.647 +	list_add(&watch->list, &watches);
  12.648 +	spin_unlock(&watches_lock);
  12.649 +
  12.650  	err = xs_watch(watch->node, token);
  12.651 -	if (!err)
  12.652 -		list_add(&watch->list, &watches);
  12.653 +
  12.654 +	/* Ignore errors due to multiple registration. */
  12.655 +	if ((err != 0) && (err != -EEXIST)) {
  12.656 +		spin_lock(&watches_lock);
  12.657 +		list_del(&watch->list);
  12.658 +		spin_unlock(&watches_lock);
  12.659 +	}
  12.660 +
  12.661 +	up_read(&xs_state.suspend_mutex);
  12.662 +
  12.663  	return err;
  12.664  }
  12.665  
  12.666  void unregister_xenbus_watch(struct xenbus_watch *watch)
  12.667  {
  12.668 +	struct xs_stored_msg *msg, *tmp;
  12.669  	char token[sizeof(watch) * 2 + 1];
  12.670  	int err;
  12.671  
  12.672  	sprintf(token, "%lX", (long)watch);
  12.673 -	//BUG_ON(!find_watch(token));
  12.674 +
  12.675 +	down_read(&xs_state.suspend_mutex);
  12.676 +
  12.677 +	spin_lock(&watches_lock);
  12.678 +	//	BUG_ON(!find_watch(token));
  12.679 +	list_del(&watch->list);
  12.680 +	spin_unlock(&watches_lock);
  12.681  
  12.682  	err = xs_unwatch(watch->node, token);
  12.683 -	list_del(&watch->list);
  12.684 -
  12.685  	if (err)
  12.686  		printk("XENBUS Failed to release watch %s: %i\n",
  12.687  		       watch->node, err);
  12.688 +
  12.689 +	up_read(&xs_state.suspend_mutex);
  12.690 +
  12.691 +	/* Cancel pending watch events. */
  12.692 +	spin_lock(&watch_events_lock);
  12.693 +	list_for_each_entry_safe(msg, tmp, &watch_events, list) {
  12.694 +		if (msg->u.watch.handle != watch)
  12.695 +			continue;
  12.696 +		list_del(&msg->list);
  12.697 +		free(msg->u.watch.vec);
  12.698 +		free(msg);
  12.699 +	}
  12.700 +	spin_unlock(&watch_events_lock);
  12.701  }
  12.702  
  12.703 -/* Re-register callbacks to all watches. */
  12.704 -void reregister_xenbus_watches(void)
  12.705 +void xs_suspend(void)
  12.706 +{
  12.707 +	down_write(&xs_state.suspend_mutex);
  12.708 +	down(&xs_state.request_mutex);
  12.709 +}
  12.710 +
  12.711 +void xs_resume(void)
  12.712  {
  12.713  	struct xenbus_watch *watch;
  12.714  	char token[sizeof(watch) * 2 + 1];
  12.715  
  12.716 +	up(&xs_state.request_mutex);
  12.717 +
  12.718 +	/* No need for watches_lock: the suspend_mutex is sufficient. */
  12.719  	list_for_each_entry(watch, &watches, list) {
  12.720  		sprintf(token, "%lX", (long)watch);
  12.721  		xs_watch(watch->node, token);
  12.722  	}
  12.723 +
  12.724 +	up_write(&xs_state.suspend_mutex);
  12.725  }
  12.726  
  12.727 -void watch_thread(void *unused)
  12.728 +static void xenwatch_thread(void *unused)
  12.729  {
  12.730 +	struct list_head *ent;
  12.731 +	struct xs_stored_msg *msg;
  12.732 +
  12.733  	for (;;) {
  12.734 -		char *token;
  12.735 -		char *node = NULL;
  12.736 +		wait_event(watch_events_waitq,
  12.737 +			   !list_empty(&watch_events));
  12.738  
  12.739 -		wait_event(xb_waitq, xs_input_avail());
  12.740 +		down(&xenwatch_mutex);
  12.741  
  12.742 -		/* If this is a spurious wakeup caused by someone
  12.743 -		 * doing an op, they'll hold the lock and the buffer
  12.744 -		 * will be empty by the time we get there.		 
  12.745 -		 */
  12.746 -		down(&xenbus_lock);
  12.747 -		if (xs_input_avail())
  12.748 -			node = xs_read_watch(&token);
  12.749 +		spin_lock(&watch_events_lock);
  12.750 +		ent = watch_events.next;
  12.751 +		if (ent != &watch_events)
  12.752 +			list_del(ent);
  12.753 +		spin_unlock(&watch_events_lock);
  12.754  
  12.755 -		if (node && !IS_ERR(node)) {
  12.756 -			struct xenbus_watch *w;
  12.757 -			int err;
  12.758 +		if (ent != &watch_events) {
  12.759 +			msg = list_entry(ent, struct xs_stored_msg, list);
  12.760 +			msg->u.watch.handle->callback(
  12.761 +				msg->u.watch.handle,
  12.762 +				(const char **)msg->u.watch.vec,
  12.763 +				msg->u.watch.vec_size);
  12.764 +			free(msg->u.watch.vec);
  12.765 +			free(msg);
  12.766 +		}
  12.767  
  12.768 -			err = xs_acknowledge_watch(token);
  12.769 -			if (err)
  12.770 -				printk("XENBUS ack %s fail %i\n", node, err);
  12.771 -			w = find_watch(token);
  12.772 -			//BUG_ON(!w);
  12.773 -			w->callback(w, node);
  12.774 -			xfree(node);
  12.775 -		} else
  12.776 -			printk("XENBUS xs_read_watch: %li\n", PTR_ERR(node));
  12.777 -		up(&xenbus_lock);
  12.778 +		up(&xenwatch_mutex);
  12.779  	}
  12.780  }
  12.781  
  12.782 -
  12.783 -static void ballon_changed(struct xenbus_watch *watch, const char *node)
  12.784 +static int process_msg(void)
  12.785  {
  12.786 -    unsigned long new_target;
  12.787 -    int err;
  12.788 -    err = xenbus_scanf("memory", "target", "%lu", &new_target);
  12.789 +	struct xs_stored_msg *msg;
  12.790 +	char *body;
  12.791 +	int err;
  12.792 +
  12.793 +	msg = malloc(sizeof(*msg));
  12.794 +	if (msg == NULL)
  12.795 +		return -ENOMEM;
  12.796 +
  12.797 +	err = xb_read(&msg->hdr, sizeof(msg->hdr));
  12.798 +	if (err) {
  12.799 +		free(msg);
  12.800 +		return err;
  12.801 +	}
  12.802 +
  12.803 +	body = malloc(msg->hdr.len + 1);
  12.804 +	if (body == NULL) {
  12.805 +		free(msg);
  12.806 +		return -ENOMEM;
  12.807 +	}
  12.808 +
  12.809 +	err = xb_read(body, msg->hdr.len);
  12.810 +	if (err) {
  12.811 +		free(body);
  12.812 +		free(msg);
  12.813 +		return err;
  12.814 +	}
  12.815 +	body[msg->hdr.len] = '\0';
  12.816  
  12.817 -    if(err != 1)
  12.818 -    {
  12.819 -        printk("Unable to read memory/target\n");
  12.820 -        return;
  12.821 -    }
  12.822 +	if (msg->hdr.type == XS_WATCH_EVENT) {
  12.823 +		msg->u.watch.vec = split(body, msg->hdr.len,
  12.824 +					 &msg->u.watch.vec_size);
  12.825 +		if (IS_ERR(msg->u.watch.vec)) {
  12.826 +			free(msg);
  12.827 +			return PTR_ERR(msg->u.watch.vec);
  12.828 +		}
  12.829  
  12.830 -    printk("Memory target changed to: %ld bytes, ignoring.\n", new_target);
  12.831 +		spin_lock(&watches_lock);
  12.832 +		msg->u.watch.handle = find_watch(
  12.833 +			msg->u.watch.vec[XS_WATCH_TOKEN]);
  12.834 +		if (msg->u.watch.handle != NULL) {
  12.835 +			spin_lock(&watch_events_lock);
  12.836 +			list_add_tail(&msg->list, &watch_events);
  12.837 +			wake_up(&watch_events_waitq);
  12.838 +			spin_unlock(&watch_events_lock);
  12.839 +		} else {
  12.840 +			free(msg->u.watch.vec);
  12.841 +			free(msg);
  12.842 +		}
  12.843 +		spin_unlock(&watches_lock);
  12.844 +	} else {
  12.845 +		msg->u.reply.body = body;
  12.846 +		spin_lock(&xs_state.reply_lock);
  12.847 +		list_add_tail(&msg->list, &xs_state.reply_list);
  12.848 +		spin_unlock(&xs_state.reply_lock);
  12.849 +		wake_up(&xs_state.reply_waitq);
  12.850 +	}
  12.851 +
  12.852 +	return 0;
  12.853  }
  12.854  
  12.855 +static void xenbus_thread(void *unused)
  12.856 +{
  12.857 +	int err;
  12.858  
  12.859 -static struct xenbus_watch ballon_watch = {
  12.860 -    .node = "memory/target",
  12.861 -    .callback = ballon_changed,
  12.862 -};
  12.863 -
  12.864 -
  12.865 +	for (;;) {
  12.866 +		err = process_msg();
  12.867 +		if (err)
  12.868 +			printk("XENBUS error %d while reading "
  12.869 +			       "message\n", err);
  12.870 +	}
  12.871 +}
  12.872  
  12.873  int xs_init(void)
  12.874  {
  12.875  	int err;
  12.876 -	struct thread *watcher;
  12.877 -    printk("xb_init_comms\n");
  12.878 +	struct thread *kxwatcher_thread;
  12.879 +	struct thread *kxenbus_thread;
  12.880 +
  12.881 +	INIT_LIST_HEAD(&xs_state.reply_list);
  12.882 +	spin_lock_init(&xs_state.reply_lock);
  12.883 +	init_waitqueue_head(&xs_state.reply_waitq);
  12.884 +
  12.885 +	init_MUTEX(&xs_state.request_mutex);
  12.886 +	init_rwsem(&xs_state.suspend_mutex);
  12.887 +
  12.888 +	/* Initialize the shared memory rings to talk to xenstored */
  12.889  	err = xb_init_comms();
  12.890  	if (err)
  12.891  		return err;
  12.892 -	
  12.893 -	watcher = create_thread("kxwatch", watch_thread, NULL);
  12.894 -    down(&xenbus_lock);
  12.895 -    register_xenbus_watch(&ballon_watch);
  12.896 -    up(&xenbus_lock);
  12.897 +
  12.898 +	kxwatcher_thread = create_thread("kxwatch", xenwatch_thread, NULL);
  12.899 +	if (IS_ERR(kxwatcher_thread))
  12.900 +		return PTR_ERR(kxwatcher_thread);
  12.901 +
  12.902 +	kxenbus_thread = create_thread("kxenbus", xenbus_thread, NULL);
  12.903 +	if (IS_ERR(kxenbus_thread))
  12.904 +		return PTR_ERR(kxenbus_thread);
  12.905 +
  12.906  	return 0;
  12.907  }