ia64/xen-unstable

changeset 7299:1ac39c7a0435

Merged.
author emellor@ewan
date Mon Oct 10 14:46:53 2005 +0100 (2005-10-10)
parents 0e7c48861e95 b7dce4fe2488
children 015f8ae81276 d6d1c3cbc151
files
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Oct 10 14:42:38 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Mon Oct 10 14:46:53 2005 +0100
     1.3 @@ -1327,18 +1327,14 @@ static struct xenbus_watch cpu_watch = {
     1.4  	.callback = handle_vcpu_hotplug_event
     1.5  };
     1.6  
     1.7 -/* NB: Assumes xenbus_lock is held! */
     1.8  static int setup_cpu_watcher(struct notifier_block *notifier,
     1.9  			      unsigned long event, void *data)
    1.10  {
    1.11 -	int err = 0;
    1.12 +	int err;
    1.13  
    1.14 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
    1.15  	err = register_xenbus_watch(&cpu_watch);
    1.16 -
    1.17 -	if (err) {
    1.18 +	if (err)
    1.19  		printk("Failed to register watch on /cpu\n");
    1.20 -	}
    1.21  
    1.22  	return NOTIFY_DONE;
    1.23  }
    1.24 @@ -1368,7 +1364,7 @@ static void handle_vcpu_hotplug_event(st
    1.25  			return;
    1.26  
    1.27  		/* get the state value */
    1.28 -		err = xenbus_scanf(dir, "availability", "%s", state);
    1.29 +		err = xenbus_scanf(NULL, dir, "availability", "%s", state);
    1.30  
    1.31  		if (err != 1) {
    1.32  			printk(KERN_ERR
    1.33 @@ -1578,7 +1574,7 @@ void smp_suspend(void)
    1.34  void smp_resume(void)
    1.35  {
    1.36  	smp_intr_init();
    1.37 -	local_setup_timer_irq();
    1.38 +	local_setup_timer();
    1.39  }
    1.40  
    1.41  void vcpu_prepare(int vcpu)
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c	Mon Oct 10 14:42:38 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c	Mon Oct 10 14:46:53 2005 +0100
     2.3 @@ -122,7 +122,7 @@ static u32 shadow_tv_version;
     2.4  static u64 processed_system_time;   /* System time (ns) at last processing. */
     2.5  static DEFINE_PER_CPU(u64, processed_system_time);
     2.6  
     2.7 -#define NS_PER_TICK (1000000000L/HZ)
     2.8 +#define NS_PER_TICK (1000000000ULL/HZ)
     2.9  
    2.10  static inline void __normalize_time(time_t *sec, s64 *nsec)
    2.11  {
    2.12 @@ -800,9 +800,9 @@ static inline u64 jiffies_to_st(unsigned
    2.13  		delta = j - jiffies;
    2.14  		/* NB. The next check can trigger in some wrap-around cases,
    2.15  		 * but that's ok: we'll just end up with a shorter timeout. */
    2.16 -		if (delta < 1)
    2.17 +		if (delta < 1) 
    2.18  			delta = 1;
    2.19 -		st = processed_system_time + (delta * NS_PER_TICK);
    2.20 +		st = processed_system_time + ((u64)delta * NS_PER_TICK);
    2.21  	} while (read_seqretry(&xtime_lock, seq));
    2.22  
    2.23  	return st;
    2.24 @@ -816,7 +816,7 @@ void stop_hz_timer(void)
    2.25  {
    2.26  	unsigned int cpu = smp_processor_id();
    2.27  	unsigned long j;
    2.28 -
    2.29 +	
    2.30  	/* s390 does this /before/ checking rcu_pending(). We copy them. */
    2.31  	cpu_set(cpu, nohz_cpu_mask);
    2.32  
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Oct 10 14:42:38 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Mon Oct 10 14:46:53 2005 +0100
     3.3 @@ -275,22 +275,23 @@ static void shutdown_handler(struct xenb
     3.4  {
     3.5  	static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
     3.6  	char *str;
     3.7 +	struct xenbus_transaction *xbt;
     3.8  	int err;
     3.9  
    3.10   again:
    3.11 -	err = xenbus_transaction_start();
    3.12 -	if (err)
    3.13 +	xbt = xenbus_transaction_start();
    3.14 +	if (IS_ERR(xbt))
    3.15  		return;
    3.16 -	str = (char *)xenbus_read("control", "shutdown", NULL);
    3.17 +	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
    3.18  	/* Ignore read errors and empty reads. */
    3.19  	if (XENBUS_IS_ERR_READ(str)) {
    3.20 -		xenbus_transaction_end(1);
    3.21 +		xenbus_transaction_end(xbt, 1);
    3.22  		return;
    3.23  	}
    3.24  
    3.25 -	xenbus_write("control", "shutdown", "");
    3.26 +	xenbus_write(xbt, "control", "shutdown", "");
    3.27  
    3.28 -	err = xenbus_transaction_end(0);
    3.29 +	err = xenbus_transaction_end(xbt, 0);
    3.30  	if (err == -EAGAIN) {
    3.31  		kfree(str);
    3.32  		goto again;
    3.33 @@ -320,23 +321,24 @@ static void sysrq_handler(struct xenbus_
    3.34  			  unsigned int len)
    3.35  {
    3.36  	char sysrq_key = '\0';
    3.37 +	struct xenbus_transaction *xbt;
    3.38  	int err;
    3.39  
    3.40   again:
    3.41 -	err = xenbus_transaction_start();
    3.42 -	if (err)
    3.43 +	xbt  = xenbus_transaction_start();
    3.44 +	if (IS_ERR(xbt))
    3.45  		return;
    3.46 -	if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
    3.47 +	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
    3.48  		printk(KERN_ERR "Unable to read sysrq code in "
    3.49  		       "control/sysrq\n");
    3.50 -		xenbus_transaction_end(1);
    3.51 +		xenbus_transaction_end(xbt, 1);
    3.52  		return;
    3.53  	}
    3.54  
    3.55  	if (sysrq_key != '\0')
    3.56 -		xenbus_printf("control", "sysrq", "%c", '\0');
    3.57 +		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
    3.58  
    3.59 -	err = xenbus_transaction_end(0);
    3.60 +	err = xenbus_transaction_end(xbt, 0);
    3.61  	if (err == -EAGAIN)
    3.62  		goto again;
    3.63  
    3.64 @@ -360,9 +362,6 @@ static struct xenbus_watch sysrq_watch =
    3.65  
    3.66  static struct notifier_block xenstore_notifier;
    3.67  
    3.68 -/* Setup our watcher
    3.69 -   NB: Assumes xenbus_lock is held!
    3.70 -*/
    3.71  static int setup_shutdown_watcher(struct notifier_block *notifier,
    3.72                                    unsigned long event,
    3.73                                    void *data)
    3.74 @@ -372,8 +371,6 @@ static int setup_shutdown_watcher(struct
    3.75  	int err2 = 0;
    3.76  #endif
    3.77  
    3.78 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
    3.79 -
    3.80  	err1 = register_xenbus_watch(&shutdown_watch);
    3.81  #ifdef CONFIG_MAGIC_SYSRQ
    3.82  	err2 = register_xenbus_watch(&sysrq_watch);
     4.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Mon Oct 10 14:42:38 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Mon Oct 10 14:46:53 2005 +0100
     4.3 @@ -357,7 +357,7 @@ static void watch_target(struct xenbus_w
     4.4  	unsigned long long new_target;
     4.5  	int err;
     4.6  
     4.7 -	err = xenbus_scanf("memory", "target", "%llu", &new_target);
     4.8 +	err = xenbus_scanf(NULL, "memory", "target", "%llu", &new_target);
     4.9  	if (err != 1) {
    4.10  		printk(KERN_ERR "Unable to read memory/target\n");
    4.11  		return;
    4.12 @@ -370,17 +370,12 @@ static void watch_target(struct xenbus_w
    4.13      
    4.14  }
    4.15  
    4.16 -/* Setup our watcher
    4.17 -   NB: Assumes xenbus_lock is held!
    4.18 -*/
    4.19  int balloon_init_watcher(struct notifier_block *notifier,
    4.20                           unsigned long event,
    4.21                           void *data)
    4.22  {
    4.23  	int err;
    4.24  
    4.25 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
    4.26 -
    4.27  	err = register_xenbus_watch(&target_watch);
    4.28  	if (err)
    4.29  		printk(KERN_ERR "Failed to set balloon watcher\n");
     5.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Mon Oct 10 14:42:38 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Mon Oct 10 14:46:53 2005 +0100
     5.3 @@ -61,18 +61,19 @@ static void frontend_changed(struct xenb
     5.4  	unsigned long ring_ref;
     5.5  	unsigned int evtchn;
     5.6  	int err;
     5.7 +	struct xenbus_transaction *xbt;
     5.8  	struct backend_info *be
     5.9  		= container_of(watch, struct backend_info, watch);
    5.10  
    5.11  	/* If other end is gone, delete ourself. */
    5.12 -	if (vec && !xenbus_exists(be->frontpath, "")) {
    5.13 +	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
    5.14  		device_unregister(&be->dev->dev);
    5.15  		return;
    5.16  	}
    5.17  	if (be->blkif == NULL || be->blkif->status == CONNECTED)
    5.18  		return;
    5.19  
    5.20 -	err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
    5.21 +	err = xenbus_gather(NULL, be->frontpath, "ring-ref", "%lu", &ring_ref,
    5.22  			    "event-channel", "%u", &evtchn, NULL);
    5.23  	if (err) {
    5.24  		xenbus_dev_error(be->dev, err,
    5.25 @@ -84,7 +85,8 @@ static void frontend_changed(struct xenb
    5.26  	/* Map the shared frame, irq etc. */
    5.27  	err = blkif_map(be->blkif, ring_ref, evtchn);
    5.28  	if (err) {
    5.29 -		xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
    5.30 +		xenbus_dev_error(be->dev, err,
    5.31 +				 "mapping ring-ref %lu port %u",
    5.32  				 ring_ref, evtchn);
    5.33  		return;
    5.34  	}
    5.35 @@ -92,13 +94,13 @@ static void frontend_changed(struct xenb
    5.36  
    5.37  again:
    5.38  	/* Supply the information about the device the frontend needs */
    5.39 -	err = xenbus_transaction_start();
    5.40 -	if (err) {
    5.41 +	xbt = xenbus_transaction_start();
    5.42 +	if (IS_ERR(xbt)) {
    5.43  		xenbus_dev_error(be->dev, err, "starting transaction");
    5.44  		return;
    5.45  	}
    5.46  
    5.47 -	err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
    5.48 +	err = xenbus_printf(xbt, be->dev->nodename, "sectors", "%lu",
    5.49  			    vbd_size(&be->blkif->vbd));
    5.50  	if (err) {
    5.51  		xenbus_dev_error(be->dev, err, "writing %s/sectors",
    5.52 @@ -107,14 +109,14 @@ again:
    5.53  	}
    5.54  
    5.55  	/* FIXME: use a typename instead */
    5.56 -	err = xenbus_printf(be->dev->nodename, "info", "%u",
    5.57 +	err = xenbus_printf(xbt, be->dev->nodename, "info", "%u",
    5.58  			    vbd_info(&be->blkif->vbd));
    5.59  	if (err) {
    5.60  		xenbus_dev_error(be->dev, err, "writing %s/info",
    5.61  				 be->dev->nodename);
    5.62  		goto abort;
    5.63  	}
    5.64 -	err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
    5.65 +	err = xenbus_printf(xbt, be->dev->nodename, "sector-size", "%lu",
    5.66  			    vbd_secsize(&be->blkif->vbd));
    5.67  	if (err) {
    5.68  		xenbus_dev_error(be->dev, err, "writing %s/sector-size",
    5.69 @@ -122,7 +124,7 @@ again:
    5.70  		goto abort;
    5.71  	}
    5.72  
    5.73 -	err = xenbus_transaction_end(0);
    5.74 +	err = xenbus_transaction_end(xbt, 0);
    5.75  	if (err == -EAGAIN)
    5.76  		goto again;
    5.77  	if (err) {
    5.78 @@ -136,7 +138,7 @@ again:
    5.79  	return;
    5.80  
    5.81   abort:
    5.82 -	xenbus_transaction_end(1);
    5.83 +	xenbus_transaction_end(xbt, 1);
    5.84  }
    5.85  
    5.86  /* 
    5.87 @@ -154,7 +156,8 @@ static void backend_changed(struct xenbu
    5.88  		= container_of(watch, struct backend_info, backend_watch);
    5.89  	struct xenbus_device *dev = be->dev;
    5.90  
    5.91 -	err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
    5.92 +	err = xenbus_scanf(NULL, dev->nodename,
    5.93 +			   "physical-device", "%li", &pdev);
    5.94  	if (XENBUS_EXIST_ERR(err))
    5.95  		return;
    5.96  	if (err < 0) {
    5.97 @@ -169,7 +172,7 @@ static void backend_changed(struct xenbu
    5.98  	be->pdev = pdev;
    5.99  
   5.100  	/* If there's a read-only node, we're read only. */
   5.101 -	p = xenbus_read(dev->nodename, "read-only", NULL);
   5.102 +	p = xenbus_read(NULL, dev->nodename, "read-only", NULL);
   5.103  	if (!IS_ERR(p)) {
   5.104  		be->readonly = 1;
   5.105  		kfree(p);
   5.106 @@ -184,7 +187,8 @@ static void backend_changed(struct xenbu
   5.107  		if (IS_ERR(be->blkif)) {
   5.108  			err = PTR_ERR(be->blkif);
   5.109  			be->blkif = NULL;
   5.110 -			xenbus_dev_error(dev, err, "creating block interface");
   5.111 +			xenbus_dev_error(dev, err,
   5.112 +					 "creating block interface");
   5.113  			return;
   5.114  		}
   5.115  
   5.116 @@ -192,7 +196,8 @@ static void backend_changed(struct xenbu
   5.117  		if (err) {
   5.118  			blkif_put(be->blkif);
   5.119  			be->blkif = NULL;
   5.120 -			xenbus_dev_error(dev, err, "creating vbd structure");
   5.121 +			xenbus_dev_error(dev, err,
   5.122 +					 "creating vbd structure");
   5.123  			return;
   5.124  		}
   5.125  
   5.126 @@ -210,13 +215,14 @@ static int blkback_probe(struct xenbus_d
   5.127  
   5.128  	be = kmalloc(sizeof(*be), GFP_KERNEL);
   5.129  	if (!be) {
   5.130 -		xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
   5.131 +		xenbus_dev_error(dev, -ENOMEM,
   5.132 +				 "allocating backend structure");
   5.133  		return -ENOMEM;
   5.134  	}
   5.135  	memset(be, 0, sizeof(*be));
   5.136  
   5.137  	frontend = NULL;
   5.138 -	err = xenbus_gather(dev->nodename,
   5.139 +	err = xenbus_gather(NULL, dev->nodename,
   5.140  			    "frontend-id", "%li", &be->frontend_id,
   5.141  			    "frontend", NULL, &frontend,
   5.142  			    NULL);
   5.143 @@ -228,7 +234,7 @@ static int blkback_probe(struct xenbus_d
   5.144  				 dev->nodename);
   5.145  		goto free_be;
   5.146  	}
   5.147 -	if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
   5.148 +	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
   5.149  		/* If we can't get a frontend path and a frontend-id,
   5.150  		 * then our bus-id is no longer valid and we need to
   5.151  		 * destroy the backend device.
   5.152 @@ -244,7 +250,8 @@ static int blkback_probe(struct xenbus_d
   5.153  	err = register_xenbus_watch(&be->backend_watch);
   5.154  	if (err) {
   5.155  		be->backend_watch.node = NULL;
   5.156 -		xenbus_dev_error(dev, err, "adding backend watch on %s",
   5.157 +		xenbus_dev_error(dev, err,
   5.158 +				 "adding backend watch on %s",
   5.159  				 dev->nodename);
   5.160  		goto free_be;
   5.161  	}
     6.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Oct 10 14:42:38 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Mon Oct 10 14:46:53 2005 +0100
     6.3 @@ -460,7 +460,7 @@ static void watch_for_status(struct xenb
     6.4  	if (info->connected == BLKIF_STATE_CONNECTED)
     6.5  		return;
     6.6  
     6.7 -	err = xenbus_gather(watch->node,
     6.8 +	err = xenbus_gather(NULL, watch->node,
     6.9  			    "sectors", "%lu", &sectors,
    6.10  			    "info", "%u", &binfo,
    6.11  			    "sector-size", "%lu", &sector_size,
    6.12 @@ -532,10 +532,11 @@ static int talk_to_backend(struct xenbus
    6.13  {
    6.14  	char *backend;
    6.15  	const char *message;
    6.16 +	struct xenbus_transaction *xbt;
    6.17  	int err;
    6.18  
    6.19  	backend = NULL;
    6.20 -	err = xenbus_gather(dev->nodename,
    6.21 +	err = xenbus_gather(NULL, dev->nodename,
    6.22  			    "backend-id", "%i", &info->backend_id,
    6.23  			    "backend", NULL, &backend,
    6.24  			    NULL);
    6.25 @@ -559,25 +560,26 @@ static int talk_to_backend(struct xenbus
    6.26  	}
    6.27  
    6.28  again:
    6.29 -	err = xenbus_transaction_start();
    6.30 -	if (err) {
    6.31 +	xbt = xenbus_transaction_start();
    6.32 +	if (IS_ERR(xbt)) {
    6.33  		xenbus_dev_error(dev, err, "starting transaction");
    6.34  		goto destroy_blkring;
    6.35  	}
    6.36  
    6.37 -	err = xenbus_printf(dev->nodename, "ring-ref","%u", info->ring_ref);
    6.38 +	err = xenbus_printf(xbt, dev->nodename,
    6.39 +			    "ring-ref","%u", info->ring_ref);
    6.40  	if (err) {
    6.41  		message = "writing ring-ref";
    6.42  		goto abort_transaction;
    6.43  	}
    6.44 -	err = xenbus_printf(dev->nodename,
    6.45 +	err = xenbus_printf(xbt, dev->nodename,
    6.46  			    "event-channel", "%u", info->evtchn);
    6.47  	if (err) {
    6.48  		message = "writing event-channel";
    6.49  		goto abort_transaction;
    6.50  	}
    6.51  
    6.52 -	err = xenbus_transaction_end(0);
    6.53 +	err = xenbus_transaction_end(xbt, 0);
    6.54  	if (err) {
    6.55  		if (err == -EAGAIN)
    6.56  			goto again;
    6.57 @@ -598,8 +600,7 @@ again:
    6.58  	return 0;
    6.59  
    6.60   abort_transaction:
    6.61 -	xenbus_transaction_end(1);
    6.62 -	/* Have to do this *outside* transaction.  */
    6.63 +	xenbus_transaction_end(xbt, 1);
    6.64  	xenbus_dev_error(dev, err, "%s", message);
    6.65   destroy_blkring:
    6.66  	blkif_free(info);
    6.67 @@ -620,7 +621,8 @@ static int blkfront_probe(struct xenbus_
    6.68  	struct blkfront_info *info;
    6.69  
    6.70  	/* FIXME: Use dynamic device id if this is not set. */
    6.71 -	err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice);
    6.72 +	err = xenbus_scanf(NULL, dev->nodename,
    6.73 +			   "virtual-device", "%i", &vdevice);
    6.74  	if (XENBUS_EXIST_ERR(err))
    6.75  		return err;
    6.76  	if (err < 0) {
     7.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c	Mon Oct 10 14:42:38 2005 +0100
     7.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c	Mon Oct 10 14:46:53 2005 +0100
     7.3 @@ -160,7 +160,8 @@ xlbd_get_major_info(int vdevice)
     7.4  
     7.5  	mi = ((major_info[index] != NULL) ? major_info[index] :
     7.6  	      xlbd_alloc_major_info(major, minor, index));
     7.7 -	mi->usage++;
     7.8 +	if (mi)
     7.9 +		mi->usage++;
    7.10  	return mi;
    7.11  }
    7.12  
     8.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Mon Oct 10 14:42:38 2005 +0100
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Mon Oct 10 14:46:53 2005 +0100
     8.3 @@ -69,15 +69,15 @@ static void frontend_changed(struct xenb
     8.4  	int i;
     8.5  
     8.6  	/* If other end is gone, delete ourself. */
     8.7 -	if (vec && !xenbus_exists(be->frontpath, "")) {
     8.8 -		xenbus_rm(be->dev->nodename, "");
     8.9 +	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
    8.10 +		xenbus_rm(NULL, be->dev->nodename, "");
    8.11  		device_unregister(&be->dev->dev);
    8.12  		return;
    8.13  	}
    8.14  	if (be->netif == NULL || be->netif->status == CONNECTED)
    8.15  		return;
    8.16  
    8.17 -	mac = xenbus_read(be->frontpath, "mac", NULL);
    8.18 +	mac = xenbus_read(NULL, be->frontpath, "mac", NULL);
    8.19  	if (IS_ERR(mac)) {
    8.20  		err = PTR_ERR(mac);
    8.21  		xenbus_dev_error(be->dev, err, "reading %s/mac",
    8.22 @@ -98,7 +98,8 @@ static void frontend_changed(struct xenb
    8.23  	}
    8.24  	kfree(mac);
    8.25  
    8.26 -	err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref,
    8.27 +	err = xenbus_gather(NULL, be->frontpath,
    8.28 +			    "tx-ring-ref", "%lu", &tx_ring_ref,
    8.29  			    "rx-ring-ref", "%lu", &rx_ring_ref,
    8.30  			    "event-channel", "%u", &evtchn, NULL);
    8.31  	if (err) {
    8.32 @@ -137,7 +138,7 @@ static void backend_changed(struct xenbu
    8.33  	struct xenbus_device *dev = be->dev;
    8.34  	u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
    8.35  
    8.36 -	err = xenbus_scanf(dev->nodename, "handle", "%li", &handle);
    8.37 +	err = xenbus_scanf(NULL, dev->nodename, "handle", "%li", &handle);
    8.38  	if (XENBUS_EXIST_ERR(err))
    8.39  		return;
    8.40  	if (err < 0) {
    8.41 @@ -188,7 +189,7 @@ static int netback_hotplug(struct xenbus
    8.42  
    8.43  	key = env_vars;
    8.44  	while (*key != NULL) {
    8.45 -		val = xenbus_read(xdev->nodename, *key, NULL);
    8.46 +		val = xenbus_read(NULL, xdev->nodename, *key, NULL);
    8.47  		if (!IS_ERR(val)) {
    8.48  			char buf[strlen(*key) + 4];
    8.49  			sprintf(buf, "%s=%%s", *key);
    8.50 @@ -220,7 +221,7 @@ static int netback_probe(struct xenbus_d
    8.51  	memset(be, 0, sizeof(*be));
    8.52  
    8.53  	frontend = NULL;
    8.54 -	err = xenbus_gather(dev->nodename,
    8.55 +	err = xenbus_gather(NULL, dev->nodename,
    8.56  			    "frontend-id", "%li", &be->frontend_id,
    8.57  			    "frontend", NULL, &frontend,
    8.58  			    NULL);
    8.59 @@ -232,7 +233,7 @@ static int netback_probe(struct xenbus_d
    8.60  				 dev->nodename);
    8.61  		goto free_be;
    8.62  	}
    8.63 -	if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
    8.64 +	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
    8.65  		/* If we can't get a frontend path and a frontend-id,
    8.66  		 * then our bus-id is no longer valid and we need to
    8.67  		 * destroy the backend device.
     9.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Oct 10 14:42:38 2005 +0100
     9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Mon Oct 10 14:46:53 2005 +0100
     9.3 @@ -1083,10 +1083,11 @@ static int talk_to_backend(struct xenbus
     9.4  {
     9.5  	char *backend, *mac, *e, *s;
     9.6  	const char *message;
     9.7 +	struct xenbus_transaction *xbt;
     9.8  	int err, i;
     9.9  
    9.10  	backend = NULL;
    9.11 -	err = xenbus_gather(dev->nodename,
    9.12 +	err = xenbus_gather(NULL, dev->nodename,
    9.13  			    "backend-id", "%i", &info->backend_id,
    9.14  			    "backend", NULL, &backend,
    9.15  			    NULL);
    9.16 @@ -1102,7 +1103,7 @@ static int talk_to_backend(struct xenbus
    9.17  		goto out;
    9.18  	}
    9.19  
    9.20 -	mac = xenbus_read(dev->nodename, "mac", NULL);
    9.21 +	mac = xenbus_read(NULL, dev->nodename, "mac", NULL);
    9.22  	if (IS_ERR(mac)) {
    9.23  		err = PTR_ERR(mac);
    9.24  		xenbus_dev_error(dev, err, "reading %s/mac",
    9.25 @@ -1131,32 +1132,32 @@ static int talk_to_backend(struct xenbus
    9.26  	}
    9.27  
    9.28  again:
    9.29 -	err = xenbus_transaction_start();
    9.30 -	if (err) {
    9.31 +	xbt = xenbus_transaction_start();
    9.32 +	if (IS_ERR(xbt)) {
    9.33  		xenbus_dev_error(dev, err, "starting transaction");
    9.34  		goto destroy_ring;
    9.35  	}
    9.36  
    9.37 -	err = xenbus_printf(dev->nodename, "tx-ring-ref","%u",
    9.38 +	err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
    9.39  			    info->tx_ring_ref);
    9.40  	if (err) {
    9.41  		message = "writing tx ring-ref";
    9.42  		goto abort_transaction;
    9.43  	}
    9.44 -	err = xenbus_printf(dev->nodename, "rx-ring-ref","%u",
    9.45 +	err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
    9.46  			    info->rx_ring_ref);
    9.47  	if (err) {
    9.48  		message = "writing rx ring-ref";
    9.49  		goto abort_transaction;
    9.50  	}
    9.51 -	err = xenbus_printf(dev->nodename,
    9.52 +	err = xenbus_printf(xbt, dev->nodename,
    9.53  			    "event-channel", "%u", info->evtchn);
    9.54  	if (err) {
    9.55  		message = "writing event-channel";
    9.56  		goto abort_transaction;
    9.57  	}
    9.58  
    9.59 -	err = xenbus_transaction_end(0);
    9.60 +	err = xenbus_transaction_end(xbt, 0);
    9.61  	if (err) {
    9.62  		if (err == -EAGAIN)
    9.63  			goto again;
    9.64 @@ -1177,8 +1178,7 @@ again:
    9.65  	return 0;
    9.66  
    9.67   abort_transaction:
    9.68 -	xenbus_transaction_end(1);
    9.69 -	/* Have to do this *outside* transaction.  */
    9.70 +	xenbus_transaction_end(xbt, 1);
    9.71  	xenbus_dev_error(dev, err, "%s", message);
    9.72   destroy_ring:
    9.73  	shutdown_device(info);
    9.74 @@ -1201,7 +1201,7 @@ static int netfront_probe(struct xenbus_
    9.75  	struct netfront_info *info;
    9.76  	unsigned int handle;
    9.77  
    9.78 -	err = xenbus_scanf(dev->nodename, "handle", "%u", &handle);
    9.79 +	err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle);
    9.80  	if (XENBUS_EXIST_ERR(err))
    9.81  		return err;
    9.82  	if (err < 0) {
    10.1 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Mon Oct 10 14:42:38 2005 +0100
    10.2 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Mon Oct 10 14:46:53 2005 +0100
    10.3 @@ -246,7 +246,10 @@ static int privcmd_ioctl(struct inode *i
    10.4  				   PAGE_SHIFT);
    10.5  		ret = xen_start_info->store_mfn;
    10.6  
    10.7 -		/* We'll return then this will wait for daemon to answer */
    10.8 +		/* 
    10.9 +		** Complete initialization of xenbus (viz. set up the 
   10.10 +		** connection to xenstored now that it has started). 
   10.11 +		*/
   10.12  		kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
   10.13  	}
   10.14  	break;
    11.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Mon Oct 10 14:42:38 2005 +0100
    11.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Mon Oct 10 14:46:53 2005 +0100
    11.3 @@ -66,12 +66,13 @@ static void frontend_changed(struct xenb
    11.4  	unsigned int evtchn;
    11.5  	unsigned long ready = 1;
    11.6  	int err;
    11.7 +	struct xenbus_transaction *xbt;
    11.8  	struct backend_info *be
    11.9  		= container_of(watch, struct backend_info, watch);
   11.10  
   11.11  	/* If other end is gone, delete ourself. */
   11.12 -	if (vec && !xenbus_exists(be->frontpath, "")) {
   11.13 -		xenbus_rm(be->dev->nodename, "");
   11.14 +	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
   11.15 +		xenbus_rm(NULL, be->dev->nodename, "");
   11.16  		device_unregister(&be->dev->dev);
   11.17  		return;
   11.18  	}
   11.19 @@ -79,7 +80,7 @@ static void frontend_changed(struct xenb
   11.20  	if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
   11.21  		return;
   11.22  
   11.23 -	err = xenbus_gather(be->frontpath,
   11.24 +	err = xenbus_gather(NULL, be->frontpath,
   11.25  	                    "ring-ref", "%lu", &ringref,
   11.26  			    "event-channel", "%u", &evtchn, NULL);
   11.27  	if (err) {
   11.28 @@ -115,20 +116,20 @@ static void frontend_changed(struct xenb
   11.29  	 * unless something bad happens
   11.30  	 */
   11.31  again:
   11.32 -	err = xenbus_transaction_start();
   11.33 -	if (err) {
   11.34 +	xbt = xenbus_transaction_start();
   11.35 +	if (IS_ERR(xbt)) {
   11.36  		xenbus_dev_error(be->dev, err, "starting transaction");
   11.37  		return;
   11.38  	}
   11.39  
   11.40 -	err = xenbus_printf(be->dev->nodename,
   11.41 +	err = xenbus_printf(xbt, be->dev->nodename,
   11.42  	                    "ready", "%lu", ready);
   11.43  	if (err) {
   11.44  		xenbus_dev_error(be->dev, err, "writing 'ready'");
   11.45  		goto abort;
   11.46  	}
   11.47  
   11.48 -	err = xenbus_transaction_end(0);
   11.49 +	err = xenbus_transaction_end(xbt, 0);
   11.50  	if (err == -EAGAIN)
   11.51  		goto again;
   11.52  	if (err) {
   11.53 @@ -139,7 +140,7 @@ again:
   11.54  	xenbus_dev_ok(be->dev);
   11.55  	return;
   11.56  abort:
   11.57 -	xenbus_transaction_end(1);
   11.58 +	xenbus_transaction_end(xbt, 1);
   11.59  }
   11.60  
   11.61  
   11.62 @@ -152,7 +153,7 @@ static void backend_changed(struct xenbu
   11.63  		= container_of(watch, struct backend_info, backend_watch);
   11.64  	struct xenbus_device *dev = be->dev;
   11.65  
   11.66 -	err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
   11.67 +	err = xenbus_scanf(NULL, dev->nodename, "instance", "%li", &instance);
   11.68  	if (XENBUS_EXIST_ERR(err))
   11.69  		return;
   11.70  	if (err < 0) {
   11.71 @@ -205,7 +206,7 @@ static int tpmback_probe(struct xenbus_d
   11.72  	memset(be, 0, sizeof(*be));
   11.73  
   11.74  	frontend = NULL;
   11.75 -	err = xenbus_gather(dev->nodename,
   11.76 +	err = xenbus_gather(NULL, dev->nodename,
   11.77  			    "frontend-id", "%li", &be->frontend_id,
   11.78  			    "frontend", NULL, &frontend,
   11.79  			    NULL);
   11.80 @@ -217,7 +218,7 @@ static int tpmback_probe(struct xenbus_d
   11.81  				 dev->nodename);
   11.82  		goto free_be;
   11.83  	}
   11.84 -	if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
   11.85 +	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
   11.86  		/* If we can't get a frontend path and a frontend-id,
   11.87  		 * then our bus-id is no longer valid and we need to
   11.88  		 * destroy the backend device.
    12.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c	Mon Oct 10 14:42:38 2005 +0100
    12.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c	Mon Oct 10 14:46:53 2005 +0100
    12.3 @@ -226,7 +226,7 @@ static void watch_for_status(struct xenb
    12.4  	if (tp->connected)
    12.5  		return;
    12.6  
    12.7 -	err = xenbus_gather(watch->node,
    12.8 +	err = xenbus_gather(NULL, watch->node,
    12.9  	                    "ready", "%lu", &ready,
   12.10  	                    NULL);
   12.11  	if (err) {
   12.12 @@ -311,9 +311,10 @@ static int talk_to_backend(struct xenbus
   12.13  	const char *message;
   12.14  	int err;
   12.15  	int backend_id;
   12.16 +	struct xenbus_transaction *xbt;
   12.17  
   12.18  	backend = NULL;
   12.19 -	err = xenbus_gather(dev->nodename,
   12.20 +	err = xenbus_gather(NULL, dev->nodename,
   12.21  			    "backend-id", "%i", &backend_id,
   12.22  			    "backend", NULL, &backend,
   12.23  			    NULL);
   12.24 @@ -339,27 +340,27 @@ static int talk_to_backend(struct xenbus
   12.25  	}
   12.26  
   12.27  again:
   12.28 -	err = xenbus_transaction_start();
   12.29 -	if (err) {
   12.30 +	xbt = xenbus_transaction_start();
   12.31 +	if (IS_ERR(xbt)) {
   12.32  		xenbus_dev_error(dev, err, "starting transaction");
   12.33  		goto destroy_tpmring;
   12.34  	}
   12.35  
   12.36 -	err = xenbus_printf(dev->nodename,
   12.37 +	err = xenbus_printf(xbt, dev->nodename,
   12.38  	                    "ring-ref","%u", info->ring_ref);
   12.39  	if (err) {
   12.40  		message = "writing ring-ref";
   12.41  		goto abort_transaction;
   12.42  	}
   12.43  
   12.44 -	err = xenbus_printf(dev->nodename,
   12.45 +	err = xenbus_printf(xbt, dev->nodename,
   12.46  			    "event-channel", "%u", my_private.evtchn);
   12.47  	if (err) {
   12.48  		message = "writing event-channel";
   12.49  		goto abort_transaction;
   12.50  	}
   12.51  
   12.52 -	err = xenbus_transaction_end(0);
   12.53 +	err = xenbus_transaction_end(xbt, 0);
   12.54  	if (err == -EAGAIN)
   12.55  		goto again;
   12.56  	if (err) {
   12.57 @@ -380,8 +381,7 @@ again:
   12.58  	return 0;
   12.59  
   12.60  abort_transaction:
   12.61 -	xenbus_transaction_end(1);
   12.62 -	/* Have to do this *outside* transaction.  */
   12.63 +	xenbus_transaction_end(xbt, 1);
   12.64  	xenbus_dev_error(dev, err, "%s", message);
   12.65  destroy_tpmring:
   12.66  	destroy_tpmring(info, &my_private);
   12.67 @@ -399,7 +399,7 @@ static int tpmfront_probe(struct xenbus_
   12.68  	struct tpmfront_info *info;
   12.69  	int handle;
   12.70  
   12.71 -	err = xenbus_scanf(dev->nodename,
   12.72 +	err = xenbus_scanf(NULL, dev->nodename,
   12.73  	                   "handle", "%i", &handle);
   12.74  	if (XENBUS_EXIST_ERR(err))
   12.75  		return err;
    13.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Mon Oct 10 14:42:38 2005 +0100
    13.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Mon Oct 10 14:46:53 2005 +0100
    13.3 @@ -130,15 +130,10 @@ int xb_write(const void *data, unsigned 
    13.4  
    13.5  		wait_event(xb_waitq, output_avail(out));
    13.6  
    13.7 -		/* Read, then check: not that we don't trust store.
    13.8 -		 * Hell, some of my best friends are daemons.  But,
    13.9 -		 * in this post-911 world... */
   13.10 +		mb();
   13.11  		h = *out;
   13.12 -		mb();
   13.13 -		if (!check_buffer(&h)) {
   13.14 -			set_current_state(TASK_RUNNING);
   13.15 -			return -EIO; /* ETERRORIST! */
   13.16 -		}
   13.17 +		if (!check_buffer(&h))
   13.18 +			return -EIO;
   13.19  
   13.20  		dst = get_output_chunk(&h, out->buf, &avail);
   13.21  		if (avail > len)
   13.22 @@ -173,12 +168,11 @@ int xb_read(void *data, unsigned len)
   13.23  		const char *src;
   13.24  
   13.25  		wait_event(xb_waitq, xs_input_avail());
   13.26 -		h = *in;
   13.27 +
   13.28  		mb();
   13.29 -		if (!check_buffer(&h)) {
   13.30 -			set_current_state(TASK_RUNNING);
   13.31 +		h = *in;
   13.32 +		if (!check_buffer(&h))
   13.33  			return -EIO;
   13.34 -		}
   13.35  
   13.36  		src = get_input_chunk(&h, in->buf, &avail);
   13.37  		if (avail > len)
   13.38 @@ -195,10 +189,6 @@ int xb_read(void *data, unsigned len)
   13.39  			notify_remote_via_evtchn(xen_start_info->store_evtchn);
   13.40  	}
   13.41  
   13.42 -	/* If we left something, wake watch thread to deal with it. */
   13.43 -	if (xs_input_avail())
   13.44 -		wake_up(&xb_waitq);
   13.45 -
   13.46  	return 0;
   13.47  }
   13.48  
    14.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Mon Oct 10 14:42:38 2005 +0100
    14.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Mon Oct 10 14:46:53 2005 +0100
    14.3 @@ -46,85 +46,113 @@
    14.4  #include <asm/hypervisor.h>
    14.5  
    14.6  struct xenbus_dev_data {
    14.7 -	/* Are there bytes left to be read in this message? */
    14.8 -	int bytes_left;
    14.9 -	/* Are we still waiting for the reply to a message we wrote? */
   14.10 -	int awaiting_reply;
   14.11 -	/* Buffer for outgoing messages. */
   14.12 +	int in_transaction;
   14.13 +
   14.14 +	/* Partial request. */
   14.15  	unsigned int len;
   14.16  	union {
   14.17  		struct xsd_sockmsg msg;
   14.18  		char buffer[PAGE_SIZE];
   14.19  	} u;
   14.20 +
   14.21 +	/* Response queue. */
   14.22 +#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
   14.23 +	char read_buffer[PAGE_SIZE];
   14.24 +	unsigned int read_cons, read_prod;
   14.25 +	wait_queue_head_t read_waitq;
   14.26  };
   14.27  
   14.28  static struct proc_dir_entry *xenbus_dev_intf;
   14.29  
   14.30 -/* Reply can be long (dir, getperm): don't buffer, just examine
   14.31 - * headers so we can discard rest if they die. */
   14.32  static ssize_t xenbus_dev_read(struct file *filp,
   14.33  			       char __user *ubuf,
   14.34  			       size_t len, loff_t *ppos)
   14.35  {
   14.36 -	struct xenbus_dev_data *data = filp->private_data;
   14.37 -	struct xsd_sockmsg msg;
   14.38 -	int err;
   14.39 -
   14.40 -	/* Refill empty buffer? */
   14.41 -	if (data->bytes_left == 0) {
   14.42 -		if (len < sizeof(msg))
   14.43 -			return -EINVAL;
   14.44 +	struct xenbus_dev_data *u = filp->private_data;
   14.45 +	int i;
   14.46  
   14.47 -		err = xb_read(&msg, sizeof(msg));
   14.48 -		if (err)
   14.49 -			return err;
   14.50 -		data->bytes_left = msg.len;
   14.51 -		if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0)
   14.52 -			return -EFAULT;
   14.53 -		/* We can receive spurious XS_WATCH_EVENT messages. */
   14.54 -		if (msg.type != XS_WATCH_EVENT)
   14.55 -			data->awaiting_reply = 0;
   14.56 -		return sizeof(msg);
   14.57 +	if (wait_event_interruptible(u->read_waitq,
   14.58 +				     u->read_prod != u->read_cons))
   14.59 +		return -EINTR;
   14.60 +
   14.61 +	for (i = 0; i < len; i++) {
   14.62 +		if (u->read_cons == u->read_prod)
   14.63 +			break;
   14.64 +		put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i);
   14.65 +		u->read_cons++;
   14.66  	}
   14.67  
   14.68 -	/* Don't read over next header, or over temporary buffer. */
   14.69 -	if (len > sizeof(data->u.buffer))
   14.70 -		len = sizeof(data->u.buffer);
   14.71 -	if (len > data->bytes_left)
   14.72 -		len = data->bytes_left;
   14.73 -
   14.74 -	err = xb_read(data->u.buffer, len);
   14.75 -	if (err)
   14.76 -		return err;
   14.77 -
   14.78 -	data->bytes_left -= len;
   14.79 -	if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0)
   14.80 -		return -EFAULT;
   14.81 -	return len;
   14.82 +	return i;
   14.83  }
   14.84  
   14.85 -/* We do v. basic sanity checking so they don't screw up kernel later. */
   14.86 +static void queue_reply(struct xenbus_dev_data *u,
   14.87 +			char *data, unsigned int len)
   14.88 +{
   14.89 +	int i;
   14.90 +
   14.91 +	for (i = 0; i < len; i++, u->read_prod++)
   14.92 +		u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
   14.93 +
   14.94 +	BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
   14.95 +
   14.96 +	wake_up(&u->read_waitq);
   14.97 +}
   14.98 +
   14.99  static ssize_t xenbus_dev_write(struct file *filp,
  14.100  				const char __user *ubuf,
  14.101  				size_t len, loff_t *ppos)
  14.102  {
  14.103 -	struct xenbus_dev_data *data = filp->private_data;
  14.104 -	int err;
  14.105 +	struct xenbus_dev_data *u = filp->private_data;
  14.106 +	void *reply;
  14.107 +	int err = 0;
  14.108  
  14.109 -	/* We gather data in buffer until we're ready to send it. */
  14.110 -	if (len > data->len + sizeof(data->u))
  14.111 +	if ((len + u->len) > sizeof(u->u.buffer))
  14.112  		return -EINVAL;
  14.113 -	if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0)
  14.114 +
  14.115 +	if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0)
  14.116  		return -EFAULT;
  14.117 -	data->len += len;
  14.118 -	if (data->len >= sizeof(data->u.msg) + data->u.msg.len) {
  14.119 -		err = xb_write(data->u.buffer, data->len);
  14.120 -		if (err)
  14.121 -			return err;
  14.122 -		data->len = 0;
  14.123 -		data->awaiting_reply = 1;
  14.124 +
  14.125 +	u->len += len;
  14.126 +	if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
  14.127 +		return len;
  14.128 +
  14.129 +	switch (u->u.msg.type) {
  14.130 +	case XS_TRANSACTION_START:
  14.131 +	case XS_TRANSACTION_END:
  14.132 +	case XS_DIRECTORY:
  14.133 +	case XS_READ:
  14.134 +	case XS_GET_PERMS:
  14.135 +	case XS_RELEASE:
  14.136 +	case XS_GET_DOMAIN_PATH:
  14.137 +	case XS_WRITE:
  14.138 +	case XS_MKDIR:
  14.139 +	case XS_RM:
  14.140 +	case XS_SET_PERMS:
  14.141 +		reply = xenbus_dev_request_and_reply(&u->u.msg);
  14.142 +		if (IS_ERR(reply))
  14.143 +			err = PTR_ERR(reply);
  14.144 +		else {
  14.145 +			if (u->u.msg.type == XS_TRANSACTION_START)
  14.146 +				u->in_transaction = 1;
  14.147 +			if (u->u.msg.type == XS_TRANSACTION_END)
  14.148 +				u->in_transaction = 0;
  14.149 +			queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
  14.150 +			queue_reply(u, (char *)reply, u->u.msg.len);
  14.151 +			kfree(reply);
  14.152 +		}
  14.153 +		break;
  14.154 +
  14.155 +	default:
  14.156 +		err = -EINVAL;
  14.157 +		break;
  14.158  	}
  14.159 -	return len;
  14.160 +
  14.161 +	if (err == 0) {
  14.162 +		u->len = 0;
  14.163 +		err = len;
  14.164 +	}
  14.165 +
  14.166 +	return err;
  14.167  }
  14.168  
  14.169  static int xenbus_dev_open(struct inode *inode, struct file *filp)
  14.170 @@ -134,7 +162,6 @@ static int xenbus_dev_open(struct inode 
  14.171  	if (xen_start_info->store_evtchn == 0)
  14.172  		return -ENOENT;
  14.173  
  14.174 -	/* Don't try seeking. */
  14.175  	nonseekable_open(inode, filp);
  14.176  
  14.177  	u = kmalloc(sizeof(*u), GFP_KERNEL);
  14.178 @@ -142,28 +169,21 @@ static int xenbus_dev_open(struct inode 
  14.179  		return -ENOMEM;
  14.180  
  14.181  	memset(u, 0, sizeof(*u));
  14.182 +	init_waitqueue_head(&u->read_waitq);
  14.183  
  14.184  	filp->private_data = u;
  14.185  
  14.186 -	down(&xenbus_lock);
  14.187 -
  14.188  	return 0;
  14.189  }
  14.190  
  14.191  static int xenbus_dev_release(struct inode *inode, struct file *filp)
  14.192  {
  14.193 -	struct xenbus_dev_data *data = filp->private_data;
  14.194 -
  14.195 -	/* Discard any unread replies. */
  14.196 -	while (data->bytes_left || data->awaiting_reply)
  14.197 -		xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL);
  14.198 +	struct xenbus_dev_data *u = filp->private_data;
  14.199  
  14.200 -	/* Harmless if no transaction in progress. */
  14.201 -	xenbus_transaction_end(1);
  14.202 +	if (u->in_transaction)
  14.203 +		xenbus_transaction_end((struct xenbus_transaction *)1, 1);
  14.204  
  14.205 -	up(&xenbus_lock);
  14.206 -
  14.207 -	kfree(data);
  14.208 +	kfree(u);
  14.209  
  14.210  	return 0;
  14.211  }
    15.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Mon Oct 10 14:42:38 2005 +0100
    15.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Mon Oct 10 14:46:53 2005 +0100
    15.3 @@ -43,6 +43,9 @@
    15.4  
    15.5  static struct notifier_block *xenstore_chain;
    15.6  
    15.7 +/* Now used to protect xenbus probes against save/restore. */
    15.8 +static DECLARE_MUTEX(xenbus_lock);
    15.9 +
   15.10  /* If something in array of ids matches this device, return it. */
   15.11  static const struct xenbus_device_id *
   15.12  match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
   15.13 @@ -125,7 +128,7 @@ static int backend_bus_id(char bus_id[BU
   15.14  
   15.15  	devid = strrchr(nodename, '/') + 1;
   15.16  
   15.17 -	err = xenbus_gather(nodename, "frontend-id", "%i", &domid,
   15.18 +	err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
   15.19  			    "frontend", NULL, &frontend,
   15.20  			    NULL);
   15.21  	if (err)
   15.22 @@ -133,7 +136,7 @@ static int backend_bus_id(char bus_id[BU
   15.23  	if (strlen(frontend) == 0)
   15.24  		err = -ERANGE;
   15.25  
   15.26 -	if (!err && !xenbus_exists(frontend, ""))
   15.27 +	if (!err && !xenbus_exists(NULL, frontend, ""))
   15.28  		err = -ENOENT;
   15.29  
   15.30  	if (err) {
   15.31 @@ -447,7 +450,7 @@ static int xenbus_probe_backend(const ch
   15.32  	if (!nodename)
   15.33  		return -ENOMEM;
   15.34  
   15.35 -	dir = xenbus_directory(nodename, "", &dir_n);
   15.36 +	dir = xenbus_directory(NULL, nodename, "", &dir_n);
   15.37  	if (IS_ERR(dir)) {
   15.38  		kfree(nodename);
   15.39  		return PTR_ERR(dir);
   15.40 @@ -470,7 +473,7 @@ static int xenbus_probe_device_type(stru
   15.41  	unsigned int dir_n = 0;
   15.42  	int i;
   15.43  
   15.44 -	dir = xenbus_directory(bus->root, type, &dir_n);
   15.45 +	dir = xenbus_directory(NULL, bus->root, type, &dir_n);
   15.46  	if (IS_ERR(dir))
   15.47  		return PTR_ERR(dir);
   15.48  
   15.49 @@ -489,7 +492,7 @@ static int xenbus_probe_devices(struct x
   15.50  	char **dir;
   15.51  	unsigned int i, dir_n;
   15.52  
   15.53 -	dir = xenbus_directory(bus->root, "", &dir_n);
   15.54 +	dir = xenbus_directory(NULL, bus->root, "", &dir_n);
   15.55  	if (IS_ERR(dir))
   15.56  		return PTR_ERR(dir);
   15.57  
   15.58 @@ -535,7 +538,7 @@ static void dev_changed(const char *node
   15.59  	if (char_count(node, '/') < 2)
   15.60   		return;
   15.61  
   15.62 -	exists = xenbus_exists(node, "");
   15.63 +	exists = xenbus_exists(NULL, node, "");
   15.64  	if (!exists) {
   15.65  		xenbus_cleanup_devices(node, &bus->bus);
   15.66  		return;
   15.67 @@ -625,12 +628,13 @@ void xenbus_suspend(void)
   15.68  	down(&xenbus_lock);
   15.69  	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
   15.70  	bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
   15.71 +	xs_suspend();
   15.72  }
   15.73  
   15.74  void xenbus_resume(void)
   15.75  {
   15.76  	xb_init_comms();
   15.77 -	reregister_xenbus_watches();
   15.78 +	xs_resume();
   15.79  	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
   15.80  	bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
   15.81  	up(&xenbus_lock);
   15.82 @@ -662,12 +666,16 @@ void unregister_xenstore_notifier(struct
   15.83  }
   15.84  EXPORT_SYMBOL(unregister_xenstore_notifier);
   15.85  
   15.86 -/* called from a thread in privcmd/privcmd.c */
   15.87 +/* 
   15.88 +** Called either from below xenbus_probe_init() initcall (for domUs) 
   15.89 +** or, for dom0, from a thread created in privcmd/privcmd.c (after 
   15.90 +** the user-space tools have invoked initDomainStore()) 
   15.91 +*/
   15.92  int do_xenbus_probe(void *unused)
   15.93  {
   15.94  	int err = 0;
   15.95  
   15.96 -	/* Initialize xenstore comms unless already done. */
   15.97 +	/* Initialize the interface to xenstore. */
   15.98  	err = xs_init();
   15.99  	if (err) {
  15.100  		printk("XENBUS: Error initializing xenstore comms:"
  15.101 @@ -685,6 +693,7 @@ int do_xenbus_probe(void *unused)
  15.102  	/* Notify others that xenstore is up */
  15.103  	notifier_call_chain(&xenstore_chain, 0, 0);
  15.104  	up(&xenbus_lock);
  15.105 +
  15.106  	return 0;
  15.107  }
  15.108  
  15.109 @@ -698,6 +707,10 @@ static int __init xenbus_probe_init(void
  15.110  	device_register(&xenbus_frontend.dev);
  15.111  	device_register(&xenbus_backend.dev);
  15.112  
  15.113 +	/* 
  15.114 +	** Domain0 doesn't have a store_evtchn yet - this will
  15.115 +	** be set up later by xend invoking initDomainStore() 
  15.116 +	*/
  15.117  	if (!xen_start_info->store_evtchn)
  15.118  		return 0;
  15.119  
    16.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Mon Oct 10 14:42:38 2005 +0100
    16.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Mon Oct 10 14:46:53 2005 +0100
    16.3 @@ -42,11 +42,67 @@
    16.4  
    16.5  #define streq(a, b) (strcmp((a), (b)) == 0)
    16.6  
    16.7 -static char printf_buffer[4096];
    16.8 -static LIST_HEAD(watches);
    16.9 +struct xs_stored_msg {
   16.10 +	struct xsd_sockmsg hdr;
   16.11 +
   16.12 +	union {
   16.13 +		/* Stored replies. */
   16.14 +		struct {
   16.15 +			struct list_head list;
   16.16 +			char *body;
   16.17 +		} reply;
   16.18 +
   16.19 +		/* Queued watch callbacks. */
   16.20 +		struct {
   16.21 +			struct work_struct work;
   16.22 +			struct xenbus_watch *handle;
   16.23 +			char **vec;
   16.24 +			unsigned int vec_size;
   16.25 +		} watch;
   16.26 +	} u;
   16.27 +};
   16.28 +
   16.29 +struct xs_handle {
   16.30 +	/* A list of replies. Currently only one will ever be outstanding. */
   16.31 +	struct list_head reply_list;
   16.32 +	spinlock_t reply_lock;
   16.33 +	wait_queue_head_t reply_waitq;
   16.34 +
   16.35 +	/* One request at a time. */
   16.36 +	struct semaphore request_mutex;
   16.37  
   16.38 -DECLARE_MUTEX(xenbus_lock);
   16.39 -EXPORT_SYMBOL(xenbus_lock);
   16.40 +	/* One transaction at a time. */
   16.41 +	struct semaphore transaction_mutex;
   16.42 +	int transaction_pid;
   16.43 +};
   16.44 +
   16.45 +static struct xs_handle xs_state;
   16.46 +
   16.47 +static LIST_HEAD(watches);
   16.48 +static DEFINE_SPINLOCK(watches_lock);
   16.49 +
   16.50 +/* Can wait on !xs_resuming for suspend/resume cycle to complete. */
   16.51 +static int xs_resuming;
   16.52 +static DECLARE_WAIT_QUEUE_HEAD(xs_resuming_waitq);
   16.53 +
   16.54 +static void request_mutex_acquire(void)
   16.55 +{
   16.56 +	/*
   16.57 +	 * We can't distinguish non-transactional from transactional
   16.58 +	 * requests right now. So temporarily acquire the transaction mutex
   16.59 +	 * if this task is outside transaction context.
   16.60 + 	 */
   16.61 +	if (xs_state.transaction_pid != current->pid)
   16.62 +		down(&xs_state.transaction_mutex);
   16.63 +	down(&xs_state.request_mutex);
   16.64 +}
   16.65 +
   16.66 +static void request_mutex_release(void)
   16.67 +{
   16.68 +	up(&xs_state.request_mutex);
   16.69 +	if (xs_state.transaction_pid != current->pid)
   16.70 +		up(&xs_state.transaction_mutex);
   16.71 +}
   16.72  
   16.73  static int get_error(const char *errorstring)
   16.74  {
   16.75 @@ -65,29 +121,32 @@ static int get_error(const char *errorst
   16.76  
   16.77  static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
   16.78  {
   16.79 -	struct xsd_sockmsg msg;
   16.80 -	void *ret;
   16.81 -	int err;
   16.82 +	struct xs_stored_msg *msg;
   16.83 +	char *body;
   16.84 +
   16.85 +	spin_lock(&xs_state.reply_lock);
   16.86  
   16.87 -	err = xb_read(&msg, sizeof(msg));
   16.88 -	if (err)
   16.89 -		return ERR_PTR(err);
   16.90 -
   16.91 -	ret = kmalloc(msg.len + 1, GFP_KERNEL);
   16.92 -	if (!ret)
   16.93 -		return ERR_PTR(-ENOMEM);
   16.94 +	while (list_empty(&xs_state.reply_list)) {
   16.95 +		spin_unlock(&xs_state.reply_lock);
   16.96 +		wait_event(xs_state.reply_waitq,
   16.97 +			   !list_empty(&xs_state.reply_list));
   16.98 +		spin_lock(&xs_state.reply_lock);
   16.99 +	}
  16.100  
  16.101 -	err = xb_read(ret, msg.len);
  16.102 -	if (err) {
  16.103 -		kfree(ret);
  16.104 -		return ERR_PTR(err);
  16.105 -	}
  16.106 -	((char*)ret)[msg.len] = '\0';
  16.107 +	msg = list_entry(xs_state.reply_list.next,
  16.108 +			 struct xs_stored_msg, u.reply.list);
  16.109 +	list_del(&msg->u.reply.list);
  16.110 +
  16.111 +	spin_unlock(&xs_state.reply_lock);
  16.112  
  16.113 -	*type = msg.type;
  16.114 +	*type = msg->hdr.type;
  16.115  	if (len)
  16.116 -		*len = msg.len;
  16.117 -	return ret;
  16.118 +		*len = msg->hdr.len;
  16.119 +	body = msg->u.reply.body;
  16.120 +
  16.121 +	kfree(msg);
  16.122 +
  16.123 +	return body;
  16.124  }
  16.125  
  16.126  /* Emergency write. */
  16.127 @@ -98,10 +157,45 @@ void xenbus_debug_write(const char *str,
  16.128  	msg.type = XS_DEBUG;
  16.129  	msg.len = sizeof("print") + count + 1;
  16.130  
  16.131 +	request_mutex_acquire();
  16.132  	xb_write(&msg, sizeof(msg));
  16.133  	xb_write("print", sizeof("print"));
  16.134  	xb_write(str, count);
  16.135  	xb_write("", 1);
  16.136 +	request_mutex_release();
  16.137 +}
  16.138 +
  16.139 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
  16.140 +{
  16.141 +	void *ret;
  16.142 +	struct xsd_sockmsg req_msg = *msg;
  16.143 +	int err;
  16.144 +
  16.145 +	if (req_msg.type == XS_TRANSACTION_START) {
  16.146 +		down(&xs_state.transaction_mutex);
  16.147 +		xs_state.transaction_pid = current->pid;
  16.148 +	}
  16.149 +
  16.150 +	request_mutex_acquire();
  16.151 +
  16.152 +	err = xb_write(msg, sizeof(*msg) + msg->len);
  16.153 +	if (err) {
  16.154 +		msg->type = XS_ERROR;
  16.155 +		ret = ERR_PTR(err);
  16.156 +	} else {
  16.157 +		ret = read_reply(&msg->type, &msg->len);
  16.158 +	}
  16.159 +
  16.160 +	request_mutex_release();
  16.161 +
  16.162 +	if ((msg->type == XS_TRANSACTION_END) ||
  16.163 +	    ((req_msg.type == XS_TRANSACTION_START) &&
  16.164 +	     (msg->type == XS_ERROR))) {
  16.165 +		xs_state.transaction_pid = -1;
  16.166 +		up(&xs_state.transaction_mutex);
  16.167 +	}
  16.168 +
  16.169 +	return ret;
  16.170  }
  16.171  
  16.172  /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
  16.173 @@ -115,31 +209,33 @@ static void *xs_talkv(enum xsd_sockmsg_t
  16.174  	unsigned int i;
  16.175  	int err;
  16.176  
  16.177 -	WARN_ON(down_trylock(&xenbus_lock) == 0);
  16.178 -
  16.179  	msg.type = type;
  16.180  	msg.len = 0;
  16.181  	for (i = 0; i < num_vecs; i++)
  16.182  		msg.len += iovec[i].iov_len;
  16.183  
  16.184 +	request_mutex_acquire();
  16.185 +
  16.186  	err = xb_write(&msg, sizeof(msg));
  16.187 -	if (err)
  16.188 +	if (err) {
  16.189 +		up(&xs_state.request_mutex);
  16.190  		return ERR_PTR(err);
  16.191 +	}
  16.192  
  16.193  	for (i = 0; i < num_vecs; i++) {
  16.194  		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
  16.195 -		if (err)
  16.196 +		if (err) {
  16.197 +			request_mutex_release();
  16.198  			return ERR_PTR(err);
  16.199 +		}
  16.200  	}
  16.201  
  16.202 -	/* Watches can have fired before reply comes: daemon detects
  16.203 -	 * and re-transmits, so we can ignore this. */
  16.204 -	do {
  16.205 -		kfree(ret);
  16.206 -		ret = read_reply(&msg.type, len);
  16.207 -		if (IS_ERR(ret))
  16.208 -			return ret;
  16.209 -	} while (msg.type == XS_WATCH_EVENT);
  16.210 +	ret = read_reply(&msg.type, len);
  16.211 +
  16.212 +	request_mutex_release();
  16.213 +
  16.214 +	if (IS_ERR(ret))
  16.215 +		return ret;
  16.216  
  16.217  	if (msg.type == XS_ERROR) {
  16.218  		err = get_error(ret);
  16.219 @@ -187,8 +283,6 @@ static char *join(const char *dir, const
  16.220  {
  16.221  	static char buffer[4096];
  16.222  
  16.223 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
  16.224 -	/* XXX FIXME: might not be correct if name == "" */
  16.225  	BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
  16.226  
  16.227  	strcpy(buffer, dir);
  16.228 @@ -207,7 +301,7 @@ static char **split(char *strings, unsig
  16.229  	*num = count_strings(strings, len);
  16.230  
  16.231  	/* Transfer to one big alloc for easy freeing. */
  16.232 -	ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
  16.233 +	ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL);
  16.234  	if (!ret) {
  16.235  		kfree(strings);
  16.236  		return ERR_PTR(-ENOMEM);
  16.237 @@ -222,7 +316,8 @@ static char **split(char *strings, unsig
  16.238  	return ret;
  16.239  }
  16.240  
  16.241 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
  16.242 +char **xenbus_directory(struct xenbus_transaction *t,
  16.243 +			const char *dir, const char *node, unsigned int *num)
  16.244  {
  16.245  	char *strings;
  16.246  	unsigned int len;
  16.247 @@ -236,12 +331,13 @@ char **xenbus_directory(const char *dir,
  16.248  EXPORT_SYMBOL(xenbus_directory);
  16.249  
  16.250  /* Check if a path exists. Return 1 if it does. */
  16.251 -int xenbus_exists(const char *dir, const char *node)
  16.252 +int xenbus_exists(struct xenbus_transaction *t,
  16.253 +		  const char *dir, const char *node)
  16.254  {
  16.255  	char **d;
  16.256  	int dir_n;
  16.257  
  16.258 -	d = xenbus_directory(dir, node, &dir_n);
  16.259 +	d = xenbus_directory(t, dir, node, &dir_n);
  16.260  	if (IS_ERR(d))
  16.261  		return 0;
  16.262  	kfree(d);
  16.263 @@ -253,7 +349,8 @@ EXPORT_SYMBOL(xenbus_exists);
  16.264   * Returns a kmalloced value: call free() on it after use.
  16.265   * len indicates length in bytes.
  16.266   */
  16.267 -void *xenbus_read(const char *dir, const char *node, unsigned int *len)
  16.268 +void *xenbus_read(struct xenbus_transaction *t,
  16.269 +		  const char *dir, const char *node, unsigned int *len)
  16.270  {
  16.271  	return xs_single(XS_READ, join(dir, node), len);
  16.272  }
  16.273 @@ -262,7 +359,8 @@ EXPORT_SYMBOL(xenbus_read);
  16.274  /* Write the value of a single file.
  16.275   * Returns -err on failure.
  16.276   */
  16.277 -int xenbus_write(const char *dir, const char *node, const char *string)
  16.278 +int xenbus_write(struct xenbus_transaction *t,
  16.279 +		 const char *dir, const char *node, const char *string)
  16.280  {
  16.281  	const char *path;
  16.282  	struct kvec iovec[2];
  16.283 @@ -279,14 +377,15 @@ int xenbus_write(const char *dir, const 
  16.284  EXPORT_SYMBOL(xenbus_write);
  16.285  
  16.286  /* Create a new directory. */
  16.287 -int xenbus_mkdir(const char *dir, const char *node)
  16.288 +int xenbus_mkdir(struct xenbus_transaction *t,
  16.289 +		 const char *dir, const char *node)
  16.290  {
  16.291  	return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
  16.292  }
  16.293  EXPORT_SYMBOL(xenbus_mkdir);
  16.294  
  16.295  /* Destroy a file or directory (directories must be empty). */
  16.296 -int xenbus_rm(const char *dir, const char *node)
  16.297 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
  16.298  {
  16.299  	return xs_error(xs_single(XS_RM, join(dir, node), NULL));
  16.300  }
  16.301 @@ -294,37 +393,57 @@ EXPORT_SYMBOL(xenbus_rm);
  16.302  
  16.303  /* Start a transaction: changes by others will not be seen during this
  16.304   * transaction, and changes will not be visible to others until end.
  16.305 - * You can only have one transaction at any time.
  16.306   */
  16.307 -int xenbus_transaction_start(void)
  16.308 +struct xenbus_transaction *xenbus_transaction_start(void)
  16.309  {
  16.310 -	return xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
  16.311 +	int err;
  16.312 +
  16.313 +	down(&xs_state.transaction_mutex);
  16.314 +	xs_state.transaction_pid = current->pid;
  16.315 +
  16.316 +	err = xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
  16.317 +	if (err) {
  16.318 +		xs_state.transaction_pid = -1;
  16.319 +		up(&xs_state.transaction_mutex);
  16.320 +	}
  16.321 +
  16.322 +	return err ? ERR_PTR(err) : (struct xenbus_transaction *)1;
  16.323  }
  16.324  EXPORT_SYMBOL(xenbus_transaction_start);
  16.325  
  16.326  /* End a transaction.
  16.327   * If abandon is true, transaction is discarded instead of committed.
  16.328   */
  16.329 -int xenbus_transaction_end(int abort)
  16.330 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort)
  16.331  {
  16.332  	char abortstr[2];
  16.333 +	int err;
  16.334 +
  16.335 +	BUG_ON(t == NULL);
  16.336  
  16.337  	if (abort)
  16.338  		strcpy(abortstr, "F");
  16.339  	else
  16.340  		strcpy(abortstr, "T");
  16.341 -	return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
  16.342 +
  16.343 +	err = xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
  16.344 +
  16.345 +	xs_state.transaction_pid = -1;
  16.346 +	up(&xs_state.transaction_mutex);
  16.347 +
  16.348 +	return err;
  16.349  }
  16.350  EXPORT_SYMBOL(xenbus_transaction_end);
  16.351  
  16.352  /* Single read and scanf: returns -errno or num scanned. */
  16.353 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
  16.354 +int xenbus_scanf(struct xenbus_transaction *t,
  16.355 +		 const char *dir, const char *node, const char *fmt, ...)
  16.356  {
  16.357  	va_list ap;
  16.358  	int ret;
  16.359  	char *val;
  16.360  
  16.361 -	val = xenbus_read(dir, node, NULL);
  16.362 +	val = xenbus_read(t, dir, node, NULL);
  16.363  	if (IS_ERR(val))
  16.364  		return PTR_ERR(val);
  16.365  
  16.366 @@ -340,18 +459,28 @@ int xenbus_scanf(const char *dir, const 
  16.367  EXPORT_SYMBOL(xenbus_scanf);
  16.368  
  16.369  /* Single printf and write: returns -errno or 0. */
  16.370 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
  16.371 +int xenbus_printf(struct xenbus_transaction *t,
  16.372 +		  const char *dir, const char *node, const char *fmt, ...)
  16.373  {
  16.374  	va_list ap;
  16.375  	int ret;
  16.376 +#define PRINTF_BUFFER_SIZE 4096
  16.377 +	char *printf_buffer;
  16.378  
  16.379 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
  16.380 +	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
  16.381 +	if (printf_buffer == NULL)
  16.382 +		return -ENOMEM;
  16.383 +
  16.384  	va_start(ap, fmt);
  16.385 -	ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
  16.386 +	ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
  16.387  	va_end(ap);
  16.388  
  16.389 -	BUG_ON(ret > sizeof(printf_buffer)-1);
  16.390 -	return xenbus_write(dir, node, printf_buffer);
  16.391 +	BUG_ON(ret > PRINTF_BUFFER_SIZE-1);
  16.392 +	ret = xenbus_write(t, dir, node, printf_buffer);
  16.393 +
  16.394 +	kfree(printf_buffer);
  16.395 +
  16.396 +	return ret;
  16.397  }
  16.398  EXPORT_SYMBOL(xenbus_printf);
  16.399  
  16.400 @@ -361,19 +490,28 @@ void xenbus_dev_error(struct xenbus_devi
  16.401  	va_list ap;
  16.402  	int ret;
  16.403  	unsigned int len;
  16.404 +	char *printf_buffer;
  16.405  
  16.406 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
  16.407 +	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
  16.408 +	if (printf_buffer == NULL)
  16.409 +		goto fail;
  16.410  
  16.411  	len = sprintf(printf_buffer, "%i ", -err);
  16.412  	va_start(ap, fmt);
  16.413 -	ret = vsnprintf(printf_buffer+len, sizeof(printf_buffer)-len, fmt, ap);
  16.414 +	ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
  16.415  	va_end(ap);
  16.416  
  16.417 -	BUG_ON(len + ret > sizeof(printf_buffer)-1);
  16.418 +	BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
  16.419  	dev->has_error = 1;
  16.420 -	if (xenbus_write(dev->nodename, "error", printf_buffer) != 0)
  16.421 -		printk("xenbus: failed to write error node for %s (%s)\n",
  16.422 -		       dev->nodename, printf_buffer);
  16.423 +	if (xenbus_write(NULL, dev->nodename, "error", printf_buffer) != 0)
  16.424 +		goto fail;
  16.425 +
  16.426 +	kfree(printf_buffer);
  16.427 +	return;
  16.428 +
  16.429 + fail:
  16.430 +	printk("xenbus: failed to write error node for %s (%s)\n",
  16.431 +	       dev->nodename, printf_buffer);
  16.432  }
  16.433  EXPORT_SYMBOL(xenbus_dev_error);
  16.434  
  16.435 @@ -381,7 +519,7 @@ EXPORT_SYMBOL(xenbus_dev_error);
  16.436  void xenbus_dev_ok(struct xenbus_device *dev)
  16.437  {
  16.438  	if (dev->has_error) {
  16.439 -		if (xenbus_rm(dev->nodename, "error") != 0)
  16.440 +		if (xenbus_rm(NULL, dev->nodename, "error") != 0)
  16.441  			printk("xenbus: failed to clear error node for %s\n",
  16.442  			       dev->nodename);
  16.443  		else
  16.444 @@ -391,7 +529,7 @@ void xenbus_dev_ok(struct xenbus_device 
  16.445  EXPORT_SYMBOL(xenbus_dev_ok);
  16.446  	
  16.447  /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
  16.448 -int xenbus_gather(const char *dir, ...)
  16.449 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...)
  16.450  {
  16.451  	va_list ap;
  16.452  	const char *name;
  16.453 @@ -403,7 +541,7 @@ int xenbus_gather(const char *dir, ...)
  16.454  		void *result = va_arg(ap, void *);
  16.455  		char *p;
  16.456  
  16.457 -		p = xenbus_read(dir, name, NULL);
  16.458 +		p = xenbus_read(t, dir, name, NULL);
  16.459  		if (IS_ERR(p)) {
  16.460  			ret = PTR_ERR(p);
  16.461  			break;
  16.462 @@ -432,26 +570,6 @@ static int xs_watch(const char *path, co
  16.463  	return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
  16.464  }
  16.465  
  16.466 -static char **xs_read_watch(unsigned int *num)
  16.467 -{
  16.468 -	enum xsd_sockmsg_type type;
  16.469 -	char *strings;
  16.470 -	unsigned int len;
  16.471 -
  16.472 -	strings = read_reply(&type, &len);
  16.473 -	if (IS_ERR(strings))
  16.474 -		return (char **)strings;
  16.475 -
  16.476 -	BUG_ON(type != XS_WATCH_EVENT);
  16.477 -
  16.478 -	return split(strings, len, num);
  16.479 -}
  16.480 -
  16.481 -static int xs_acknowledge_watch(const char *token)
  16.482 -{
  16.483 -	return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
  16.484 -}
  16.485 -
  16.486  static int xs_unwatch(const char *path, const char *token)
  16.487  {
  16.488  	struct kvec iov[2];
  16.489 @@ -464,7 +582,6 @@ static int xs_unwatch(const char *path, 
  16.490  	return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
  16.491  }
  16.492  
  16.493 -/* A little paranoia: we don't just trust token. */
  16.494  static struct xenbus_watch *find_watch(const char *token)
  16.495  {
  16.496  	struct xenbus_watch *i, *cmp;
  16.497 @@ -474,6 +591,7 @@ static struct xenbus_watch *find_watch(c
  16.498  	list_for_each_entry(i, &watches, list)
  16.499  		if (i == cmp)
  16.500  			return i;
  16.501 +
  16.502  	return NULL;
  16.503  }
  16.504  
  16.505 @@ -485,11 +603,20 @@ int register_xenbus_watch(struct xenbus_
  16.506  	int err;
  16.507  
  16.508  	sprintf(token, "%lX", (long)watch);
  16.509 +
  16.510 +	spin_lock(&watches_lock);
  16.511  	BUG_ON(find_watch(token));
  16.512 +	spin_unlock(&watches_lock);
  16.513  
  16.514  	err = xs_watch(watch->node, token);
  16.515 -	if (!err)
  16.516 +
  16.517 +	/* Ignore errors due to multiple registration. */
  16.518 +	if ((err == 0) || (err == -EEXIST)) {
  16.519 +		spin_lock(&watches_lock);
  16.520  		list_add(&watch->list, &watches);
  16.521 +		spin_unlock(&watches_lock);
  16.522 +	}
  16.523 +
  16.524  	return err;
  16.525  }
  16.526  EXPORT_SYMBOL(register_xenbus_watch);
  16.527 @@ -500,77 +627,192 @@ void unregister_xenbus_watch(struct xenb
  16.528  	int err;
  16.529  
  16.530  	sprintf(token, "%lX", (long)watch);
  16.531 +
  16.532 +	spin_lock(&watches_lock);
  16.533  	BUG_ON(!find_watch(token));
  16.534 +	list_del(&watch->list);
  16.535 +	spin_unlock(&watches_lock);
  16.536 +
  16.537 +	/* Ensure xs_resume() is not in progress (see comments there). */
  16.538 +	wait_event(xs_resuming_waitq, !xs_resuming);
  16.539  
  16.540  	err = xs_unwatch(watch->node, token);
  16.541 -	list_del(&watch->list);
  16.542 -
  16.543  	if (err)
  16.544  		printk(KERN_WARNING
  16.545  		       "XENBUS Failed to release watch %s: %i\n",
  16.546  		       watch->node, err);
  16.547 +
  16.548 +	/* Make sure watch is not in use. */
  16.549 +	flush_scheduled_work();
  16.550  }
  16.551  EXPORT_SYMBOL(unregister_xenbus_watch);
  16.552  
  16.553 -/* Re-register callbacks to all watches. */
  16.554 -void reregister_xenbus_watches(void)
  16.555 +void xs_suspend(void)
  16.556  {
  16.557 +	down(&xs_state.transaction_mutex);
  16.558 +	down(&xs_state.request_mutex);
  16.559 +}
  16.560 +
  16.561 +void xs_resume(void)
  16.562 +{
  16.563 +	struct list_head *ent, *prev_ent = &watches;
  16.564  	struct xenbus_watch *watch;
  16.565  	char token[sizeof(watch) * 2 + 1];
  16.566  
  16.567 -	list_for_each_entry(watch, &watches, list) {
  16.568 -		sprintf(token, "%lX", (long)watch);
  16.569 -		xs_watch(watch->node, token);
  16.570 +	/* Protect against concurrent unregistration and freeing of watches. */
  16.571 +	BUG_ON(xs_resuming);
  16.572 +	xs_resuming = 1;
  16.573 +
  16.574 +	up(&xs_state.request_mutex);
  16.575 +	up(&xs_state.transaction_mutex);
  16.576 +
  16.577 +	/*
  16.578 +	 * Iterate over the watch list re-registering each node. We must
  16.579 +	 * be careful about concurrent registrations and unregistrations.
  16.580 +	 * We search for the node immediately following the previously
  16.581 +	 * re-registered node. If we get no match then either we are done
  16.582 +	 * (previous node is last in list) or the node was unregistered, in
  16.583 +	 * which case we restart from the beginning of the list.
  16.584 +	 * register_xenbus_watch() + unregister_xenbus_watch() is safe because
  16.585 +	 * it will only ever move a watch node earlier in the list, so it
  16.586 +	 * cannot cause us to skip nodes.
  16.587 +	 */
  16.588 +	for (;;) {
  16.589 +		spin_lock(&watches_lock);
  16.590 +		list_for_each(ent, &watches)
  16.591 +			if (ent->prev == prev_ent)
  16.592 +				break;
  16.593 +		spin_unlock(&watches_lock);
  16.594 +
  16.595 +		/* No match because prev_ent is at the end of the list? */
  16.596 +		if ((ent == &watches) && (watches.prev == prev_ent))
  16.597 +			 break; /* We're done! */
  16.598 +
  16.599 +		if ((prev_ent = ent) != &watches) {
  16.600 +			/*
  16.601 +			 * Safe even with watch_lock not held. We are saved by
  16.602 +			 * (xs_resumed==1) check in unregister_xenbus_watch.
  16.603 +			 */
  16.604 +			watch = list_entry(ent, struct xenbus_watch, list);
  16.605 +			sprintf(token, "%lX", (long)watch);
  16.606 +			xs_watch(watch->node, token);
  16.607 +		}
  16.608 +	}
  16.609 +
  16.610 +	xs_resuming = 0;
  16.611 +	wake_up(&xs_resuming_waitq);
  16.612 +}
  16.613 +
  16.614 +static void xenbus_fire_watch(void *arg)
  16.615 +{
  16.616 +	struct xs_stored_msg *msg = arg;
  16.617 +
  16.618 +	msg->u.watch.handle->callback(msg->u.watch.handle,
  16.619 +				      (const char **)msg->u.watch.vec,
  16.620 +				      msg->u.watch.vec_size);
  16.621 +
  16.622 +	kfree(msg->u.watch.vec);
  16.623 +	kfree(msg);
  16.624 +}
  16.625 +
  16.626 +static int process_msg(void)
  16.627 +{
  16.628 +	struct xs_stored_msg *msg;
  16.629 +	char *body;
  16.630 +	int err;
  16.631 +
  16.632 +	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
  16.633 +	if (msg == NULL)
  16.634 +		return -ENOMEM;
  16.635 +
  16.636 +	err = xb_read(&msg->hdr, sizeof(msg->hdr));
  16.637 +	if (err) {
  16.638 +		kfree(msg);
  16.639 +		return err;
  16.640 +	}
  16.641 +
  16.642 +	body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
  16.643 +	if (body == NULL) {
  16.644 +		kfree(msg);
  16.645 +		return -ENOMEM;
  16.646 +	}
  16.647 +
  16.648 +	err = xb_read(body, msg->hdr.len);
  16.649 +	if (err) {
  16.650 +		kfree(body);
  16.651 +		kfree(msg);
  16.652 +		return err;
  16.653 +	}
  16.654 +	body[msg->hdr.len] = '\0';
  16.655 +
  16.656 +	if (msg->hdr.type == XS_WATCH_EVENT) {
  16.657 +		INIT_WORK(&msg->u.watch.work, xenbus_fire_watch, msg);
  16.658 +
  16.659 +		msg->u.watch.vec = split(body, msg->hdr.len,
  16.660 +					 &msg->u.watch.vec_size);
  16.661 +		if (IS_ERR(msg->u.watch.vec)) {
  16.662 +			kfree(msg);
  16.663 +			return PTR_ERR(msg->u.watch.vec);
  16.664 +		}
  16.665 +
  16.666 +		spin_lock(&watches_lock);
  16.667 +		msg->u.watch.handle = find_watch(
  16.668 +			msg->u.watch.vec[XS_WATCH_TOKEN]);
  16.669 +		if (msg->u.watch.handle != NULL) {
  16.670 +			schedule_work(&msg->u.watch.work);
  16.671 +		} else {
  16.672 +			kfree(msg->u.watch.vec);
  16.673 +			kfree(msg);
  16.674 +		}
  16.675 +		spin_unlock(&watches_lock);
  16.676 +	} else {
  16.677 +		msg->u.reply.body = body;
  16.678 +		spin_lock(&xs_state.reply_lock);
  16.679 +		list_add_tail(&msg->u.reply.list, &xs_state.reply_list);
  16.680 +		spin_unlock(&xs_state.reply_lock);
  16.681 +		wake_up(&xs_state.reply_waitq);
  16.682 +	}
  16.683 +
  16.684 +	return 0;
  16.685 +}
  16.686 +
  16.687 +static int read_thread(void *unused)
  16.688 +{
  16.689 +	int err;
  16.690 +
  16.691 +	for (;;) {
  16.692 +		err = process_msg();
  16.693 +		if (err)
  16.694 +			printk(KERN_WARNING "XENBUS error %d while reading "
  16.695 +			       "message\n", err);
  16.696  	}
  16.697  }
  16.698  
  16.699 -static int watch_thread(void *unused)
  16.700 -{
  16.701 -	for (;;) {
  16.702 -		char **vec = NULL;
  16.703 -		unsigned int num;
  16.704 -
  16.705 -		wait_event(xb_waitq, xs_input_avail());
  16.706 -
  16.707 -		/* If this is a spurious wakeup caused by someone
  16.708 -		 * doing an op, they'll hold the lock and the buffer
  16.709 -		 * will be empty by the time we get there.		 
  16.710 -		 */
  16.711 -		down(&xenbus_lock);
  16.712 -		if (xs_input_avail())
  16.713 -			vec = xs_read_watch(&num);
  16.714 -
  16.715 -		if (vec && !IS_ERR(vec)) {
  16.716 -			struct xenbus_watch *w;
  16.717 -			int err;
  16.718 -
  16.719 -			err = xs_acknowledge_watch(vec[XS_WATCH_TOKEN]);
  16.720 -			if (err)
  16.721 -				printk(KERN_WARNING "XENBUS ack %s fail %i\n",
  16.722 -				       vec[XS_WATCH_TOKEN], err);
  16.723 -			w = find_watch(vec[XS_WATCH_TOKEN]);
  16.724 -			BUG_ON(!w);
  16.725 -			w->callback(w, (const char **)vec, num);
  16.726 -			kfree(vec);
  16.727 -		} else if (vec)
  16.728 -			printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
  16.729 -			       PTR_ERR(vec));
  16.730 -		up(&xenbus_lock);
  16.731 -	}
  16.732 -}
  16.733 -
  16.734 +/*
  16.735 +** Initialize the interface to xenstore. 
  16.736 +*/
  16.737  int xs_init(void)
  16.738  {
  16.739  	int err;
  16.740 -	struct task_struct *watcher;
  16.741 +	struct task_struct *reader;
  16.742 +
  16.743 +	INIT_LIST_HEAD(&xs_state.reply_list);
  16.744 +	spin_lock_init(&xs_state.reply_lock);
  16.745 +	init_waitqueue_head(&xs_state.reply_waitq);
  16.746  
  16.747 +	init_MUTEX(&xs_state.request_mutex);
  16.748 +	init_MUTEX(&xs_state.transaction_mutex);
  16.749 +	xs_state.transaction_pid = -1;
  16.750 +
  16.751 +	/* Initialize the shared memory rings to talk to xenstored */
  16.752  	err = xb_init_comms();
  16.753  	if (err)
  16.754  		return err;
  16.755  	
  16.756 -	watcher = kthread_run(watch_thread, NULL, "kxbwatch");
  16.757 -	if (IS_ERR(watcher))
  16.758 -		return PTR_ERR(watcher);
  16.759 +	reader = kthread_run(read_thread, NULL, "xenbusd");
  16.760 +	if (IS_ERR(reader))
  16.761 +		return PTR_ERR(reader);
  16.762 +
  16.763  	return 0;
  16.764  }
  16.765  
    17.1 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Mon Oct 10 14:42:38 2005 +0100
    17.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Mon Oct 10 14:46:53 2005 +0100
    17.3 @@ -78,30 +78,35 @@ int xenbus_register_driver(struct xenbus
    17.4  int xenbus_register_backend(struct xenbus_driver *drv);
    17.5  void xenbus_unregister_driver(struct xenbus_driver *drv);
    17.6  
    17.7 -/* Caller must hold this lock to call these functions: it's also held
    17.8 - * across watch callbacks. */
    17.9 -extern struct semaphore xenbus_lock;
   17.10 +struct xenbus_transaction;
   17.11  
   17.12 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
   17.13 -void *xenbus_read(const char *dir, const char *node, unsigned int *len);
   17.14 -int xenbus_write(const char *dir, const char *node, const char *string);
   17.15 -int xenbus_mkdir(const char *dir, const char *node);
   17.16 -int xenbus_exists(const char *dir, const char *node);
   17.17 -int xenbus_rm(const char *dir, const char *node);
   17.18 -int xenbus_transaction_start(void);
   17.19 -int xenbus_transaction_end(int abort);
   17.20 +char **xenbus_directory(struct xenbus_transaction *t,
   17.21 +			const char *dir, const char *node, unsigned int *num);
   17.22 +void *xenbus_read(struct xenbus_transaction *t,
   17.23 +		  const char *dir, const char *node, unsigned int *len);
   17.24 +int xenbus_write(struct xenbus_transaction *t,
   17.25 +		 const char *dir, const char *node, const char *string);
   17.26 +int xenbus_mkdir(struct xenbus_transaction *t,
   17.27 +		 const char *dir, const char *node);
   17.28 +int xenbus_exists(struct xenbus_transaction *t,
   17.29 +		  const char *dir, const char *node);
   17.30 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node);
   17.31 +struct xenbus_transaction *xenbus_transaction_start(void);
   17.32 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort);
   17.33  
   17.34  /* Single read and scanf: returns -errno or num scanned if > 0. */
   17.35 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
   17.36 -	__attribute__((format(scanf, 3, 4)));
   17.37 +int xenbus_scanf(struct xenbus_transaction *t,
   17.38 +		 const char *dir, const char *node, const char *fmt, ...)
   17.39 +	__attribute__((format(scanf, 4, 5)));
   17.40  
   17.41  /* Single printf and write: returns -errno or 0. */
   17.42 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
   17.43 -	__attribute__((format(printf, 3, 4)));
   17.44 +int xenbus_printf(struct xenbus_transaction *t,
   17.45 +		  const char *dir, const char *node, const char *fmt, ...)
   17.46 +	__attribute__((format(printf, 4, 5)));
   17.47  
   17.48  /* Generic read function: NULL-terminated triples of name,
   17.49   * sprintf-style type string, and pointer. Returns 0 or errno.*/
   17.50 -int xenbus_gather(const char *dir, ...);
   17.51 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...);
   17.52  
   17.53  /* Report a (negative) errno into the store, with explanation. */
   17.54  void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,...);
   17.55 @@ -113,7 +118,11 @@ void xenbus_dev_ok(struct xenbus_device 
   17.56  struct xenbus_watch
   17.57  {
   17.58  	struct list_head list;
   17.59 +
   17.60 +	/* Path being watched. */
   17.61  	char *node;
   17.62 +
   17.63 +	/* Callback (executed in a process context with no locks held). */
   17.64  	void (*callback)(struct xenbus_watch *,
   17.65  			 const char **vec, unsigned int len);
   17.66  };
   17.67 @@ -124,7 +133,11 @@ void unregister_xenstore_notifier(struct
   17.68  
   17.69  int register_xenbus_watch(struct xenbus_watch *watch);
   17.70  void unregister_xenbus_watch(struct xenbus_watch *watch);
   17.71 -void reregister_xenbus_watches(void);
   17.72 +void xs_suspend(void);
   17.73 +void xs_resume(void);
   17.74 +
   17.75 +/* Used by xenbus_dev to borrow kernel's store connection. */
   17.76 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
   17.77  
   17.78  /* Called from xen core code. */
   17.79  void xenbus_suspend(void);
    18.1 --- a/tools/blktap/xenbus.c	Mon Oct 10 14:42:38 2005 +0100
    18.2 +++ b/tools/blktap/xenbus.c	Mon Oct 10 14:46:53 2005 +0100
    18.3 @@ -260,10 +260,6 @@ int xs_fire_next_watch(struct xs_handle 
    18.4      node  = res[XS_WATCH_PATH];
    18.5      token = res[XS_WATCH_TOKEN];
    18.6  
    18.7 -    er = xs_acknowledge_watch(h, token);
    18.8 -    if (er == 0)
    18.9 -        warn("Couldn't acknowledge watch (%s)", token);
   18.10 -
   18.11      w = find_watch(token);
   18.12      if (!w)
   18.13      {
    19.1 --- a/tools/console/client/main.c	Mon Oct 10 14:42:38 2005 +0100
    19.2 +++ b/tools/console/client/main.c	Mon Oct 10 14:46:53 2005 +0100
    19.3 @@ -220,7 +220,7 @@ int main(int argc, char **argv)
    19.4  	if (path == NULL)
    19.5  		err(ENOMEM, "realloc");
    19.6  	strcat(path, "/console/tty");
    19.7 -	str_pty = xs_read(xs, path, &len);
    19.8 +	str_pty = xs_read(xs, NULL, path, &len);
    19.9  
   19.10  	/* FIXME consoled currently does not assume domain-0 doesn't have a
   19.11  	   console which is good when we break domain-0 up.  To keep us
   19.12 @@ -245,7 +245,7 @@ int main(int argc, char **argv)
   19.13  		struct timeval tv = { 0, 500 };
   19.14  		select(0, NULL, NULL, NULL, &tv); /* pause briefly */
   19.15  
   19.16 -		str_pty = xs_read(xs, path, &len);
   19.17 +		str_pty = xs_read(xs, NULL, path, &len);
   19.18  	}
   19.19  
   19.20  	if (str_pty == NULL) {
    20.1 --- a/tools/console/daemon/io.c	Mon Oct 10 14:42:38 2005 +0100
    20.2 +++ b/tools/console/daemon/io.c	Mon Oct 10 14:46:53 2005 +0100
    20.3 @@ -179,7 +179,7 @@ static int domain_create_tty(struct doma
    20.4  		success = asprintf(&path, "%s/tty", dom->conspath) != -1;
    20.5  		if (!success)
    20.6  			goto out;
    20.7 -		success = xs_write(xs, path, slave, strlen(slave));
    20.8 +		success = xs_write(xs, NULL, path, slave, strlen(slave));
    20.9  		free(path);
   20.10  		if (!success)
   20.11  			goto out;
   20.12 @@ -187,7 +187,7 @@ static int domain_create_tty(struct doma
   20.13  		success = asprintf(&path, "%s/limit", dom->conspath) != -1;
   20.14  		if (!success)
   20.15  			goto out;
   20.16 -		data = xs_read(xs, path, &len);
   20.17 +		data = xs_read(xs, NULL, path, &len);
   20.18  		if (data) {
   20.19  			dom->buffer.max_capacity = strtoul(data, 0, 0);
   20.20  			free(data);
   20.21 @@ -216,7 +216,7 @@ int xs_gather(struct xs_handle *xs, cons
   20.22  		char *p;
   20.23  
   20.24  		asprintf(&path, "%s/%s", dir, name);
   20.25 -		p = xs_read(xs, path, NULL);
   20.26 +		p = xs_read(xs, NULL, path, NULL);
   20.27  		free(path);
   20.28  		if (p == NULL) {
   20.29  			ret = ENOENT;
   20.30 @@ -505,7 +505,6 @@ static void handle_xs(int fd)
   20.31  			domain_create_ring(dom);
   20.32  	}
   20.33  
   20.34 -	xs_acknowledge_watch(xs, vec[1]);
   20.35  	free(vec);
   20.36  }
   20.37  
    21.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Mon Oct 10 14:42:38 2005 +0100
    21.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Mon Oct 10 14:46:53 2005 +0100
    21.3 @@ -80,8 +80,8 @@ static inline PyObject *pyvalue_str(char
    21.4  
    21.5  static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
    21.6  {
    21.7 -    static char *kwd_spec[] = { "path", NULL };
    21.8 -    static char *arg_spec = "s|";
    21.9 +    static char *kwd_spec[] = { "transaction", "path", NULL };
   21.10 +    static char *arg_spec = "ss";
   21.11      char *path = NULL;
   21.12  
   21.13      struct xs_handle *xh = xshandle(self);
   21.14 @@ -89,13 +89,19 @@ static PyObject *xspy_read(PyObject *sel
   21.15      unsigned int xsval_n = 0;
   21.16      PyObject *val = NULL;
   21.17  
   21.18 +    struct xs_transaction_handle *th;
   21.19 +    char *thstr;
   21.20 +
   21.21      if (!xh)
   21.22          goto exit;
   21.23      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   21.24 -                                     &path))
   21.25 +                                     &thstr, &path))
   21.26          goto exit;
   21.27 +
   21.28 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   21.29 +
   21.30      Py_BEGIN_ALLOW_THREADS
   21.31 -    xsval = xs_read(xh, path, &xsval_n);
   21.32 +    xsval = xs_read(xh, th, path, &xsval_n);
   21.33      Py_END_ALLOW_THREADS
   21.34      if (!xsval) {
   21.35          if (errno == ENOENT) {
   21.36 @@ -123,8 +129,8 @@ static PyObject *xspy_read(PyObject *sel
   21.37  
   21.38  static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
   21.39  {
   21.40 -    static char *kwd_spec[] = { "path", "data", NULL };
   21.41 -    static char *arg_spec = "ss#";
   21.42 +    static char *kwd_spec[] = { "transaction", "path", "data", NULL };
   21.43 +    static char *arg_spec = "sss#";
   21.44      char *path = NULL;
   21.45      char *data = NULL;
   21.46      int data_n = 0;
   21.47 @@ -133,13 +139,19 @@ static PyObject *xspy_write(PyObject *se
   21.48      PyObject *val = NULL;
   21.49      int xsval = 0;
   21.50  
   21.51 +    struct xs_transaction_handle *th;
   21.52 +    char *thstr;
   21.53 +
   21.54      if (!xh)
   21.55          goto exit;
   21.56      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   21.57 -                                     &path, &data, &data_n))
   21.58 +                                     &thstr, &path, &data, &data_n))
   21.59          goto exit;
   21.60 +
   21.61 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   21.62 +
   21.63      Py_BEGIN_ALLOW_THREADS
   21.64 -    xsval = xs_write(xh, path, data, data_n);
   21.65 +    xsval = xs_write(xh, th, path, data, data_n);
   21.66      Py_END_ALLOW_THREADS
   21.67      if (!xsval) {
   21.68          PyErr_SetFromErrno(PyExc_RuntimeError);
   21.69 @@ -162,8 +174,8 @@ static PyObject *xspy_write(PyObject *se
   21.70  
   21.71  static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
   21.72  {
   21.73 -    static char *kwd_spec[] = { "path", NULL };
   21.74 -    static char *arg_spec = "s|";
   21.75 +    static char *kwd_spec[] = { "transaction", "path", NULL };
   21.76 +    static char *arg_spec = "ss";
   21.77      char *path = NULL;
   21.78  
   21.79      struct xs_handle *xh = xshandle(self);
   21.80 @@ -172,12 +184,20 @@ static PyObject *xspy_ls(PyObject *self,
   21.81      unsigned int xsval_n = 0;
   21.82      int i;
   21.83  
   21.84 +    struct xs_transaction_handle *th;
   21.85 +    char *thstr;
   21.86 +
   21.87      if (!xh)
   21.88          goto exit;
   21.89 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
   21.90 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   21.91 +                                     &thstr, &path))
   21.92          goto exit;
   21.93 +
   21.94 +
   21.95 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   21.96 +
   21.97      Py_BEGIN_ALLOW_THREADS
   21.98 -    xsval = xs_directory(xh, path, &xsval_n);
   21.99 +    xsval = xs_directory(xh, th, path, &xsval_n);
  21.100      Py_END_ALLOW_THREADS
  21.101      if (!xsval) {
  21.102          if (errno == ENOENT) {
  21.103 @@ -205,20 +225,27 @@ static PyObject *xspy_ls(PyObject *self,
  21.104  
  21.105  static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
  21.106  {
  21.107 -    static char *kwd_spec[] = { "path", NULL };
  21.108 -    static char *arg_spec = "s|";
  21.109 +    static char *kwd_spec[] = { "transaction", "path", NULL };
  21.110 +    static char *arg_spec = "ss";
  21.111      char *path = NULL;
  21.112  
  21.113      struct xs_handle *xh = xshandle(self);
  21.114      PyObject *val = NULL;
  21.115      int xsval = 0;
  21.116  
  21.117 +    struct xs_transaction_handle *th;
  21.118 +    char *thstr;
  21.119 +
  21.120      if (!xh)
  21.121          goto exit;
  21.122 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.123 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  21.124 +                                     &thstr, &path))
  21.125          goto exit;
  21.126 +
  21.127 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  21.128 +
  21.129      Py_BEGIN_ALLOW_THREADS
  21.130 -    xsval = xs_mkdir(xh, path);
  21.131 +    xsval = xs_mkdir(xh, th, path);
  21.132      Py_END_ALLOW_THREADS
  21.133      if (!xsval) {
  21.134          PyErr_SetFromErrno(PyExc_RuntimeError);
  21.135 @@ -240,20 +267,27 @@ static PyObject *xspy_mkdir(PyObject *se
  21.136  
  21.137  static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
  21.138  {
  21.139 -    static char *kwd_spec[] = { "path", NULL };
  21.140 -    static char *arg_spec = "s|";
  21.141 +    static char *kwd_spec[] = { "transaction", "path", NULL };
  21.142 +    static char *arg_spec = "ss";
  21.143      char *path = NULL;
  21.144  
  21.145      struct xs_handle *xh = xshandle(self);
  21.146      PyObject *val = NULL;
  21.147      int xsval = 0;
  21.148  
  21.149 +    struct xs_transaction_handle *th;
  21.150 +    char *thstr;
  21.151 +
  21.152      if (!xh)
  21.153          goto exit;
  21.154 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.155 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  21.156 +                                     &thstr, &path))
  21.157          goto exit;
  21.158 +
  21.159 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  21.160 +
  21.161      Py_BEGIN_ALLOW_THREADS
  21.162 -    xsval = xs_rm(xh, path);
  21.163 +    xsval = xs_rm(xh, th, path);
  21.164      Py_END_ALLOW_THREADS
  21.165      if (!xsval && errno != ENOENT) {
  21.166          PyErr_SetFromErrno(PyExc_RuntimeError);
  21.167 @@ -276,8 +310,8 @@ static PyObject *xspy_rm(PyObject *self,
  21.168  static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
  21.169                                        PyObject *kwds)
  21.170  {
  21.171 -    static char *kwd_spec[] = { "path", NULL };
  21.172 -    static char *arg_spec = "s|";
  21.173 +    static char *kwd_spec[] = { "transaction", "path", NULL };
  21.174 +    static char *arg_spec = "ss";
  21.175      char *path = NULL;
  21.176  
  21.177      struct xs_handle *xh = xshandle(self);
  21.178 @@ -286,12 +320,19 @@ static PyObject *xspy_get_permissions(Py
  21.179      unsigned int perms_n = 0;
  21.180      int i;
  21.181  
  21.182 +    struct xs_transaction_handle *th;
  21.183 +    char *thstr;
  21.184 +
  21.185      if (!xh)
  21.186          goto exit;
  21.187 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.188 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  21.189 +                                     &thstr, &path))
  21.190          goto exit;
  21.191 +
  21.192 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  21.193 +
  21.194      Py_BEGIN_ALLOW_THREADS
  21.195 -    perms = xs_get_permissions(xh, path, &perms_n);
  21.196 +    perms = xs_get_permissions(xh, th, path, &perms_n);
  21.197      Py_END_ALLOW_THREADS
  21.198      if (!perms) {
  21.199          PyErr_SetFromErrno(PyExc_RuntimeError);
  21.200 @@ -321,8 +362,8 @@ static PyObject *xspy_get_permissions(Py
  21.201  static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
  21.202                                        PyObject *kwds)
  21.203  {
  21.204 -    static char *kwd_spec[] = { "path", "perms", NULL };
  21.205 -    static char *arg_spec = "sO";
  21.206 +    static char *kwd_spec[] = { "transaction", "path", "perms", NULL };
  21.207 +    static char *arg_spec = "ssO";
  21.208      char *path = NULL;
  21.209      PyObject *perms = NULL;
  21.210      static char *perm_names[] = { "dom", "read", "write", NULL };
  21.211 @@ -335,11 +376,17 @@ static PyObject *xspy_set_permissions(Py
  21.212      PyObject *tuple0 = NULL;
  21.213      PyObject *val = NULL;
  21.214  
  21.215 +    struct xs_transaction_handle *th;
  21.216 +    char *thstr;
  21.217 +
  21.218      if (!xh)
  21.219          goto exit;
  21.220      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  21.221 -                                     &path, &perms))
  21.222 +                                     &thstr, &path, &perms))
  21.223          goto exit;
  21.224 +
  21.225 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  21.226 +
  21.227      if (!PyList_Check(perms)) {
  21.228          PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
  21.229          goto exit;
  21.230 @@ -369,7 +416,7 @@ static PyObject *xspy_set_permissions(Py
  21.231              xsperms[i].perms |= XS_PERM_WRITE;
  21.232      }
  21.233      Py_BEGIN_ALLOW_THREADS
  21.234 -    xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
  21.235 +    xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
  21.236      Py_END_ALLOW_THREADS
  21.237      if (!xsval) {
  21.238          PyErr_SetFromErrno(PyExc_RuntimeError);
  21.239 @@ -442,9 +489,6 @@ static PyObject *xspy_watch(PyObject *se
  21.240  
  21.241  #define xspy_read_watch_doc "\n"				\
  21.242  	"Read a watch notification.\n"				\
  21.243 -	"The notification must be acknowledged by passing\n"	\
  21.244 -	"the token to acknowledge_watch().\n"			\
  21.245 -	" path [string]: xenstore path.\n"			\
  21.246  	"\n"							\
  21.247  	"Returns: [tuple] (path, token).\n"			\
  21.248  	"Raises RuntimeError on error.\n"			\
  21.249 @@ -495,44 +539,6 @@ static PyObject *xspy_read_watch(PyObjec
  21.250      return val;
  21.251  }
  21.252  
  21.253 -#define xspy_acknowledge_watch_doc "\n"					\
  21.254 -	"Acknowledge a watch notification that has been read.\n"	\
  21.255 -	" token [string] : from the watch notification\n"		\
  21.256 -	"\n"								\
  21.257 -	"Returns None on success.\n"					\
  21.258 -	"Raises RuntimeError on error.\n"				\
  21.259 -	"\n"
  21.260 -
  21.261 -static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
  21.262 -                                        PyObject *kwds)
  21.263 -{
  21.264 -    static char *kwd_spec[] = { "token", NULL };
  21.265 -    static char *arg_spec = "O";
  21.266 -    PyObject *token;
  21.267 -    char token_str[MAX_STRLEN(unsigned long) + 1];
  21.268 -
  21.269 -    struct xs_handle *xh = xshandle(self);
  21.270 -    PyObject *val = NULL;
  21.271 -    int xsval = 0;
  21.272 -
  21.273 -    if (!xh)
  21.274 -        goto exit;
  21.275 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
  21.276 -        goto exit;
  21.277 -    sprintf(token_str, "%li", (unsigned long)token);
  21.278 -    Py_BEGIN_ALLOW_THREADS
  21.279 -    xsval = xs_acknowledge_watch(xh, token_str);
  21.280 -    Py_END_ALLOW_THREADS
  21.281 -    if (!xsval) {
  21.282 -        PyErr_SetFromErrno(PyExc_RuntimeError);
  21.283 -        goto exit;
  21.284 -    }
  21.285 -    Py_INCREF(Py_None);
  21.286 -    val = Py_None;
  21.287 - exit:
  21.288 -    return val;
  21.289 -}
  21.290 -
  21.291  #define xspy_unwatch_doc "\n"				\
  21.292  	"Stop watching a path.\n"			\
  21.293  	" path  [string] : xenstore path.\n"		\
  21.294 @@ -584,9 +590,8 @@ static PyObject *xspy_unwatch(PyObject *
  21.295  
  21.296  #define xspy_transaction_start_doc "\n"				\
  21.297  	"Start a transaction.\n"				\
  21.298 -	"Only one transaction can be active at a time.\n"	\
  21.299  	"\n"							\
  21.300 -	"Returns None on success.\n"				\
  21.301 +	"Returns transaction handle on success.\n"		\
  21.302  	"Raises RuntimeError on error.\n"			\
  21.303  	"\n"
  21.304  
  21.305 @@ -599,21 +604,23 @@ static PyObject *xspy_transaction_start(
  21.306  
  21.307      struct xs_handle *xh = xshandle(self);
  21.308      PyObject *val = NULL;
  21.309 -    int xsval = 0;
  21.310 +    struct xs_transaction_handle *th;
  21.311 +    char thstr[20];
  21.312  
  21.313      if (!xh)
  21.314          goto exit;
  21.315      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  21.316          goto exit;
  21.317      Py_BEGIN_ALLOW_THREADS
  21.318 -    xsval = xs_transaction_start(xh);
  21.319 +    th = xs_transaction_start(xh);
  21.320      Py_END_ALLOW_THREADS
  21.321 -    if (!xsval) {
  21.322 +    if (th == NULL) {
  21.323          PyErr_SetFromErrno(PyExc_RuntimeError);
  21.324          goto exit;
  21.325      }
  21.326 -    Py_INCREF(Py_None);
  21.327 -    val = Py_None;
  21.328 +
  21.329 +    sprintf(thstr, "%lX", (unsigned long)th);
  21.330 +    val = PyString_FromString(thstr);
  21.331   exit:
  21.332      return val;
  21.333  }
  21.334 @@ -630,20 +637,27 @@ static PyObject *xspy_transaction_start(
  21.335  static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
  21.336                                        PyObject *kwds)
  21.337  {
  21.338 -    static char *kwd_spec[] = { "abort", NULL };
  21.339 -    static char *arg_spec = "|i";
  21.340 +    static char *kwd_spec[] = { "transaction", "abort", NULL };
  21.341 +    static char *arg_spec = "s|i";
  21.342      int abort = 0;
  21.343  
  21.344      struct xs_handle *xh = xshandle(self);
  21.345      PyObject *val = NULL;
  21.346      int xsval = 0;
  21.347  
  21.348 +    struct xs_transaction_handle *th;
  21.349 +    char *thstr;
  21.350 +
  21.351      if (!xh)
  21.352          goto exit;
  21.353 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
  21.354 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  21.355 +                                     &thstr, &abort))
  21.356          goto exit;
  21.357 +
  21.358 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  21.359 +
  21.360      Py_BEGIN_ALLOW_THREADS
  21.361 -    xsval = xs_transaction_end(xh, abort);
  21.362 +    xsval = xs_transaction_end(xh, th, abort);
  21.363      Py_END_ALLOW_THREADS
  21.364      if (!xsval) {
  21.365  	if (errno == EAGAIN) {
  21.366 @@ -833,7 +847,6 @@ static PyMethodDef xshandle_methods[] = 
  21.367       XSPY_METH(set_permissions),
  21.368       XSPY_METH(watch),
  21.369       XSPY_METH(read_watch),
  21.370 -     XSPY_METH(acknowledge_watch),
  21.371       XSPY_METH(unwatch),
  21.372       XSPY_METH(transaction_start),
  21.373       XSPY_METH(transaction_end),
    22.1 --- a/tools/python/xen/xend/xenstore/xstransact.py	Mon Oct 10 14:42:38 2005 +0100
    22.2 +++ b/tools/python/xen/xend/xenstore/xstransact.py	Mon Oct 10 14:46:53 2005 +0100
    22.3 @@ -14,29 +14,34 @@ from xen.xend.xenstore.xsutil import xsh
    22.4  class xstransact:
    22.5  
    22.6      def __init__(self, path):
    22.7 -        self.in_transaction = False
    22.8          self.path = path.rstrip("/")
    22.9 -        xshandle().transaction_start()
   22.10 +        self.transaction = xshandle().transaction_start()
   22.11          self.in_transaction = True
   22.12  
   22.13      def __del__(self):
   22.14          if self.in_transaction:
   22.15 -            xshandle().transaction_end(True)
   22.16 +            xshandle().transaction_end(self.transaction, True)
   22.17  
   22.18      def commit(self):
   22.19          if not self.in_transaction:
   22.20              raise RuntimeError
   22.21          self.in_transaction = False
   22.22 -        return xshandle().transaction_end(False)
   22.23 +        rc = xshandle().transaction_end(self.transaction, False)
   22.24 +        self.transaction = "0"
   22.25 +        return rc
   22.26  
   22.27      def abort(self):
   22.28 +        if not self.in_transaction:
   22.29 +            return True
   22.30          self.in_transaction = False
   22.31 -        return xshandle().transaction_end(True)
   22.32 +        rc = xshandle().transaction_end(self.transaction, True)
   22.33 +        self.transaction = "0"
   22.34 +        return rc
   22.35  
   22.36      def _read(self, key):
   22.37          path = "%s/%s" % (self.path, key)
   22.38          try:
   22.39 -            return xshandle().read(path)
   22.40 +            return xshandle().read(self.transaction, path)
   22.41          except RuntimeError, ex:
   22.42              raise RuntimeError(ex.args[0],
   22.43                                 '%s, while reading %s' % (ex.args[1], path))
   22.44 @@ -50,7 +55,7 @@ class xstransact:
   22.45          instead.
   22.46          """
   22.47          if len(args) == 0:
   22.48 -            return xshandle().read(self.path)
   22.49 +            return xshandle().read(self.transaction, self.path)
   22.50          if len(args) == 1:
   22.51              return self._read(args[0])
   22.52          ret = []
   22.53 @@ -61,7 +66,7 @@ class xstransact:
   22.54      def _write(self, key, data):
   22.55          path = "%s/%s" % (self.path, key)
   22.56          try:
   22.57 -            xshandle().write(path, data)
   22.58 +            xshandle().write(self.transaction, path, data)
   22.59          except RuntimeError, ex:
   22.60              raise RuntimeError(ex.args[0],
   22.61                                 ('%s, while writing %s : %s' %
   22.62 @@ -93,7 +98,7 @@ class xstransact:
   22.63  
   22.64      def _remove(self, key):
   22.65          path = "%s/%s" % (self.path, key)
   22.66 -        return xshandle().rm(path)
   22.67 +        return xshandle().rm(self.transaction, path)
   22.68  
   22.69      def remove(self, *args):
   22.70          """If no arguments are given, remove this transaction's path.
   22.71 @@ -101,14 +106,14 @@ class xstransact:
   22.72          path, and remove each of those instead.
   22.73          """
   22.74          if len(args) == 0:
   22.75 -            xshandle().rm(self.path)
   22.76 +            xshandle().rm(self.transaction, self.path)
   22.77          else:
   22.78              for key in args:
   22.79                  self._remove(key)
   22.80  
   22.81      def _list(self, key):
   22.82          path = "%s/%s" % (self.path, key)
   22.83 -        l = xshandle().ls(path)
   22.84 +        l = xshandle().ls(self.transaction, path)
   22.85          if l:
   22.86              return map(lambda x: key + "/" + x, l)
   22.87          return []
   22.88 @@ -120,7 +125,7 @@ class xstransact:
   22.89          path, and return the cumulative listing of each of those instead.
   22.90          """
   22.91          if len(args) == 0:
   22.92 -            ret = xshandle().ls(self.path)
   22.93 +            ret = xshandle().ls(self.transaction, self.path)
   22.94              if ret is None:
   22.95                  return []
   22.96              else:
   22.97 @@ -136,11 +141,11 @@ class xstransact:
   22.98          ret = []
   22.99          for key in keys:
  22.100              new_subdir = subdir + "/" + key
  22.101 -            l = xshandle().ls(new_subdir)
  22.102 +            l = xshandle().ls(self.transaction, new_subdir)
  22.103              if l:
  22.104                  ret.append([key, self.list_recursive_(new_subdir, l)])
  22.105              else:
  22.106 -                ret.append([key, xshandle().read(new_subdir)])
  22.107 +                ret.append([key, xshandle().read(self.transaction, new_subdir)])
  22.108          return ret
  22.109  
  22.110  
    23.1 --- a/tools/python/xen/xend/xenstore/xswatch.py	Mon Oct 10 14:42:38 2005 +0100
    23.2 +++ b/tools/python/xen/xend/xenstore/xswatch.py	Mon Oct 10 14:46:53 2005 +0100
    23.3 @@ -8,6 +8,7 @@
    23.4  import select
    23.5  import threading
    23.6  from xen.lowlevel import xs
    23.7 +from xen.xend.xenstore.xsutil import xshandle
    23.8  
    23.9  class xswatch:
   23.10  
   23.11 @@ -27,10 +28,7 @@ class xswatch:
   23.12          if cls.watchThread:
   23.13              cls.xslock.release()
   23.14              return
   23.15 -        # XXX: When we fix xenstored to have better watch semantics,
   23.16 -        # this can change to shared xshandle(). Currently that would result
   23.17 -        # in duplicate watch firings, thus failed extra xs.acknowledge_watch.
   23.18 -        cls.xs = xs.open()
   23.19 +        cls.xs = xshandle()
   23.20          cls.watchThread = threading.Thread(name="Watcher",
   23.21                                             target=cls.watchMain)
   23.22          cls.watchThread.setDaemon(True)
   23.23 @@ -43,11 +41,10 @@ class xswatch:
   23.24          while True:
   23.25              try:
   23.26                  we = cls.xs.read_watch()
   23.27 -                watch = we[1]
   23.28 -                cls.xs.acknowledge_watch(watch)
   23.29              except RuntimeError, ex:
   23.30                  print ex
   23.31                  raise
   23.32 +            watch = we[1]
   23.33              watch.fn(*watch.args, **watch.kwargs)
   23.34  
   23.35      watchMain = classmethod(watchMain)
    24.1 --- a/tools/xenstore/Makefile	Mon Oct 10 14:42:38 2005 +0100
    24.2 +++ b/tools/xenstore/Makefile	Mon Oct 10 14:46:53 2005 +0100
    24.3 @@ -8,7 +8,7 @@ INSTALL_PROG    = $(INSTALL) -m0755
    24.4  INSTALL_DIR     = $(INSTALL) -d -m0755
    24.5  
    24.6  PROFILE=#-pg
    24.7 -BASECFLAGS=-Wall -W -g -Werror
    24.8 +BASECFLAGS=-Wall -g -Werror
    24.9  # Make gcc generate dependencies.
   24.10  BASECFLAGS += -Wp,-MD,.$(@F).d
   24.11  PROG_DEP = .*.d
    25.1 --- a/tools/xenstore/testsuite/07watch.test	Mon Oct 10 14:42:38 2005 +0100
    25.2 +++ b/tools/xenstore/testsuite/07watch.test	Mon Oct 10 14:46:53 2005 +0100
    25.3 @@ -5,7 +5,6 @@ 1 watch /test token
    25.4  2 write /test contents2
    25.5  expect 1:/test:token
    25.6  1 waitwatch
    25.7 -1 ackwatch token
    25.8  1 close
    25.9  
   25.10  # Check that reads don't set it off.
   25.11 @@ -22,15 +21,12 @@ 1 watch /dir token
   25.12  2 mkdir /dir/newdir
   25.13  expect 1:/dir/newdir:token
   25.14  1 waitwatch
   25.15 -1 ackwatch token
   25.16  2 setperm /dir/newdir 0 READ
   25.17  expect 1:/dir/newdir:token
   25.18  1 waitwatch
   25.19 -1 ackwatch token
   25.20  2 rm /dir/newdir
   25.21  expect 1:/dir/newdir:token
   25.22  1 waitwatch
   25.23 -1 ackwatch token
   25.24  1 close
   25.25  2 close
   25.26  
   25.27 @@ -49,7 +45,6 @@ expect contents
   25.28  read /dir/test
   25.29  expect /dir/test:token
   25.30  waitwatch
   25.31 -ackwatch token
   25.32  close
   25.33  
   25.34  # watch priority test: all simultaneous
   25.35 @@ -59,13 +54,10 @@ 2 watch /dir token2
   25.36  write /dir/test contents
   25.37  expect 3:/dir/test:token3
   25.38  3 waitwatch
   25.39 -3 ackwatch token3
   25.40  expect 2:/dir/test:token2
   25.41  2 waitwatch
   25.42 -2 ackwatch token2
   25.43  expect 1:/dir/test:token1
   25.44  1 waitwatch
   25.45 -1 ackwatch token1
   25.46  1 close
   25.47  2 close
   25.48  3 close
   25.49 @@ -79,7 +71,6 @@ 2 waitwatch
   25.50  2 close
   25.51  expect 1:/dir/test:token1
   25.52  1 waitwatch
   25.53 -1 ackwatch token1
   25.54  1 close
   25.55  
   25.56  # If one dies (without reading at all), the other should still get ack.
   25.57 @@ -89,7 +80,6 @@ write /dir/test contents
   25.58  2 close
   25.59  expect 1:/dir/test:token1
   25.60  1 waitwatch
   25.61 -1 ackwatch token1
   25.62  1 close
   25.63  2 close
   25.64  
   25.65 @@ -111,7 +101,6 @@ write /dir/test contents
   25.66  2 unwatch /dir token2
   25.67  expect 1:/dir/test:token1
   25.68  1 waitwatch
   25.69 -1 ackwatch token1
   25.70  1 close
   25.71  2 close
   25.72  
   25.73 @@ -123,14 +112,12 @@ 1 watch /dir/test token2
   25.74  write /dir/test contents2
   25.75  expect 1:/dir/test:token2
   25.76  1 waitwatch
   25.77 -1 ackwatch token2
   25.78  
   25.79  # check we only get notified once.
   25.80  1 watch /test token
   25.81  2 write /test contents2
   25.82  expect 1:/test:token
   25.83  1 waitwatch
   25.84 -1 ackwatch token
   25.85  expect 1: waitwatch failed: Connection timed out
   25.86  1 waitwatch
   25.87  1 close
   25.88 @@ -142,13 +129,10 @@ 2 write /test2 contents
   25.89  2 write /test3 contents
   25.90  expect 1:/test1:token
   25.91  1 waitwatch
   25.92 -1 ackwatch token
   25.93  expect 1:/test2:token
   25.94  1 waitwatch
   25.95 -1 ackwatch token
   25.96  expect 1:/test3:token
   25.97  1 waitwatch
   25.98 -1 ackwatch token
   25.99  1 close
  25.100  
  25.101  # Creation of subpaths should be covered correctly.
  25.102 @@ -157,10 +141,8 @@ 2 write /test/subnode contents2
  25.103  2 write /test/subnode/subnode contents2
  25.104  expect 1:/test/subnode:token
  25.105  1 waitwatch
  25.106 -1 ackwatch token
  25.107  expect 1:/test/subnode/subnode:token
  25.108  1 waitwatch
  25.109 -1 ackwatch token
  25.110  expect 1: waitwatch failed: Connection timed out
  25.111  1 waitwatch
  25.112  1 close
  25.113 @@ -171,7 +153,6 @@ 2 write /test/subnode contents2
  25.114  1 watchnoack / token2 0
  25.115  expect 1:/test/subnode:token
  25.116  1 waitwatch
  25.117 -1 ackwatch token
  25.118  expect 1:/:token2
  25.119  1 waitwatch
  25.120  expect 1: waitwatch failed: Connection timed out
  25.121 @@ -183,7 +164,6 @@ 1 watch /test/subnode token
  25.122  2 rm /test
  25.123  expect 1:/test/subnode:token
  25.124  1 waitwatch
  25.125 -1 ackwatch token
  25.126  
  25.127  # Watch should not double-send after we ack, even if we did something in between.
  25.128  1 watch /test2 token
  25.129 @@ -192,6 +172,5 @@ expect 1:/test2/foo:token
  25.130  1 waitwatch
  25.131  expect 1:contents2
  25.132  1 read /test2/foo
  25.133 -1 ackwatch token
  25.134  expect 1: waitwatch failed: Connection timed out
  25.135  1 waitwatch
    26.1 --- a/tools/xenstore/testsuite/08transaction.test	Mon Oct 10 14:42:38 2005 +0100
    26.2 +++ b/tools/xenstore/testsuite/08transaction.test	Mon Oct 10 14:46:53 2005 +0100
    26.3 @@ -68,7 +68,6 @@ 2 mkdir /test/dir/sub
    26.4  2 commit
    26.5  expect 1:/test/dir/sub:token
    26.6  1 waitwatch
    26.7 -1 ackwatch token
    26.8  1 close
    26.9  
   26.10  # Rm inside transaction works like rm outside: children get notified.
   26.11 @@ -78,7 +77,6 @@ 2 rm /test/dir
   26.12  2 commit
   26.13  expect 1:/test/dir/sub:token
   26.14  1 waitwatch
   26.15 -1 ackwatch token
   26.16  1 close
   26.17  
   26.18  # Multiple events from single transaction don't trigger assert
   26.19 @@ -89,8 +87,6 @@ 2 write /test/2 contents
   26.20  2 commit
   26.21  expect 1:/test/1:token
   26.22  1 waitwatch
   26.23 -1 ackwatch token
   26.24  expect 1:/test/2:token
   26.25  1 waitwatch
   26.26 -1 ackwatch token
   26.27  1 close
    27.1 --- a/tools/xenstore/testsuite/10domain-homedir.test	Mon Oct 10 14:42:38 2005 +0100
    27.2 +++ b/tools/xenstore/testsuite/10domain-homedir.test	Mon Oct 10 14:46:53 2005 +0100
    27.3 @@ -16,4 +16,3 @@ 1 watch foo token
    27.4  write /home/foo/bar contents
    27.5  expect 1:foo/bar:token
    27.6  1 waitwatch
    27.7 -1 ackwatch token
    28.1 --- a/tools/xenstore/testsuite/11domain-watch.test	Mon Oct 10 14:42:38 2005 +0100
    28.2 +++ b/tools/xenstore/testsuite/11domain-watch.test	Mon Oct 10 14:46:53 2005 +0100
    28.3 @@ -10,7 +10,6 @@ 1 watch /test token
    28.4  write /test contents2
    28.5  expect 1:/test:token
    28.6  1 waitwatch
    28.7 -1 ackwatch token
    28.8  1 unwatch /test token
    28.9  release 1
   28.10  1 close
   28.11 @@ -25,7 +24,6 @@ 1 write /dir/test3 contents3
   28.12  1 write /dir/test4 contents4
   28.13  expect 1:/dir/test:token
   28.14  1 waitwatch
   28.15 -1 ackwatch token
   28.16  release 1
   28.17  1 close
   28.18  
    29.1 --- a/tools/xenstore/testsuite/12readonly.test	Mon Oct 10 14:42:38 2005 +0100
    29.2 +++ b/tools/xenstore/testsuite/12readonly.test	Mon Oct 10 14:46:53 2005 +0100
    29.3 @@ -36,4 +36,3 @@ 1 readwrite
    29.4  1 write /test contents
    29.5  expect /test:token
    29.6  waitwatch
    29.7 -ackwatch token
    30.1 --- a/tools/xenstore/testsuite/13watch-ack.test	Mon Oct 10 14:42:38 2005 +0100
    30.2 +++ b/tools/xenstore/testsuite/13watch-ack.test	Mon Oct 10 14:46:53 2005 +0100
    30.3 @@ -18,5 +18,4 @@ expect 1:/test/2:token2
    30.4  1 waitwatch
    30.5  3 write /test/1 contents1
    30.6  4 write /test/3 contents3
    30.7 -1 ackwatch token2
    30.8  1 close
    31.1 --- a/tools/xenstore/xenstore_client.c	Mon Oct 10 14:42:38 2005 +0100
    31.2 +++ b/tools/xenstore/xenstore_client.c	Mon Oct 10 14:46:53 2005 +0100
    31.3 @@ -32,6 +32,7 @@ int
    31.4  main(int argc, char **argv)
    31.5  {
    31.6      struct xs_handle *xsh;
    31.7 +    struct xs_transaction_handle *xth;
    31.8      bool success;
    31.9      int ret = 0;
   31.10  #if defined(CLIENT_read) || defined(CLIENT_list)
   31.11 @@ -84,13 +85,13 @@ main(int argc, char **argv)
   31.12  #endif
   31.13  
   31.14    again:
   31.15 -    success = xs_transaction_start(xsh);
   31.16 -    if (!success)
   31.17 +    xth = xs_transaction_start(xsh);
   31.18 +    if (xth == NULL)
   31.19  	errx(1, "couldn't start transaction");
   31.20  
   31.21      while (optind < argc) {
   31.22  #if defined(CLIENT_read)
   31.23 -	char *val = xs_read(xsh, argv[optind], NULL);
   31.24 +	char *val = xs_read(xsh, xth, argv[optind], NULL);
   31.25  	if (val == NULL) {
   31.26  	    warnx("couldn't read path %s", argv[optind]);
   31.27  	    ret = 1;
   31.28 @@ -102,7 +103,7 @@ main(int argc, char **argv)
   31.29  	free(val);
   31.30  	optind++;
   31.31  #elif defined(CLIENT_write)
   31.32 -	success = xs_write(xsh, argv[optind], argv[optind + 1],
   31.33 +	success = xs_write(xsh, xth, argv[optind], argv[optind + 1],
   31.34  			   strlen(argv[optind + 1]));
   31.35  	if (!success) {
   31.36  	    warnx("could not write path %s", argv[optind]);
   31.37 @@ -111,7 +112,7 @@ main(int argc, char **argv)
   31.38  	}
   31.39  	optind += 2;
   31.40  #elif defined(CLIENT_rm)
   31.41 -	success = xs_rm(xsh, argv[optind]);
   31.42 +	success = xs_rm(xsh, xth, argv[optind]);
   31.43  	if (!success) {
   31.44  	    warnx("could not remove path %s", argv[optind]);
   31.45  	    ret = 1;
   31.46 @@ -119,7 +120,7 @@ main(int argc, char **argv)
   31.47  	}
   31.48  	optind++;
   31.49  #elif defined(CLIENT_exists)
   31.50 -	char *val = xs_read(xsh, argv[optind], NULL);
   31.51 +	char *val = xs_read(xsh, xth, argv[optind], NULL);
   31.52  	if (val == NULL) {
   31.53  	    ret = 1;
   31.54  	    goto out;
   31.55 @@ -128,7 +129,7 @@ main(int argc, char **argv)
   31.56  	optind++;
   31.57  #elif defined(CLIENT_list)
   31.58  	unsigned int i, num;
   31.59 -	char **list = xs_directory(xsh, argv[optind], &num);
   31.60 +	char **list = xs_directory(xsh, xth, argv[optind], &num);
   31.61  	if (list == NULL) {
   31.62  	    warnx("could not list path %s", argv[optind]);
   31.63  	    ret = 1;
   31.64 @@ -145,7 +146,7 @@ main(int argc, char **argv)
   31.65      }
   31.66  
   31.67   out:
   31.68 -    success = xs_transaction_end(xsh, ret ? true : false);
   31.69 +    success = xs_transaction_end(xsh, xth, ret ? true : false);
   31.70      if (!success) {
   31.71  	if (ret == 0 && errno == EAGAIN)
   31.72  	    goto again;
    32.1 --- a/tools/xenstore/xenstored_core.c	Mon Oct 10 14:42:38 2005 +0100
    32.2 +++ b/tools/xenstore/xenstored_core.c	Mon Oct 10 14:46:53 2005 +0100
    32.3 @@ -154,7 +154,6 @@ static char *sockmsg_string(enum xsd_soc
    32.4  	case XS_READ: return "READ";
    32.5  	case XS_GET_PERMS: return "GET_PERMS";
    32.6  	case XS_WATCH: return "WATCH";
    32.7 -	case XS_WATCH_ACK: return "WATCH_ACK";
    32.8  	case XS_UNWATCH: return "UNWATCH";
    32.9  	case XS_TRANSACTION_START: return "TRANSACTION_START";
   32.10  	case XS_TRANSACTION_END: return "TRANSACTION_END";
   32.11 @@ -236,52 +235,50 @@ void trace(const char *fmt, ...)
   32.12  	talloc_free(str);
   32.13  }
   32.14  
   32.15 -static bool write_message(struct connection *conn)
   32.16 +static bool write_messages(struct connection *conn)
   32.17  {
   32.18  	int ret;
   32.19 -	struct buffered_data *out = conn->out;
   32.20 +	struct buffered_data *out, *tmp;
   32.21 +
   32.22 +	list_for_each_entry_safe(out, tmp, &conn->out_list, list) {
   32.23 +		if (out->inhdr) {
   32.24 +			if (verbose)
   32.25 +				xprintf("Writing msg %s (%s) out to %p\n",
   32.26 +					sockmsg_string(out->hdr.msg.type),
   32.27 +					out->buffer, conn);
   32.28 +			ret = conn->write(conn, out->hdr.raw + out->used,
   32.29 +					  sizeof(out->hdr) - out->used);
   32.30 +			if (ret < 0)
   32.31 +				return false;
   32.32  
   32.33 -	if (out->inhdr) {
   32.34 -		if (verbose)
   32.35 -			xprintf("Writing msg %s (%s) out to %p\n",
   32.36 -				sockmsg_string(out->hdr.msg.type),
   32.37 -				out->buffer, conn);
   32.38 -		ret = conn->write(conn, out->hdr.raw + out->used,
   32.39 -				  sizeof(out->hdr) - out->used);
   32.40 +			out->used += ret;
   32.41 +			if (out->used < sizeof(out->hdr))
   32.42 +				return true;
   32.43 +
   32.44 +			out->inhdr = false;
   32.45 +			out->used = 0;
   32.46 +
   32.47 +			/* Second write might block if non-zero. */
   32.48 +			if (out->hdr.msg.len && !conn->domain)
   32.49 +				return true;
   32.50 +		}
   32.51 +
   32.52 +		ret = conn->write(conn, out->buffer + out->used,
   32.53 +				  out->hdr.msg.len - out->used);
   32.54 +
   32.55  		if (ret < 0)
   32.56  			return false;
   32.57  
   32.58  		out->used += ret;
   32.59 -		if (out->used < sizeof(out->hdr))
   32.60 +		if (out->used != out->hdr.msg.len)
   32.61  			return true;
   32.62  
   32.63 -		out->inhdr = false;
   32.64 -		out->used = 0;
   32.65 +		trace_io(conn, "OUT", out);
   32.66  
   32.67 -		/* Second write might block if non-zero. */
   32.68 -		if (out->hdr.msg.len && !conn->domain)
   32.69 -			return true;
   32.70 +		list_del(&out->list);
   32.71 +		talloc_free(out);
   32.72  	}
   32.73  
   32.74 -	ret = conn->write(conn, out->buffer + out->used,
   32.75 -			  out->hdr.msg.len - out->used);
   32.76 -
   32.77 -	if (ret < 0)
   32.78 -		return false;
   32.79 -
   32.80 -	out->used += ret;
   32.81 -	if (out->used != out->hdr.msg.len)
   32.82 -		return true;
   32.83 -
   32.84 -	trace_io(conn, "OUT", out);
   32.85 -	conn->out = NULL;
   32.86 -	talloc_free(out);
   32.87 -
   32.88 -	queue_next_event(conn);
   32.89 -
   32.90 -	/* No longer busy? */
   32.91 -	if (!conn->out)
   32.92 -		conn->state = OK;
   32.93  	return true;
   32.94  }
   32.95  
   32.96 @@ -298,9 +295,9 @@ static int destroy_conn(void *_conn)
   32.97  		FD_SET(conn->fd, &set);
   32.98  		none.tv_sec = none.tv_usec = 0;
   32.99  
  32.100 -		while (conn->out
  32.101 +		while (!list_empty(&conn->out_list)
  32.102  		       && select(conn->fd+1, NULL, &set, NULL, &none) == 1)
  32.103 -			if (!write_message(conn))
  32.104 +			if (!write_messages(conn))
  32.105  				break;
  32.106  		close(conn->fd);
  32.107  	}
  32.108 @@ -327,9 +324,8 @@ static int initialize_set(fd_set *inset,
  32.109  	list_for_each_entry(i, &connections, list) {
  32.110  		if (i->domain)
  32.111  			continue;
  32.112 -		if (i->state == OK)
  32.113 -			FD_SET(i->fd, inset);
  32.114 -		if (i->out)
  32.115 +		FD_SET(i->fd, inset);
  32.116 +		if (!list_empty(&i->out_list))
  32.117  			FD_SET(i->fd, outset);
  32.118  		if (i->fd > max)
  32.119  			max = i->fd;
  32.120 @@ -595,14 +591,7 @@ void send_reply(struct connection *conn,
  32.121  	bdata->hdr.msg.len = len;
  32.122  	memcpy(bdata->buffer, data, len);
  32.123  
  32.124 -	/* There might be an event going out now.  Queue behind it. */
  32.125 -	if (conn->out) {
  32.126 -		assert(conn->out->hdr.msg.type == XS_WATCH_EVENT);
  32.127 -		assert(!conn->waiting_reply);
  32.128 -		conn->waiting_reply = bdata;
  32.129 -	} else
  32.130 -		conn->out = bdata;
  32.131 -	conn->state = BUSY;
  32.132 +	list_add_tail(&bdata->list, &conn->out_list);
  32.133  }
  32.134  
  32.135  /* Some routines (write, mkdir, etc) just need a non-error return */
  32.136 @@ -1103,10 +1092,6 @@ static void process_message(struct conne
  32.137  		do_watch(conn, in);
  32.138  		break;
  32.139  
  32.140 -	case XS_WATCH_ACK:
  32.141 -		do_watch_ack(conn, onearg(in));
  32.142 -		break;
  32.143 -
  32.144  	case XS_UNWATCH:
  32.145  		do_unwatch(conn, in);
  32.146  		break;
  32.147 @@ -1153,8 +1138,6 @@ static void consider_message(struct conn
  32.148  	enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type;
  32.149  	jmp_buf talloc_fail;
  32.150  
  32.151 -	assert(conn->state == OK);
  32.152 -
  32.153  	/* For simplicity, we kill the connection on OOM. */
  32.154  	talloc_set_fail_handler(out_of_mem, &talloc_fail);
  32.155  	if (setjmp(talloc_fail)) {
  32.156 @@ -1168,11 +1151,6 @@ static void consider_message(struct conn
  32.157  		xprintf("Got message %s len %i from %p\n",
  32.158  			sockmsg_string(type), conn->in->hdr.msg.len, conn);
  32.159  
  32.160 -	/* We might get a command while waiting for an ack: this means
  32.161 -	 * the other end discarded it: we will re-transmit. */
  32.162 -	if (type != XS_WATCH_ACK)
  32.163 -		conn->waiting_for_ack = NULL;
  32.164 -
  32.165  	/* Careful: process_message may free connection.  We detach
  32.166  	 * "in" beforehand and allocate the new buffer to avoid
  32.167  	 * touching conn after process_message.
  32.168 @@ -1196,10 +1174,7 @@ end:
  32.169  static void handle_input(struct connection *conn)
  32.170  {
  32.171  	int bytes;
  32.172 -	struct buffered_data *in;
  32.173 -
  32.174 -	assert(conn->state == OK);
  32.175 -	in = conn->in;
  32.176 +	struct buffered_data *in = conn->in;
  32.177  
  32.178  	/* Not finished header yet? */
  32.179  	if (in->inhdr) {
  32.180 @@ -1247,7 +1222,7 @@ bad_client:
  32.181  
  32.182  static void handle_output(struct connection *conn)
  32.183  {
  32.184 -	if (!write_message(conn))
  32.185 +	if (!write_messages(conn))
  32.186  		talloc_free(conn);
  32.187  }
  32.188  
  32.189 @@ -1264,9 +1239,6 @@ struct connection *new_connection(connwr
  32.190  	if (!new)
  32.191  		return NULL;
  32.192  
  32.193 -	new->state = OK;
  32.194 -	new->out = new->waiting_reply = NULL;
  32.195 -	new->waiting_for_ack = NULL;
  32.196  	new->fd = -1;
  32.197  	new->id = 0;
  32.198  	new->domain = NULL;
  32.199 @@ -1274,6 +1246,7 @@ struct connection *new_connection(connwr
  32.200  	new->write = write;
  32.201  	new->read = read;
  32.202  	new->can_write = true;
  32.203 +	INIT_LIST_HEAD(&new->out_list);
  32.204  	INIT_LIST_HEAD(&new->watches);
  32.205  
  32.206  	talloc_set_fail_handler(out_of_mem, &talloc_fail);
  32.207 @@ -1328,23 +1301,17 @@ void dump_connection(void)
  32.208  	list_for_each_entry(i, &connections, list) {
  32.209  		printf("Connection %p:\n", i);
  32.210  		printf("    state = %s\n",
  32.211 -		       i->state == OK ? "OK"
  32.212 -		       : i->state == BUSY ? "BUSY"
  32.213 -		       : "INVALID");
  32.214 +		       list_empty(&i->out_list) ? "OK" : "BUSY");
  32.215  		if (i->id)
  32.216  			printf("    id = %i\n", i->id);
  32.217  		if (!i->in->inhdr || i->in->used)
  32.218  			printf("    got %i bytes of %s\n",
  32.219  			       i->in->used, i->in->inhdr ? "header" : "data");
  32.220 +#if 0
  32.221  		if (i->out)
  32.222  			printf("    sending message %s (%s) out\n",
  32.223  			       sockmsg_string(i->out->hdr.msg.type),
  32.224  			       i->out->buffer);
  32.225 -		if (i->waiting_reply)
  32.226 -			printf("    ... and behind is queued %s (%s)\n",
  32.227 -			       sockmsg_string(i->waiting_reply->hdr.msg.type),
  32.228 -			       i->waiting_reply->buffer);
  32.229 -#if 0
  32.230  		if (i->transaction)
  32.231  			dump_transaction(i);
  32.232  		if (i->domain)
  32.233 @@ -1615,3 +1582,13 @@ int main(int argc, char *argv[])
  32.234  		max = initialize_set(&inset, &outset, *sock, *ro_sock);
  32.235  	}
  32.236  }
  32.237 +
  32.238 +/*
  32.239 + * Local variables:
  32.240 + *  c-file-style: "linux"
  32.241 + *  indent-tabs-mode: t
  32.242 + *  c-indent-level: 8
  32.243 + *  c-basic-offset: 8
  32.244 + *  tab-width: 8
  32.245 + * End:
  32.246 + */
    33.1 --- a/tools/xenstore/xenstored_core.h	Mon Oct 10 14:42:38 2005 +0100
    33.2 +++ b/tools/xenstore/xenstored_core.h	Mon Oct 10 14:46:53 2005 +0100
    33.3 @@ -31,14 +31,19 @@
    33.4  
    33.5  struct buffered_data
    33.6  {
    33.7 +	struct list_head list;
    33.8 +
    33.9  	/* Are we still doing the header? */
   33.10  	bool inhdr;
   33.11 +
   33.12  	/* How far are we? */
   33.13  	unsigned int used;
   33.14 +
   33.15  	union {
   33.16  		struct xsd_sockmsg msg;
   33.17  		char raw[sizeof(struct xsd_sockmsg)];
   33.18  	} hdr;
   33.19 +
   33.20  	/* The actual data. */
   33.21  	char *buffer;
   33.22  };
   33.23 @@ -47,14 +52,6 @@ struct connection;
   33.24  typedef int connwritefn_t(struct connection *, const void *, unsigned int);
   33.25  typedef int connreadfn_t(struct connection *, void *, unsigned int);
   33.26  
   33.27 -enum state
   33.28 -{
   33.29 -	/* Doing action, not listening */
   33.30 -	BUSY,
   33.31 -	/* Completed */
   33.32 -	OK,
   33.33 -};
   33.34 -
   33.35  struct connection
   33.36  {
   33.37  	struct list_head list;
   33.38 @@ -62,26 +59,17 @@ struct connection
   33.39  	/* The file descriptor we came in on. */
   33.40  	int fd;
   33.41  
   33.42 -	/* Who am I?  0 for socket connections. */
   33.43 +	/* Who am I? 0 for socket connections. */
   33.44  	domid_t id;
   33.45  
   33.46 -	/* Blocked on transaction?  Busy? */
   33.47 -	enum state state;
   33.48 -
   33.49  	/* Is this a read-only connection? */
   33.50  	bool can_write;
   33.51  
   33.52 -	/* Are we waiting for a watch event ack? */
   33.53 -	struct watch *waiting_for_ack;
   33.54 -
   33.55  	/* Buffered incoming data. */
   33.56  	struct buffered_data *in;
   33.57  
   33.58  	/* Buffered output data */
   33.59 -	struct buffered_data *out;
   33.60 -
   33.61 -	/* If we had a watch fire outgoing when we needed to reply... */
   33.62 -	struct buffered_data *waiting_reply;
   33.63 +	struct list_head out_list;
   33.64  
   33.65  	/* My transaction, if any. */
   33.66  	struct transaction *transaction;
   33.67 @@ -175,3 +163,13 @@ void trace(const char *fmt, ...);
   33.68  extern int event_fd;
   33.69  
   33.70  #endif /* _XENSTORED_CORE_H */
   33.71 +
   33.72 +/*
   33.73 + * Local variables:
   33.74 + *  c-file-style: "linux"
   33.75 + *  indent-tabs-mode: t
   33.76 + *  c-indent-level: 8
   33.77 + *  c-basic-offset: 8
   33.78 + *  tab-width: 8
   33.79 + * End:
   33.80 + */
    34.1 --- a/tools/xenstore/xenstored_domain.c	Mon Oct 10 14:42:38 2005 +0100
    34.2 +++ b/tools/xenstore/xenstored_domain.c	Mon Oct 10 14:46:53 2005 +0100
    34.3 @@ -276,12 +276,13 @@ void handle_event(void)
    34.4  
    34.5  bool domain_can_read(struct connection *conn)
    34.6  {
    34.7 -	return conn->state == OK && buffer_has_input(conn->domain->input);
    34.8 +	return buffer_has_input(conn->domain->input);
    34.9  }
   34.10  
   34.11  bool domain_can_write(struct connection *conn)
   34.12  {
   34.13 -	return conn->out && buffer_has_output_room(conn->domain->output);
   34.14 +	return (!list_empty(&conn->out_list) &&
   34.15 +                buffer_has_output_room(conn->domain->output));
   34.16  }
   34.17  
   34.18  static struct domain *new_domain(void *context, domid_t domid,
    35.1 --- a/tools/xenstore/xenstored_transaction.c	Mon Oct 10 14:42:38 2005 +0100
    35.2 +++ b/tools/xenstore/xenstored_transaction.c	Mon Oct 10 14:46:53 2005 +0100
    35.3 @@ -154,9 +154,9 @@ void do_transaction_end(struct connectio
    35.4  		return;
    35.5  	}
    35.6  
    35.7 -	/* Set to NULL so fire_watches sends events, tdb_context works. */
    35.8  	trans = conn->transaction;
    35.9  	conn->transaction = NULL;
   35.10 +
   35.11  	/* Attach transaction to arg for auto-cleanup */
   35.12  	talloc_steal(arg, trans);
   35.13  
    36.1 --- a/tools/xenstore/xenstored_watch.c	Mon Oct 10 14:42:38 2005 +0100
    36.2 +++ b/tools/xenstore/xenstored_watch.c	Mon Oct 10 14:46:53 2005 +0100
    36.3 @@ -32,17 +32,6 @@
    36.4  #include "xenstored_test.h"
    36.5  #include "xenstored_domain.h"
    36.6  
    36.7 -/* FIXME: time out unacked watches. */
    36.8 -struct watch_event
    36.9 -{
   36.10 -	/* The events on this watch. */
   36.11 -	struct list_head list;
   36.12 -
   36.13 -	/* Data to send (node\0token\0). */
   36.14 -	unsigned int len;
   36.15 -	char *data;
   36.16 -};
   36.17 -
   36.18  struct watch
   36.19  {
   36.20  	/* Watches on this connection */
   36.21 @@ -58,54 +47,17 @@ struct watch
   36.22  	char *node;
   36.23  };
   36.24  
   36.25 -/* Look through our watches: if any of them have an event, queue it. */
   36.26 -void queue_next_event(struct connection *conn)
   36.27 -{
   36.28 -	struct watch_event *event;
   36.29 -	struct watch *watch;
   36.30 -
   36.31 -	/* We had a reply queued already?  Send it: other end will
   36.32 -	 * discard watch. */
   36.33 -	if (conn->waiting_reply) {
   36.34 -		conn->out = conn->waiting_reply;
   36.35 -		conn->waiting_reply = NULL;
   36.36 -		conn->waiting_for_ack = NULL;
   36.37 -		return;
   36.38 -	}
   36.39 -
   36.40 -	/* If we're already waiting for ack, don't queue more. */
   36.41 -	if (conn->waiting_for_ack)
   36.42 -		return;
   36.43 -
   36.44 -	list_for_each_entry(watch, &conn->watches, list) {
   36.45 -		event = list_top(&watch->events, struct watch_event, list);
   36.46 -		if (event) {
   36.47 -			conn->waiting_for_ack = watch;
   36.48 -			send_reply(conn,XS_WATCH_EVENT,event->data,event->len);
   36.49 -			break;
   36.50 -		}
   36.51 -	}
   36.52 -}
   36.53 -
   36.54 -static int destroy_watch_event(void *_event)
   36.55 -{
   36.56 -	struct watch_event *event = _event;
   36.57 -
   36.58 -	trace_destroy(event, "watch_event");
   36.59 -	return 0;
   36.60 -}
   36.61 -
   36.62  static void add_event(struct connection *conn,
   36.63  		      struct watch *watch,
   36.64  		      const char *name)
   36.65  {
   36.66 -	struct watch_event *event;
   36.67 +	/* Data to send (node\0token\0). */
   36.68 +	unsigned int len;
   36.69 +	char *data;
   36.70  
   36.71  	if (!check_event_node(name)) {
   36.72  		/* Can this conn load node, or see that it doesn't exist? */
   36.73 -		struct node *node;
   36.74 -
   36.75 -		node = get_node(conn, name, XS_PERM_READ);
   36.76 +		struct node *node = get_node(conn, name, XS_PERM_READ);
   36.77  		if (!node && errno != ENOENT)
   36.78  			return;
   36.79  	}
   36.80 @@ -116,14 +68,12 @@ static void add_event(struct connection 
   36.81  			name++;
   36.82  	}
   36.83  
   36.84 -	event = talloc(watch, struct watch_event);
   36.85 -	event->len = strlen(name) + 1 + strlen(watch->token) + 1;
   36.86 -	event->data = talloc_array(event, char, event->len);
   36.87 -	strcpy(event->data, name);
   36.88 -	strcpy(event->data + strlen(name) + 1, watch->token);
   36.89 -	talloc_set_destructor(event, destroy_watch_event);
   36.90 -	list_add_tail(&event->list, &watch->events);
   36.91 -	trace_create(event, "watch_event");
   36.92 +	len = strlen(name) + 1 + strlen(watch->token) + 1;
   36.93 +	data = talloc_array(watch, char, len);
   36.94 +	strcpy(data, name);
   36.95 +	strcpy(data + strlen(name) + 1, watch->token);
   36.96 +        send_reply(conn, XS_WATCH_EVENT, data, len);
   36.97 +	talloc_free(data);
   36.98  }
   36.99  
  36.100  /* FIXME: we fail to fire on out of memory.  Should drop connections. */
  36.101 @@ -143,11 +93,6 @@ void fire_watches(struct connection *con
  36.102  				add_event(i, watch, name);
  36.103  			else if (recurse && is_child(watch->node, name))
  36.104  				add_event(i, watch, watch->node);
  36.105 -			else
  36.106 -				continue;
  36.107 -			/* If connection not doing anything, queue this. */
  36.108 -			if (i->state == OK)
  36.109 -				queue_next_event(i);
  36.110  		}
  36.111  	}
  36.112  }
  36.113 @@ -181,6 +126,15 @@ void do_watch(struct connection *conn, s
  36.114  		}
  36.115  	}
  36.116  
  36.117 +	/* Check for duplicates. */
  36.118 +	list_for_each_entry(watch, &conn->watches, list) {
  36.119 +		if (streq(watch->node, vec[0]) &&
  36.120 +                    streq(watch->token, vec[1])) {
  36.121 +			send_error(conn, EEXIST);
  36.122 +			return;
  36.123 +		}
  36.124 +	}
  36.125 +
  36.126  	watch = talloc(conn, struct watch);
  36.127  	watch->node = talloc_strdup(watch, vec[0]);
  36.128  	watch->token = talloc_strdup(watch, vec[1]);
  36.129 @@ -200,37 +154,6 @@ void do_watch(struct connection *conn, s
  36.130  	add_event(conn, watch, watch->node);
  36.131  }
  36.132  
  36.133 -void do_watch_ack(struct connection *conn, const char *token)
  36.134 -{
  36.135 -	struct watch_event *event;
  36.136 -
  36.137 -	if (!token) {
  36.138 -		send_error(conn, EINVAL);
  36.139 -		return;
  36.140 -	}
  36.141 -
  36.142 -	if (!conn->waiting_for_ack) {
  36.143 -		send_error(conn, ENOENT);
  36.144 -		return;
  36.145 -	}
  36.146 -
  36.147 -	if (!streq(conn->waiting_for_ack->token, token)) {
  36.148 -		/* They're confused: this will cause us to send event again */
  36.149 -		conn->waiting_for_ack = NULL;
  36.150 -		send_error(conn, EINVAL);
  36.151 -		return;
  36.152 -	}
  36.153 -
  36.154 -	/* Remove event: after ack sent, core will call queue_next_event */
  36.155 -	event = list_top(&conn->waiting_for_ack->events, struct watch_event,
  36.156 -			 list);
  36.157 -	list_del(&event->list);
  36.158 -	talloc_free(event);
  36.159 -
  36.160 -	conn->waiting_for_ack = NULL;
  36.161 -	send_ack(conn, XS_WATCH_ACK);
  36.162 -}
  36.163 -
  36.164  void do_unwatch(struct connection *conn, struct buffered_data *in)
  36.165  {
  36.166  	struct watch *watch;
  36.167 @@ -241,9 +164,6 @@ void do_unwatch(struct connection *conn,
  36.168  		return;
  36.169  	}
  36.170  
  36.171 -	/* We don't need to worry if we're waiting for an ack for the
  36.172 -	 * watch we're deleting: conn->waiting_for_ack was reset by
  36.173 -	 * this command in consider_message anyway. */
  36.174  	node = canonicalize(conn, vec[0]);
  36.175  	list_for_each_entry(watch, &conn->watches, list) {
  36.176  		if (streq(watch->node, node) && streq(watch->token, vec[1])) {
  36.177 @@ -260,18 +180,19 @@ void do_unwatch(struct connection *conn,
  36.178  void dump_watches(struct connection *conn)
  36.179  {
  36.180  	struct watch *watch;
  36.181 -	struct watch_event *event;
  36.182  
  36.183 -	if (conn->waiting_for_ack)
  36.184 -		printf("    waiting_for_ack for watch on %s token %s\n",
  36.185 -		       conn->waiting_for_ack->node,
  36.186 -		       conn->waiting_for_ack->token);
  36.187 -
  36.188 -	list_for_each_entry(watch, &conn->watches, list) {
  36.189 +	list_for_each_entry(watch, &conn->watches, list)
  36.190  		printf("    watch on %s token %s\n",
  36.191  		       watch->node, watch->token);
  36.192 -		list_for_each_entry(event, &watch->events, list)
  36.193 -			printf("        event: %s\n", event->data);
  36.194 -	}
  36.195  }
  36.196  #endif
  36.197 +
  36.198 +/*
  36.199 + * Local variables:
  36.200 + *  c-file-style: "linux"
  36.201 + *  indent-tabs-mode: t
  36.202 + *  c-indent-level: 8
  36.203 + *  c-basic-offset: 8
  36.204 + *  tab-width: 8
  36.205 + * End:
  36.206 + */
    37.1 --- a/tools/xenstore/xenstored_watch.h	Mon Oct 10 14:42:38 2005 +0100
    37.2 +++ b/tools/xenstore/xenstored_watch.h	Mon Oct 10 14:46:53 2005 +0100
    37.3 @@ -23,17 +23,9 @@
    37.4  #include "xenstored_core.h"
    37.5  
    37.6  void do_watch(struct connection *conn, struct buffered_data *in);
    37.7 -void do_watch_ack(struct connection *conn, const char *token);
    37.8  void do_unwatch(struct connection *conn, struct buffered_data *in);
    37.9  
   37.10 -/* Is this a watch event message for this connection? */
   37.11 -bool is_watch_event(struct connection *conn, struct buffered_data *out);
   37.12 -
   37.13 -/* Look through our watches: if any of them have an event, queue it. */
   37.14 -void queue_next_event(struct connection *conn);
   37.15 -
   37.16 -/* Fire all watches: recurse means all the children are affected (ie. rm).
   37.17 - */
   37.18 +/* Fire all watches: recurse means all the children are affected (ie. rm). */
   37.19  void fire_watches(struct connection *conn, const char *name, bool recurse);
   37.20  
   37.21  void dump_watches(struct connection *conn);
    38.1 --- a/tools/xenstore/xs.c	Mon Oct 10 14:42:38 2005 +0100
    38.2 +++ b/tools/xenstore/xs.c	Mon Oct 10 14:46:53 2005 +0100
    38.3 @@ -78,10 +78,34 @@ struct xs_handle {
    38.4  
    38.5  	/* One transaction at a time. */
    38.6  	pthread_mutex_t transaction_mutex;
    38.7 +	pthread_t transaction_pthread;
    38.8 +};
    38.9 +
   38.10 +struct xs_transaction_handle {
   38.11 +	int id;
   38.12  };
   38.13  
   38.14  static void *read_thread(void *arg);
   38.15  
   38.16 +static void request_mutex_acquire(struct xs_handle *h)
   38.17 +{
   38.18 +	/*
   38.19 +	 * We can't distinguish non-transactional from transactional
   38.20 +	 * requests right now. So temporarily acquire the transaction mutex
   38.21 +	 * if this task is outside transaction context.
   38.22 + 	 */
   38.23 +	if (h->transaction_pthread != pthread_self())
   38.24 +		pthread_mutex_lock(&h->transaction_mutex);
   38.25 +	pthread_mutex_lock(&h->request_mutex);
   38.26 +}
   38.27 +
   38.28 +static void request_mutex_release(struct xs_handle *h)
   38.29 +{
   38.30 +	pthread_mutex_unlock(&h->request_mutex);
   38.31 +	if (h->transaction_pthread != pthread_self())
   38.32 +		pthread_mutex_unlock(&h->transaction_mutex);
   38.33 +}
   38.34 +
   38.35  int xs_fileno(struct xs_handle *h)
   38.36  {
   38.37  	char c = 0;
   38.38 @@ -163,6 +187,7 @@ static struct xs_handle *get_handle(cons
   38.39  
   38.40  	pthread_mutex_init(&h->request_mutex, NULL);
   38.41  	pthread_mutex_init(&h->transaction_mutex, NULL);
   38.42 +	h->transaction_pthread = -1;
   38.43  
   38.44  	if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0)
   38.45  		goto error;
   38.46 @@ -316,7 +341,7 @@ static void *xs_talkv(struct xs_handle *
   38.47  	ignorepipe.sa_flags = 0;
   38.48  	sigaction(SIGPIPE, &ignorepipe, &oldact);
   38.49  
   38.50 -	pthread_mutex_lock(&h->request_mutex);
   38.51 +	request_mutex_acquire(h);
   38.52  
   38.53  	if (!xs_write_all(h->fd, &msg, sizeof(msg)))
   38.54  		goto fail;
   38.55 @@ -329,7 +354,7 @@ static void *xs_talkv(struct xs_handle *
   38.56  	if (!ret)
   38.57  		goto fail;
   38.58  
   38.59 -	pthread_mutex_unlock(&h->request_mutex);
   38.60 +	request_mutex_release(h);
   38.61  
   38.62  	sigaction(SIGPIPE, &oldact, NULL);
   38.63  	if (msg.type == XS_ERROR) {
   38.64 @@ -350,7 +375,7 @@ static void *xs_talkv(struct xs_handle *
   38.65  fail:
   38.66  	/* We're in a bad state, so close fd. */
   38.67  	saved_errno = errno;
   38.68 -	pthread_mutex_unlock(&h->request_mutex);
   38.69 +	request_mutex_release(h);
   38.70  	sigaction(SIGPIPE, &oldact, NULL);
   38.71  close_fd:
   38.72  	close(h->fd);
   38.73 @@ -386,7 +411,8 @@ static bool xs_bool(char *reply)
   38.74  	return true;
   38.75  }
   38.76  
   38.77 -char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num)
   38.78 +char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t,
   38.79 +		    const char *path, unsigned int *num)
   38.80  {
   38.81  	char *strings, *p, **ret;
   38.82  	unsigned int len;
   38.83 @@ -417,7 +443,8 @@ char **xs_directory(struct xs_handle *h,
   38.84   * Returns a malloced value: call free() on it after use.
   38.85   * len indicates length in bytes, not including the nul.
   38.86   */
   38.87 -void *xs_read(struct xs_handle *h, const char *path, unsigned int *len)
   38.88 +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
   38.89 +	      const char *path, unsigned int *len)
   38.90  {
   38.91  	return xs_single(h, XS_READ, path, len);
   38.92  }
   38.93 @@ -425,8 +452,8 @@ void *xs_read(struct xs_handle *h, const
   38.94  /* Write the value of a single file.
   38.95   * Returns false on failure.
   38.96   */
   38.97 -bool xs_write(struct xs_handle *h, const char *path,
   38.98 -	      const void *data, unsigned int len)
   38.99 +bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t,
  38.100 +	      const char *path, const void *data, unsigned int len)
  38.101  {
  38.102  	struct iovec iovec[2];
  38.103  
  38.104 @@ -441,7 +468,8 @@ bool xs_write(struct xs_handle *h, const
  38.105  /* Create a new directory.
  38.106   * Returns false on failure, or success if it already exists.
  38.107   */
  38.108 -bool xs_mkdir(struct xs_handle *h, const char *path)
  38.109 +bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
  38.110 +	      const char *path)
  38.111  {
  38.112  	return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
  38.113  }
  38.114 @@ -449,7 +477,8 @@ bool xs_mkdir(struct xs_handle *h, const
  38.115  /* Destroy a file or directory (directories must be empty).
  38.116   * Returns false on failure, or success if it doesn't exist.
  38.117   */
  38.118 -bool xs_rm(struct xs_handle *h, const char *path)
  38.119 +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
  38.120 +	   const char *path)
  38.121  {
  38.122  	return xs_bool(xs_single(h, XS_RM, path, NULL));
  38.123  }
  38.124 @@ -458,6 +487,7 @@ bool xs_rm(struct xs_handle *h, const ch
  38.125   * Returns malloced array, or NULL: call free() after use.
  38.126   */
  38.127  struct xs_permissions *xs_get_permissions(struct xs_handle *h,
  38.128 +					  struct xs_transaction_handle *t,
  38.129  					  const char *path, unsigned int *num)
  38.130  {
  38.131  	char *strings;
  38.132 @@ -490,7 +520,9 @@ struct xs_permissions *xs_get_permission
  38.133  /* Set permissions of node (must be owner).
  38.134   * Returns false on failure.
  38.135   */
  38.136 -bool xs_set_permissions(struct xs_handle *h, const char *path,
  38.137 +bool xs_set_permissions(struct xs_handle *h,
  38.138 +			struct xs_transaction_handle *t,
  38.139 +			const char *path,
  38.140  			struct xs_permissions *perms,
  38.141  			unsigned int num_perms)
  38.142  {
  38.143 @@ -593,15 +625,6 @@ char **xs_read_watch(struct xs_handle *h
  38.144  	return ret;
  38.145  }
  38.146  
  38.147 -/* Acknowledge watch on node.  Watches must be acknowledged before
  38.148 - * any other watches can be read.
  38.149 - * Returns false on failure.
  38.150 - */
  38.151 -bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
  38.152 -{
  38.153 -	return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
  38.154 -}
  38.155 -
  38.156  /* Remove a watch on a node.
  38.157   * Returns false on failure (no watch on that node).
  38.158   */
  38.159 @@ -620,12 +643,22 @@ bool xs_unwatch(struct xs_handle *h, con
  38.160  /* Start a transaction: changes by others will not be seen during this
  38.161   * transaction, and changes will not be visible to others until end.
  38.162   * You can only have one transaction at any time.
  38.163 - * Returns false on failure.
  38.164 + * Returns NULL on failure.
  38.165   */
  38.166 -bool xs_transaction_start(struct xs_handle *h)
  38.167 +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h)
  38.168  {
  38.169 +	bool rc;
  38.170 +
  38.171  	pthread_mutex_lock(&h->transaction_mutex);
  38.172 -	return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
  38.173 +	h->transaction_pthread = pthread_self();
  38.174 +
  38.175 +	rc = xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
  38.176 +	if (!rc) {
  38.177 +		h->transaction_pthread = -1;
  38.178 +		pthread_mutex_unlock(&h->transaction_mutex);
  38.179 +	}
  38.180 +
  38.181 +	return (struct xs_transaction_handle *)rc;
  38.182  }
  38.183  
  38.184  /* End a transaction.
  38.185 @@ -633,11 +666,15 @@ bool xs_transaction_start(struct xs_hand
  38.186   * Returns false on failure, which indicates an error: transactions will
  38.187   * not fail spuriously.
  38.188   */
  38.189 -bool xs_transaction_end(struct xs_handle *h, bool abort)
  38.190 +bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
  38.191 +			bool abort)
  38.192  {
  38.193  	char abortstr[2];
  38.194  	bool rc;
  38.195  
  38.196 +	if (t == NULL)
  38.197 +		return -EINVAL;
  38.198 +
  38.199  	if (abort)
  38.200  		strcpy(abortstr, "F");
  38.201  	else
  38.202 @@ -645,6 +682,7 @@ bool xs_transaction_end(struct xs_handle
  38.203  	
  38.204  	rc = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
  38.205  
  38.206 +	h->transaction_pthread = -1;
  38.207  	pthread_mutex_unlock(&h->transaction_mutex);
  38.208  
  38.209  	return rc;
    39.1 --- a/tools/xenstore/xs.h	Mon Oct 10 14:42:38 2005 +0100
    39.2 +++ b/tools/xenstore/xs.h	Mon Oct 10 14:46:53 2005 +0100
    39.3 @@ -23,6 +23,7 @@
    39.4  #include <xs_lib.h>
    39.5  
    39.6  struct xs_handle;
    39.7 +struct xs_transaction_handle;
    39.8  
    39.9  /* On failure, these routines set errno. */
   39.10  
   39.11 @@ -44,41 +45,47 @@ void xs_daemon_close(struct xs_handle *)
   39.12   * Returns a malloced array: call free() on it after use.
   39.13   * Num indicates size.
   39.14   */
   39.15 -char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num);
   39.16 +char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t,
   39.17 +		    const char *path, unsigned int *num);
   39.18  
   39.19  /* Get the value of a single file, nul terminated.
   39.20   * Returns a malloced value: call free() on it after use.
   39.21   * len indicates length in bytes, not including terminator.
   39.22   */
   39.23 -void *xs_read(struct xs_handle *h, const char *path, unsigned int *len);
   39.24 +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
   39.25 +	      const char *path, unsigned int *len);
   39.26  
   39.27  /* Write the value of a single file.
   39.28   * Returns false on failure.
   39.29   */
   39.30 -bool xs_write(struct xs_handle *h, const char *path, const void *data,
   39.31 -	      unsigned int len);
   39.32 +bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t,
   39.33 +	      const char *path, const void *data, unsigned int len);
   39.34  
   39.35  /* Create a new directory.
   39.36   * Returns false on failure, or success if it already exists.
   39.37   */
   39.38 -bool xs_mkdir(struct xs_handle *h, const char *path);
   39.39 +bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
   39.40 +	      const char *path);
   39.41  
   39.42  /* Destroy a file or directory (and children).
   39.43   * Returns false on failure, or success if it doesn't exist.
   39.44   */
   39.45 -bool xs_rm(struct xs_handle *h, const char *path);
   39.46 +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
   39.47 +	   const char *path);
   39.48  
   39.49  /* Get permissions of node (first element is owner, first perms is "other").
   39.50   * Returns malloced array, or NULL: call free() after use.
   39.51   */
   39.52  struct xs_permissions *xs_get_permissions(struct xs_handle *h,
   39.53 +					  struct xs_transaction_handle *t,
   39.54  					  const char *path, unsigned int *num);
   39.55  
   39.56  /* Set permissions of node (must be owner).
   39.57   * Returns false on failure.
   39.58   */
   39.59 -bool xs_set_permissions(struct xs_handle *h, const char *path,
   39.60 -			struct xs_permissions *perms, unsigned int num_perms);
   39.61 +bool xs_set_permissions(struct xs_handle *h, struct xs_transaction_handle *t,
   39.62 +			const char *path, struct xs_permissions *perms,
   39.63 +			unsigned int num_perms);
   39.64  
   39.65  /* Watch a node for changes (poll on fd to detect, or call read_watch()).
   39.66   * When the node (or any child) changes, fd will become readable.
   39.67 @@ -96,12 +103,6 @@ int xs_fileno(struct xs_handle *h);
   39.68   */
   39.69  char **xs_read_watch(struct xs_handle *h, unsigned int *num);
   39.70  
   39.71 -/* Acknowledge watch on node.  Watches must be acknowledged before
   39.72 - * any other watches can be read.
   39.73 - * Returns false on failure.
   39.74 - */
   39.75 -bool xs_acknowledge_watch(struct xs_handle *h, const char *token);
   39.76 -
   39.77  /* Remove a watch on a node: implicitly acks any outstanding watch.
   39.78   * Returns false on failure (no watch on that node).
   39.79   */
   39.80 @@ -110,16 +111,17 @@ bool xs_unwatch(struct xs_handle *h, con
   39.81  /* Start a transaction: changes by others will not be seen during this
   39.82   * transaction, and changes will not be visible to others until end.
   39.83   * You can only have one transaction at any time.
   39.84 - * Returns false on failure.
   39.85 + * Returns NULL on failure.
   39.86   */
   39.87 -bool xs_transaction_start(struct xs_handle *h);
   39.88 +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h);
   39.89  
   39.90  /* End a transaction.
   39.91   * If abandon is true, transaction is discarded instead of committed.
   39.92   * Returns false on failure: if errno == EAGAIN, you have to restart
   39.93   * transaction.
   39.94   */
   39.95 -bool xs_transaction_end(struct xs_handle *h, bool abort);
   39.96 +bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
   39.97 +			bool abort);
   39.98  
   39.99  /* Introduce a new domain.
  39.100   * This tells the store daemon about a shared memory page, event channel
  39.101 @@ -142,3 +144,13 @@ char *xs_debug_command(struct xs_handle 
  39.102  		       void *data, unsigned int len);
  39.103  
  39.104  #endif /* _XS_H */
  39.105 +
  39.106 +/*
  39.107 + * Local variables:
  39.108 + *  c-file-style: "linux"
  39.109 + *  indent-tabs-mode: t
  39.110 + *  c-indent-level: 8
  39.111 + *  c-basic-offset: 8
  39.112 + *  tab-width: 8
  39.113 + * End:
  39.114 + */
    40.1 --- a/tools/xenstore/xs_test.c	Mon Oct 10 14:42:38 2005 +0100
    40.2 +++ b/tools/xenstore/xs_test.c	Mon Oct 10 14:46:53 2005 +0100
    40.3 @@ -42,6 +42,7 @@
    40.4  #define XSTEST
    40.5  
    40.6  static struct xs_handle *handles[10] = { NULL };
    40.7 +static struct xs_transaction_handle *txh[10] = { NULL };
    40.8  
    40.9  static unsigned int timeout_ms = 500;
   40.10  static bool timeout_suppressed = true;
   40.11 @@ -201,7 +202,6 @@ static void __attribute__((noreturn)) us
   40.12  	     "  watch <path> <token>\n"
   40.13  	     "  watchnoack <path> <token>\n"
   40.14  	     "  waitwatch\n"
   40.15 -	     "  ackwatch <token>\n"
   40.16  	     "  unwatch <path> <token>\n"
   40.17  	     "  close\n"
   40.18  	     "  start <node>\n"
   40.19 @@ -313,7 +313,7 @@ static void do_dir(unsigned int handle, 
   40.20  	char **entries;
   40.21  	unsigned int i, num;
   40.22  
   40.23 -	entries = xs_directory(handles[handle], path, &num);
   40.24 +	entries = xs_directory(handles[handle], txh[handle], path, &num);
   40.25  	if (!entries) {
   40.26  		failed(handle);
   40.27  		return;
   40.28 @@ -332,7 +332,7 @@ static void do_read(unsigned int handle,
   40.29  	char *value;
   40.30  	unsigned int len;
   40.31  
   40.32 -	value = xs_read(handles[handle], path, &len);
   40.33 +	value = xs_read(handles[handle], txh[handle], path, &len);
   40.34  	if (!value) {
   40.35  		failed(handle);
   40.36  		return;
   40.37 @@ -348,7 +348,7 @@ static void do_read(unsigned int handle,
   40.38  
   40.39  static void do_write(unsigned int handle, char *path, char *data)
   40.40  {
   40.41 -	if (!xs_write(handles[handle], path, data, strlen(data)))
   40.42 +	if (!xs_write(handles[handle], txh[handle], path, data, strlen(data)))
   40.43  		failed(handle);
   40.44  }
   40.45  
   40.46 @@ -361,13 +361,13 @@ static void do_setid(unsigned int handle
   40.47  
   40.48  static void do_mkdir(unsigned int handle, char *path)
   40.49  {
   40.50 -	if (!xs_mkdir(handles[handle], path))
   40.51 +	if (!xs_mkdir(handles[handle], txh[handle], path))
   40.52  		failed(handle);
   40.53  }
   40.54  
   40.55  static void do_rm(unsigned int handle, char *path)
   40.56  {
   40.57 -	if (!xs_rm(handles[handle], path))
   40.58 +	if (!xs_rm(handles[handle], txh[handle], path))
   40.59  		failed(handle);
   40.60  }
   40.61  
   40.62 @@ -376,7 +376,7 @@ static void do_getperm(unsigned int hand
   40.63  	unsigned int i, num;
   40.64  	struct xs_permissions *perms;
   40.65  
   40.66 -	perms = xs_get_permissions(handles[handle], path, &num);
   40.67 +	perms = xs_get_permissions(handles[handle], txh[handle], path, &num);
   40.68  	if (!perms) {
   40.69  		failed(handle);
   40.70  		return;
   40.71 @@ -437,7 +437,7 @@ static void do_setperm(unsigned int hand
   40.72  			barf("bad flags %s\n", arg);
   40.73  	}
   40.74  
   40.75 -	if (!xs_set_permissions(handles[handle], path, perms, i))
   40.76 +	if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i))
   40.77  		failed(handle);
   40.78  }
   40.79  
   40.80 @@ -455,8 +455,6 @@ static void do_watch(unsigned int handle
   40.81  		    !streq(vec[XS_WATCH_PATH], node) ||
   40.82  		    !streq(vec[XS_WATCH_TOKEN], token))
   40.83  			failed(handle);
   40.84 -		if (!xs_acknowledge_watch(handles[handle], token))
   40.85 -			failed(handle);
   40.86  	}
   40.87  }
   40.88  
   40.89 @@ -515,12 +513,6 @@ static void do_waitwatch(unsigned int ha
   40.90  	free(vec);
   40.91  }
   40.92  
   40.93 -static void do_ackwatch(unsigned int handle, const char *token)
   40.94 -{
   40.95 -	if (!xs_acknowledge_watch(handles[handle], token))
   40.96 -		failed(handle);
   40.97 -}
   40.98 -
   40.99  static void do_unwatch(unsigned int handle, const char *node, const char *token)
  40.100  {
  40.101  	if (!xs_unwatch(handles[handle], node, token))
  40.102 @@ -529,14 +521,16 @@ static void do_unwatch(unsigned int hand
  40.103  
  40.104  static void do_start(unsigned int handle)
  40.105  {
  40.106 -	if (!xs_transaction_start(handles[handle]))
  40.107 +	txh[handle] = xs_transaction_start(handles[handle]);
  40.108 +	if (txh[handle] == NULL)
  40.109  		failed(handle);
  40.110  }
  40.111  
  40.112  static void do_end(unsigned int handle, bool abort)
  40.113  {
  40.114 -	if (!xs_transaction_end(handles[handle], abort))
  40.115 +	if (!xs_transaction_end(handles[handle], txh[handle], abort))
  40.116  		failed(handle);
  40.117 +	txh[handle] = NULL;
  40.118  }
  40.119  
  40.120  static void do_introduce(unsigned int handle,
  40.121 @@ -626,7 +620,8 @@ static void dump_dir(unsigned int handle
  40.122  
  40.123  		sprintf(subnode, "%s/%s", node, dir[i]);
  40.124  
  40.125 -		perms = xs_get_permissions(handles[handle], subnode,&numperms);
  40.126 +		perms = xs_get_permissions(handles[handle], txh[handle],
  40.127 +					   subnode,&numperms);
  40.128  		if (!perms) {
  40.129  			failed(handle);
  40.130  			return;
  40.131 @@ -643,7 +638,8 @@ static void dump_dir(unsigned int handle
  40.132  		output("\n");
  40.133  
  40.134  		/* Even directories can have contents. */
  40.135 -		contents = xs_read(handles[handle], subnode, &len);
  40.136 +		contents = xs_read(handles[handle], txh[handle], 
  40.137 +				   subnode, &len);
  40.138  		if (!contents) {
  40.139  			if (errno != EISDIR)
  40.140  				failed(handle);
  40.141 @@ -653,7 +649,8 @@ static void dump_dir(unsigned int handle
  40.142  		}			
  40.143  
  40.144  		/* Every node is a directory. */
  40.145 -		subdirs = xs_directory(handles[handle], subnode, &subnum);
  40.146 +		subdirs = xs_directory(handles[handle], txh[handle], 
  40.147 +				       subnode, &subnum);
  40.148  		if (!subdirs) {
  40.149  			failed(handle);
  40.150  			return;
  40.151 @@ -668,7 +665,7 @@ static void dump(int handle)
  40.152  	char **subdirs;
  40.153  	unsigned int subnum;
  40.154  
  40.155 -	subdirs = xs_directory(handles[handle], "/", &subnum);
  40.156 +	subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum);
  40.157  	if (!subdirs) {
  40.158  		failed(handle);
  40.159  		return;
  40.160 @@ -746,13 +743,12 @@ static void do_command(unsigned int defa
  40.161  		do_watch(handle, arg(line, 1), arg(line, 2), false);
  40.162  	else if (streq(command, "waitwatch"))
  40.163  		do_waitwatch(handle);
  40.164 -	else if (streq(command, "ackwatch"))
  40.165 -		do_ackwatch(handle, arg(line, 1));
  40.166  	else if (streq(command, "unwatch"))
  40.167  		do_unwatch(handle, arg(line, 1), arg(line, 2));
  40.168  	else if (streq(command, "close")) {
  40.169  		xs_daemon_close(handles[handle]);
  40.170  		handles[handle] = NULL;
  40.171 +		txh[handle] = NULL;
  40.172  	} else if (streq(command, "start"))
  40.173  		do_start(handle);
  40.174  	else if (streq(command, "commit"))
  40.175 @@ -836,3 +832,13 @@ int main(int argc, char *argv[])
  40.176  
  40.177  	return 0;
  40.178  }
  40.179 +
  40.180 +/*
  40.181 + * Local variables:
  40.182 + *  c-file-style: "linux"
  40.183 + *  indent-tabs-mode: t
  40.184 + *  c-indent-level: 8
  40.185 + *  c-basic-offset: 8
  40.186 + *  tab-width: 8
  40.187 + * End:
  40.188 + */
    41.1 --- a/xen/include/public/io/xs_wire.h	Mon Oct 10 14:42:38 2005 +0100
    41.2 +++ b/xen/include/public/io/xs_wire.h	Mon Oct 10 14:46:53 2005 +0100
    41.3 @@ -30,25 +30,23 @@
    41.4  
    41.5  enum xsd_sockmsg_type
    41.6  {
    41.7 -	XS_DEBUG,
    41.8 -	XS_DIRECTORY,
    41.9 -	XS_READ,
   41.10 -	XS_GET_PERMS,
   41.11 -	XS_WATCH,
   41.12 -	XS_WATCH_ACK,
   41.13 -	XS_UNWATCH,
   41.14 -	XS_TRANSACTION_START,
   41.15 -	XS_TRANSACTION_END,
   41.16 -	XS_OP_READ_ONLY = XS_TRANSACTION_END,
   41.17 -	XS_INTRODUCE,
   41.18 -	XS_RELEASE,
   41.19 -	XS_GET_DOMAIN_PATH,
   41.20 -	XS_WRITE,
   41.21 -	XS_MKDIR,
   41.22 -	XS_RM,
   41.23 -	XS_SET_PERMS,
   41.24 -	XS_WATCH_EVENT,
   41.25 -	XS_ERROR,
   41.26 +    XS_DEBUG,
   41.27 +    XS_DIRECTORY,
   41.28 +    XS_READ,
   41.29 +    XS_GET_PERMS,
   41.30 +    XS_WATCH,
   41.31 +    XS_UNWATCH,
   41.32 +    XS_TRANSACTION_START,
   41.33 +    XS_TRANSACTION_END,
   41.34 +    XS_INTRODUCE,
   41.35 +    XS_RELEASE,
   41.36 +    XS_GET_DOMAIN_PATH,
   41.37 +    XS_WRITE,
   41.38 +    XS_MKDIR,
   41.39 +    XS_RM,
   41.40 +    XS_SET_PERMS,
   41.41 +    XS_WATCH_EVENT,
   41.42 +    XS_ERROR,
   41.43  };
   41.44  
   41.45  #define XS_WRITE_NONE "NONE"
   41.46 @@ -58,38 +56,40 @@ enum xsd_sockmsg_type
   41.47  /* We hand errors as strings, for portability. */
   41.48  struct xsd_errors
   41.49  {
   41.50 -	int errnum;
   41.51 -	const char *errstring;
   41.52 +    int errnum;
   41.53 +    const char *errstring;
   41.54  };
   41.55  #define XSD_ERROR(x) { x, #x }
   41.56  static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
   41.57 -	XSD_ERROR(EINVAL),
   41.58 -	XSD_ERROR(EACCES),
   41.59 -	XSD_ERROR(EEXIST),
   41.60 -	XSD_ERROR(EISDIR),
   41.61 -	XSD_ERROR(ENOENT),
   41.62 -	XSD_ERROR(ENOMEM),
   41.63 -	XSD_ERROR(ENOSPC),
   41.64 -	XSD_ERROR(EIO),
   41.65 -	XSD_ERROR(ENOTEMPTY),
   41.66 -	XSD_ERROR(ENOSYS),
   41.67 -	XSD_ERROR(EROFS),
   41.68 -	XSD_ERROR(EBUSY),
   41.69 -	XSD_ERROR(EAGAIN),
   41.70 -	XSD_ERROR(EISCONN),
   41.71 +    XSD_ERROR(EINVAL),
   41.72 +    XSD_ERROR(EACCES),
   41.73 +    XSD_ERROR(EEXIST),
   41.74 +    XSD_ERROR(EISDIR),
   41.75 +    XSD_ERROR(ENOENT),
   41.76 +    XSD_ERROR(ENOMEM),
   41.77 +    XSD_ERROR(ENOSPC),
   41.78 +    XSD_ERROR(EIO),
   41.79 +    XSD_ERROR(ENOTEMPTY),
   41.80 +    XSD_ERROR(ENOSYS),
   41.81 +    XSD_ERROR(EROFS),
   41.82 +    XSD_ERROR(EBUSY),
   41.83 +    XSD_ERROR(EAGAIN),
   41.84 +    XSD_ERROR(EISCONN),
   41.85  };
   41.86  struct xsd_sockmsg
   41.87  {
   41.88 -	u32 type;
   41.89 -	u32 len; 		/* Length of data following this. */
   41.90 +    u32 type;  /* XS_??? */
   41.91 +    u32 req_id;/* Request identifier, echoed in daemon's response.  */
   41.92 +    u32 tx_id; /* Transaction id (0 if not related to a transaction). */
   41.93 +    u32 len;   /* Length of data following this. */
   41.94  
   41.95 -	/* Generally followed by nul-terminated string(s). */
   41.96 +    /* Generally followed by nul-terminated string(s). */
   41.97  };
   41.98  
   41.99  enum xs_watch_type
  41.100  {
  41.101 -	XS_WATCH_PATH = 0,
  41.102 -	XS_WATCH_TOKEN,
  41.103 +    XS_WATCH_PATH = 0,
  41.104 +    XS_WATCH_TOKEN,
  41.105  };
  41.106  
  41.107  #endif /* _XS_WIRE_H */