ia64/xen-unstable

changeset 7329:74d56b7ff46c

Merged
author djm@kirby.fc.hp.com
date Tue Oct 11 16:57:44 2005 -0600 (2005-10-11)
parents 333f722ed6d0 4e335372ace8
children c8eb9d82dd4b c05d5e85ded2
files .hgignore Makefile buildconfigs/Rules.mk linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c linux-2.6-xen-sparse/arch/xen/kernel/reboot.c linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c linux-2.6-xen-sparse/include/asm-xen/xenbus.h tools/console/daemon/io.c tools/examples/Makefile tools/python/xen/lowlevel/xs/xs.c tools/python/xen/xend/XendCheckpoint.py tools/python/xen/xend/XendClient.py tools/python/xen/xend/XendDomain.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/SrvDomain.py tools/python/xen/xend/server/SrvDomainDir.py tools/python/xen/xend/xenstore/xstransact.py tools/python/xen/xm/main.py tools/xenstore/Makefile tools/xenstore/testsuite/08transaction.test tools/xenstore/testsuite/12readonly.test tools/xenstore/xenstore_client.c tools/xenstore/xenstored_core.c tools/xenstore/xenstored_core.h tools/xenstore/xenstored_domain.c tools/xenstore/xenstored_transaction.c tools/xenstore/xenstored_transaction.h tools/xenstore/xenstored_watch.c tools/xenstore/xenstored_watch.h tools/xenstore/xs.c tools/xenstore/xs.h tools/xenstore/xs_test.c
line diff
     1.1 --- a/.hgignore	Tue Oct 11 15:50:21 2005 -0600
     1.2 +++ b/.hgignore	Tue Oct 11 16:57:44 2005 -0600
     1.3 @@ -161,6 +161,7 @@
     1.4  ^tools/xenstore/xs_tdb_dump$
     1.5  ^tools/xenstore/xs_test$
     1.6  ^tools/xenstore/xs_watch_stress$
     1.7 +^tools/xenstore/xsls$
     1.8  ^tools/xentrace/xenctx$
     1.9  ^tools/xentrace/xentrace$
    1.10  ^xen/BLOG$
     2.1 --- a/Makefile	Tue Oct 11 15:50:21 2005 -0600
     2.2 +++ b/Makefile	Tue Oct 11 16:57:44 2005 -0600
     2.3 @@ -66,7 +66,7 @@ install-tools:
     2.4  	$(MAKE) -C tools install
     2.5  
     2.6  install-kernels:
     2.7 -	for i in $(XKERNELS) ; do $(MAKE) $$i-build || exit 1; done
     2.8 +	for i in $(XKERNELS) ; do $(MAKE) $$i-install || exit 1; done
     2.9  
    2.10  install-docs:
    2.11  	sh ./docs/check_pkgs && $(MAKE) -C docs install || true
    2.12 @@ -179,7 +179,7 @@ uninstall:
    2.13  	rm -rf $(D)/usr/$(LIBDIR)/libxenctrl* $(D)/usr/$(LIBDIR)/libxenguest*
    2.14  	rm -rf $(D)/usr/$(LIBDIR)/libxenstore*
    2.15  	rm -rf $(D)/usr/$(LIBDIR)/python/xen $(D)/usr/$(LIBDIR)/xen 
    2.16 -	rm -rf $(D)/usr/libexec/xen
    2.17 +	rm -rf $(D)/usr/$(LIBDIR)/xen/bin
    2.18  	rm -rf $(D)/usr/sbin/xen* $(D)/usr/sbin/netfix $(D)/usr/sbin/xm
    2.19  	rm -rf $(D)/usr/share/doc/xen
    2.20  	rm -rf $(D)/usr/share/xen
     3.1 --- a/buildconfigs/Rules.mk	Tue Oct 11 15:50:21 2005 -0600
     3.2 +++ b/buildconfigs/Rules.mk	Tue Oct 11 16:57:44 2005 -0600
     3.3 @@ -87,9 +87,17 @@ ref-%/.valid-ref: pristine-%/.valid-pris
     3.4  	touch $@ # update timestamp to avoid rebuild
     3.5  endif
     3.6  
     3.7 -%-build:
     3.8 +%-install:
     3.9  	$(MAKE) -f buildconfigs/mk.$* build
    3.10  
    3.11 +%-dist: DESTDIR=$(DISTDIR)/install
    3.12 +%-dist: %-install
    3.13 +	@: # do nothing
    3.14 +
    3.15 +# Legacy dist target
    3.16 +%-build: %-dist
    3.17 +	@: # do nothing
    3.18 +
    3.19  %-delete:
    3.20  	$(MAKE) -f buildconfigs/mk.$* delete
    3.21  
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/boot/Makefile	Tue Oct 11 15:50:21 2005 -0600
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/boot/Makefile	Tue Oct 11 16:57:44 2005 -0600
     4.3 @@ -8,4 +8,4 @@ vmlinux-stripped: vmlinux FORCE
     4.4  	$(call if_changed,objcopy)
     4.5  
     4.6  bzImage: vmlinuz
     4.7 -	$(Q)$(LN) -sf ../../../vmlinuz $(srctree)/arch/xen/boot/bzImage
     4.8 +	$(Q)ln -sf ../../../vmlinuz $(srctree)/arch/xen/boot/bzImage
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Tue Oct 11 15:50:21 2005 -0600
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c	Tue Oct 11 16:57:44 2005 -0600
     5.3 @@ -1327,18 +1327,14 @@ static struct xenbus_watch cpu_watch = {
     5.4  	.callback = handle_vcpu_hotplug_event
     5.5  };
     5.6  
     5.7 -/* NB: Assumes xenbus_lock is held! */
     5.8  static int setup_cpu_watcher(struct notifier_block *notifier,
     5.9  			      unsigned long event, void *data)
    5.10  {
    5.11 -	int err = 0;
    5.12 +	int err;
    5.13  
    5.14 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
    5.15  	err = register_xenbus_watch(&cpu_watch);
    5.16 -
    5.17 -	if (err) {
    5.18 +	if (err)
    5.19  		printk("Failed to register watch on /cpu\n");
    5.20 -	}
    5.21  
    5.22  	return NOTIFY_DONE;
    5.23  }
    5.24 @@ -1368,7 +1364,7 @@ static void handle_vcpu_hotplug_event(st
    5.25  			return;
    5.26  
    5.27  		/* get the state value */
    5.28 -		err = xenbus_scanf(dir, "availability", "%s", state);
    5.29 +		err = xenbus_scanf(NULL, dir, "availability", "%s", state);
    5.30  
    5.31  		if (err != 1) {
    5.32  			printk(KERN_ERR
    5.33 @@ -1578,7 +1574,7 @@ void smp_suspend(void)
    5.34  void smp_resume(void)
    5.35  {
    5.36  	smp_intr_init();
    5.37 -	local_setup_timer_irq();
    5.38 +	local_setup_timer();
    5.39  }
    5.40  
    5.41  void vcpu_prepare(int vcpu)
     6.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c	Tue Oct 11 15:50:21 2005 -0600
     6.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c	Tue Oct 11 16:57:44 2005 -0600
     6.3 @@ -122,7 +122,7 @@ static u32 shadow_tv_version;
     6.4  static u64 processed_system_time;   /* System time (ns) at last processing. */
     6.5  static DEFINE_PER_CPU(u64, processed_system_time);
     6.6  
     6.7 -#define NS_PER_TICK (1000000000L/HZ)
     6.8 +#define NS_PER_TICK (1000000000ULL/HZ)
     6.9  
    6.10  static inline void __normalize_time(time_t *sec, s64 *nsec)
    6.11  {
    6.12 @@ -800,9 +800,9 @@ static inline u64 jiffies_to_st(unsigned
    6.13  		delta = j - jiffies;
    6.14  		/* NB. The next check can trigger in some wrap-around cases,
    6.15  		 * but that's ok: we'll just end up with a shorter timeout. */
    6.16 -		if (delta < 1)
    6.17 +		if (delta < 1) 
    6.18  			delta = 1;
    6.19 -		st = processed_system_time + (delta * NS_PER_TICK);
    6.20 +		st = processed_system_time + ((u64)delta * NS_PER_TICK);
    6.21  	} while (read_seqretry(&xtime_lock, seq));
    6.22  
    6.23  	return st;
    6.24 @@ -816,7 +816,7 @@ void stop_hz_timer(void)
    6.25  {
    6.26  	unsigned int cpu = smp_processor_id();
    6.27  	unsigned long j;
    6.28 -
    6.29 +	
    6.30  	/* s390 does this /before/ checking rcu_pending(). We copy them. */
    6.31  	cpu_set(cpu, nohz_cpu_mask);
    6.32  
     7.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Tue Oct 11 15:50:21 2005 -0600
     7.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c	Tue Oct 11 16:57:44 2005 -0600
     7.3 @@ -270,26 +270,28 @@ static void __shutdown_handler(void *unu
     7.4  	}
     7.5  }
     7.6  
     7.7 -static void shutdown_handler(struct xenbus_watch *watch, const char *node)
     7.8 +static void shutdown_handler(struct xenbus_watch *watch,
     7.9 +			     const char **vec, unsigned int len)
    7.10  {
    7.11  	static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL);
    7.12  	char *str;
    7.13 +	struct xenbus_transaction *xbt;
    7.14  	int err;
    7.15  
    7.16   again:
    7.17 -	err = xenbus_transaction_start();
    7.18 -	if (err)
    7.19 +	xbt = xenbus_transaction_start();
    7.20 +	if (IS_ERR(xbt))
    7.21  		return;
    7.22 -	str = (char *)xenbus_read("control", "shutdown", NULL);
    7.23 +	str = (char *)xenbus_read(xbt, "control", "shutdown", NULL);
    7.24  	/* Ignore read errors and empty reads. */
    7.25  	if (XENBUS_IS_ERR_READ(str)) {
    7.26 -		xenbus_transaction_end(1);
    7.27 +		xenbus_transaction_end(xbt, 1);
    7.28  		return;
    7.29  	}
    7.30  
    7.31 -	xenbus_write("control", "shutdown", "");
    7.32 +	xenbus_write(xbt, "control", "shutdown", "");
    7.33  
    7.34 -	err = xenbus_transaction_end(0);
    7.35 +	err = xenbus_transaction_end(xbt, 0);
    7.36  	if (err == -EAGAIN) {
    7.37  		kfree(str);
    7.38  		goto again;
    7.39 @@ -315,26 +317,28 @@ static void shutdown_handler(struct xenb
    7.40  }
    7.41  
    7.42  #ifdef CONFIG_MAGIC_SYSRQ
    7.43 -static void sysrq_handler(struct xenbus_watch *watch, const char *node)
    7.44 +static void sysrq_handler(struct xenbus_watch *watch, const char **vec,
    7.45 +			  unsigned int len)
    7.46  {
    7.47  	char sysrq_key = '\0';
    7.48 +	struct xenbus_transaction *xbt;
    7.49  	int err;
    7.50  
    7.51   again:
    7.52 -	err = xenbus_transaction_start();
    7.53 -	if (err)
    7.54 +	xbt  = xenbus_transaction_start();
    7.55 +	if (IS_ERR(xbt))
    7.56  		return;
    7.57 -	if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) {
    7.58 +	if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) {
    7.59  		printk(KERN_ERR "Unable to read sysrq code in "
    7.60  		       "control/sysrq\n");
    7.61 -		xenbus_transaction_end(1);
    7.62 +		xenbus_transaction_end(xbt, 1);
    7.63  		return;
    7.64  	}
    7.65  
    7.66  	if (sysrq_key != '\0')
    7.67 -		xenbus_printf("control", "sysrq", "%c", '\0');
    7.68 +		xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
    7.69  
    7.70 -	err = xenbus_transaction_end(0);
    7.71 +	err = xenbus_transaction_end(xbt, 0);
    7.72  	if (err == -EAGAIN)
    7.73  		goto again;
    7.74  
    7.75 @@ -358,9 +362,6 @@ static struct xenbus_watch sysrq_watch =
    7.76  
    7.77  static struct notifier_block xenstore_notifier;
    7.78  
    7.79 -/* Setup our watcher
    7.80 -   NB: Assumes xenbus_lock is held!
    7.81 -*/
    7.82  static int setup_shutdown_watcher(struct notifier_block *notifier,
    7.83                                    unsigned long event,
    7.84                                    void *data)
    7.85 @@ -370,8 +371,6 @@ static int setup_shutdown_watcher(struct
    7.86  	int err2 = 0;
    7.87  #endif
    7.88  
    7.89 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
    7.90 -
    7.91  	err1 = register_xenbus_watch(&shutdown_watch);
    7.92  #ifdef CONFIG_MAGIC_SYSRQ
    7.93  	err2 = register_xenbus_watch(&sysrq_watch);
    7.94 @@ -411,4 +410,3 @@ subsys_initcall(setup_shutdown_event);
    7.95   *  tab-width: 8
    7.96   * End:
    7.97   */
    7.98 -#
     8.1 --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Tue Oct 11 15:50:21 2005 -0600
     8.2 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c	Tue Oct 11 16:57:44 2005 -0600
     8.3 @@ -357,7 +357,7 @@ static void watch_target(struct xenbus_w
     8.4  	unsigned long long new_target;
     8.5  	int err;
     8.6  
     8.7 -	err = xenbus_scanf("memory", "target", "%llu", &new_target);
     8.8 +	err = xenbus_scanf(NULL, "memory", "target", "%llu", &new_target);
     8.9  	if (err != 1) {
    8.10  		printk(KERN_ERR "Unable to read memory/target\n");
    8.11  		return;
    8.12 @@ -370,17 +370,12 @@ static void watch_target(struct xenbus_w
    8.13      
    8.14  }
    8.15  
    8.16 -/* Setup our watcher
    8.17 -   NB: Assumes xenbus_lock is held!
    8.18 -*/
    8.19  int balloon_init_watcher(struct notifier_block *notifier,
    8.20                           unsigned long event,
    8.21                           void *data)
    8.22  {
    8.23  	int err;
    8.24  
    8.25 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
    8.26 -
    8.27  	err = register_xenbus_watch(&target_watch);
    8.28  	if (err)
    8.29  		printk(KERN_ERR "Failed to set balloon watcher\n");
     9.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Tue Oct 11 15:50:21 2005 -0600
     9.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c	Tue Oct 11 16:57:44 2005 -0600
     9.3 @@ -61,18 +61,19 @@ static void frontend_changed(struct xenb
     9.4  	unsigned long ring_ref;
     9.5  	unsigned int evtchn;
     9.6  	int err;
     9.7 +	struct xenbus_transaction *xbt;
     9.8  	struct backend_info *be
     9.9  		= container_of(watch, struct backend_info, watch);
    9.10  
    9.11  	/* If other end is gone, delete ourself. */
    9.12 -	if (vec && !xenbus_exists(be->frontpath, "")) {
    9.13 +	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
    9.14  		device_unregister(&be->dev->dev);
    9.15  		return;
    9.16  	}
    9.17  	if (be->blkif == NULL || be->blkif->status == CONNECTED)
    9.18  		return;
    9.19  
    9.20 -	err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref,
    9.21 +	err = xenbus_gather(NULL, be->frontpath, "ring-ref", "%lu", &ring_ref,
    9.22  			    "event-channel", "%u", &evtchn, NULL);
    9.23  	if (err) {
    9.24  		xenbus_dev_error(be->dev, err,
    9.25 @@ -84,7 +85,8 @@ static void frontend_changed(struct xenb
    9.26  	/* Map the shared frame, irq etc. */
    9.27  	err = blkif_map(be->blkif, ring_ref, evtchn);
    9.28  	if (err) {
    9.29 -		xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u",
    9.30 +		xenbus_dev_error(be->dev, err,
    9.31 +				 "mapping ring-ref %lu port %u",
    9.32  				 ring_ref, evtchn);
    9.33  		return;
    9.34  	}
    9.35 @@ -92,13 +94,13 @@ static void frontend_changed(struct xenb
    9.36  
    9.37  again:
    9.38  	/* Supply the information about the device the frontend needs */
    9.39 -	err = xenbus_transaction_start();
    9.40 -	if (err) {
    9.41 +	xbt = xenbus_transaction_start();
    9.42 +	if (IS_ERR(xbt)) {
    9.43  		xenbus_dev_error(be->dev, err, "starting transaction");
    9.44  		return;
    9.45  	}
    9.46  
    9.47 -	err = xenbus_printf(be->dev->nodename, "sectors", "%lu",
    9.48 +	err = xenbus_printf(xbt, be->dev->nodename, "sectors", "%lu",
    9.49  			    vbd_size(&be->blkif->vbd));
    9.50  	if (err) {
    9.51  		xenbus_dev_error(be->dev, err, "writing %s/sectors",
    9.52 @@ -107,14 +109,14 @@ again:
    9.53  	}
    9.54  
    9.55  	/* FIXME: use a typename instead */
    9.56 -	err = xenbus_printf(be->dev->nodename, "info", "%u",
    9.57 +	err = xenbus_printf(xbt, be->dev->nodename, "info", "%u",
    9.58  			    vbd_info(&be->blkif->vbd));
    9.59  	if (err) {
    9.60  		xenbus_dev_error(be->dev, err, "writing %s/info",
    9.61  				 be->dev->nodename);
    9.62  		goto abort;
    9.63  	}
    9.64 -	err = xenbus_printf(be->dev->nodename, "sector-size", "%lu",
    9.65 +	err = xenbus_printf(xbt, be->dev->nodename, "sector-size", "%lu",
    9.66  			    vbd_secsize(&be->blkif->vbd));
    9.67  	if (err) {
    9.68  		xenbus_dev_error(be->dev, err, "writing %s/sector-size",
    9.69 @@ -122,7 +124,7 @@ again:
    9.70  		goto abort;
    9.71  	}
    9.72  
    9.73 -	err = xenbus_transaction_end(0);
    9.74 +	err = xenbus_transaction_end(xbt, 0);
    9.75  	if (err == -EAGAIN)
    9.76  		goto again;
    9.77  	if (err) {
    9.78 @@ -136,7 +138,7 @@ again:
    9.79  	return;
    9.80  
    9.81   abort:
    9.82 -	xenbus_transaction_end(1);
    9.83 +	xenbus_transaction_end(xbt, 1);
    9.84  }
    9.85  
    9.86  /* 
    9.87 @@ -154,7 +156,8 @@ static void backend_changed(struct xenbu
    9.88  		= container_of(watch, struct backend_info, backend_watch);
    9.89  	struct xenbus_device *dev = be->dev;
    9.90  
    9.91 -	err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev);
    9.92 +	err = xenbus_scanf(NULL, dev->nodename,
    9.93 +			   "physical-device", "%li", &pdev);
    9.94  	if (XENBUS_EXIST_ERR(err))
    9.95  		return;
    9.96  	if (err < 0) {
    9.97 @@ -169,7 +172,7 @@ static void backend_changed(struct xenbu
    9.98  	be->pdev = pdev;
    9.99  
   9.100  	/* If there's a read-only node, we're read only. */
   9.101 -	p = xenbus_read(dev->nodename, "read-only", NULL);
   9.102 +	p = xenbus_read(NULL, dev->nodename, "read-only", NULL);
   9.103  	if (!IS_ERR(p)) {
   9.104  		be->readonly = 1;
   9.105  		kfree(p);
   9.106 @@ -184,7 +187,8 @@ static void backend_changed(struct xenbu
   9.107  		if (IS_ERR(be->blkif)) {
   9.108  			err = PTR_ERR(be->blkif);
   9.109  			be->blkif = NULL;
   9.110 -			xenbus_dev_error(dev, err, "creating block interface");
   9.111 +			xenbus_dev_error(dev, err,
   9.112 +					 "creating block interface");
   9.113  			return;
   9.114  		}
   9.115  
   9.116 @@ -192,7 +196,8 @@ static void backend_changed(struct xenbu
   9.117  		if (err) {
   9.118  			blkif_put(be->blkif);
   9.119  			be->blkif = NULL;
   9.120 -			xenbus_dev_error(dev, err, "creating vbd structure");
   9.121 +			xenbus_dev_error(dev, err,
   9.122 +					 "creating vbd structure");
   9.123  			return;
   9.124  		}
   9.125  
   9.126 @@ -210,13 +215,14 @@ static int blkback_probe(struct xenbus_d
   9.127  
   9.128  	be = kmalloc(sizeof(*be), GFP_KERNEL);
   9.129  	if (!be) {
   9.130 -		xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
   9.131 +		xenbus_dev_error(dev, -ENOMEM,
   9.132 +				 "allocating backend structure");
   9.133  		return -ENOMEM;
   9.134  	}
   9.135  	memset(be, 0, sizeof(*be));
   9.136  
   9.137  	frontend = NULL;
   9.138 -	err = xenbus_gather(dev->nodename,
   9.139 +	err = xenbus_gather(NULL, dev->nodename,
   9.140  			    "frontend-id", "%li", &be->frontend_id,
   9.141  			    "frontend", NULL, &frontend,
   9.142  			    NULL);
   9.143 @@ -228,7 +234,7 @@ static int blkback_probe(struct xenbus_d
   9.144  				 dev->nodename);
   9.145  		goto free_be;
   9.146  	}
   9.147 -	if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
   9.148 +	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
   9.149  		/* If we can't get a frontend path and a frontend-id,
   9.150  		 * then our bus-id is no longer valid and we need to
   9.151  		 * destroy the backend device.
   9.152 @@ -244,7 +250,8 @@ static int blkback_probe(struct xenbus_d
   9.153  	err = register_xenbus_watch(&be->backend_watch);
   9.154  	if (err) {
   9.155  		be->backend_watch.node = NULL;
   9.156 -		xenbus_dev_error(dev, err, "adding backend watch on %s",
   9.157 +		xenbus_dev_error(dev, err,
   9.158 +				 "adding backend watch on %s",
   9.159  				 dev->nodename);
   9.160  		goto free_be;
   9.161  	}
    10.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Tue Oct 11 15:50:21 2005 -0600
    10.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c	Tue Oct 11 16:57:44 2005 -0600
    10.3 @@ -460,7 +460,7 @@ static void watch_for_status(struct xenb
    10.4  	if (info->connected == BLKIF_STATE_CONNECTED)
    10.5  		return;
    10.6  
    10.7 -	err = xenbus_gather(watch->node,
    10.8 +	err = xenbus_gather(NULL, watch->node,
    10.9  			    "sectors", "%lu", &sectors,
   10.10  			    "info", "%u", &binfo,
   10.11  			    "sector-size", "%lu", &sector_size,
   10.12 @@ -532,10 +532,11 @@ static int talk_to_backend(struct xenbus
   10.13  {
   10.14  	char *backend;
   10.15  	const char *message;
   10.16 +	struct xenbus_transaction *xbt;
   10.17  	int err;
   10.18  
   10.19  	backend = NULL;
   10.20 -	err = xenbus_gather(dev->nodename,
   10.21 +	err = xenbus_gather(NULL, dev->nodename,
   10.22  			    "backend-id", "%i", &info->backend_id,
   10.23  			    "backend", NULL, &backend,
   10.24  			    NULL);
   10.25 @@ -559,25 +560,26 @@ static int talk_to_backend(struct xenbus
   10.26  	}
   10.27  
   10.28  again:
   10.29 -	err = xenbus_transaction_start();
   10.30 -	if (err) {
   10.31 +	xbt = xenbus_transaction_start();
   10.32 +	if (IS_ERR(xbt)) {
   10.33  		xenbus_dev_error(dev, err, "starting transaction");
   10.34  		goto destroy_blkring;
   10.35  	}
   10.36  
   10.37 -	err = xenbus_printf(dev->nodename, "ring-ref","%u", info->ring_ref);
   10.38 +	err = xenbus_printf(xbt, dev->nodename,
   10.39 +			    "ring-ref","%u", info->ring_ref);
   10.40  	if (err) {
   10.41  		message = "writing ring-ref";
   10.42  		goto abort_transaction;
   10.43  	}
   10.44 -	err = xenbus_printf(dev->nodename,
   10.45 +	err = xenbus_printf(xbt, dev->nodename,
   10.46  			    "event-channel", "%u", info->evtchn);
   10.47  	if (err) {
   10.48  		message = "writing event-channel";
   10.49  		goto abort_transaction;
   10.50  	}
   10.51  
   10.52 -	err = xenbus_transaction_end(0);
   10.53 +	err = xenbus_transaction_end(xbt, 0);
   10.54  	if (err) {
   10.55  		if (err == -EAGAIN)
   10.56  			goto again;
   10.57 @@ -598,8 +600,7 @@ again:
   10.58  	return 0;
   10.59  
   10.60   abort_transaction:
   10.61 -	xenbus_transaction_end(1);
   10.62 -	/* Have to do this *outside* transaction.  */
   10.63 +	xenbus_transaction_end(xbt, 1);
   10.64  	xenbus_dev_error(dev, err, "%s", message);
   10.65   destroy_blkring:
   10.66  	blkif_free(info);
   10.67 @@ -620,7 +621,8 @@ static int blkfront_probe(struct xenbus_
   10.68  	struct blkfront_info *info;
   10.69  
   10.70  	/* FIXME: Use dynamic device id if this is not set. */
   10.71 -	err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice);
   10.72 +	err = xenbus_scanf(NULL, dev->nodename,
   10.73 +			   "virtual-device", "%i", &vdevice);
   10.74  	if (XENBUS_EXIST_ERR(err))
   10.75  		return err;
   10.76  	if (err < 0) {
    11.1 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c	Tue Oct 11 15:50:21 2005 -0600
    11.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c	Tue Oct 11 16:57:44 2005 -0600
    11.3 @@ -160,7 +160,8 @@ xlbd_get_major_info(int vdevice)
    11.4  
    11.5  	mi = ((major_info[index] != NULL) ? major_info[index] :
    11.6  	      xlbd_alloc_major_info(major, minor, index));
    11.7 -	mi->usage++;
    11.8 +	if (mi)
    11.9 +		mi->usage++;
   11.10  	return mi;
   11.11  }
   11.12  
    12.1 --- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c	Tue Oct 11 15:50:21 2005 -0600
    12.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c	Tue Oct 11 16:57:44 2005 -0600
    12.3 @@ -20,69 +20,48 @@
    12.4  #include <linux/sched.h>
    12.5  #include <linux/err.h>
    12.6  #include "xencons_ring.h"
    12.7 -
    12.8 -struct ring_head
    12.9 -{
   12.10 -	u32 cons;
   12.11 -	u32 prod;
   12.12 -	char buf[0];
   12.13 -} __attribute__((packed));
   12.14 +#include <asm-xen/xen-public/io/console.h>
   12.15  
   12.16  static int xencons_irq;
   12.17 +static xencons_receiver_func *xencons_receiver;
   12.18  
   12.19 -#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
   12.20 -#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
   12.21 -#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
   12.22 -
   12.23 -static inline struct ring_head *outring(void)
   12.24 +static inline struct xencons_interface *xencons_interface(void)
   12.25  {
   12.26  	return mfn_to_virt(xen_start_info->console_mfn);
   12.27  }
   12.28  
   12.29 -static inline struct ring_head *inring(void)
   12.30 -{
   12.31 -	return mfn_to_virt(xen_start_info->console_mfn) + PAGE_SIZE/2;
   12.32 -}
   12.33 -
   12.34 -
   12.35 -/* don't block -  write as much as possible and return */
   12.36 -static int __xencons_ring_send(
   12.37 -	struct ring_head *ring, const char *data, unsigned len)
   12.38 -{
   12.39 -	int copied = 0;
   12.40 -
   12.41 -	mb();
   12.42 -	while (copied < len && !XENCONS_FULL(ring)) {
   12.43 -		ring->buf[XENCONS_IDX(ring->prod)] = data[copied];
   12.44 -		ring->prod++;
   12.45 -		copied++;
   12.46 -	}
   12.47 -	mb();
   12.48 -
   12.49 -	return copied;
   12.50 -}
   12.51 -
   12.52  int xencons_ring_send(const char *data, unsigned len)
   12.53  {
   12.54 -	int sent = __xencons_ring_send(outring(), data, len);
   12.55 +	int sent = 0;
   12.56 +	struct xencons_interface *intf = xencons_interface();
   12.57 +
   12.58 +	while ((sent < len) &&
   12.59 +	       (intf->out_prod - intf->out_cons) < sizeof(intf->out)) {
   12.60 +		intf->out[MASK_XENCONS_IDX(intf->out_prod, intf->out)] =
   12.61 +			data[sent];
   12.62 +		intf->out_prod++;
   12.63 +		sent++;
   12.64 +	}
   12.65 +
   12.66  	/* Use evtchn: this is called early, before irq is set up. */
   12.67  	notify_remote_via_evtchn(xen_start_info->console_evtchn);
   12.68 +
   12.69  	return sent;
   12.70  }	
   12.71  
   12.72 -
   12.73 -static xencons_receiver_func *xencons_receiver;
   12.74 -
   12.75  static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
   12.76  {
   12.77 -	struct ring_head *ring = inring();
   12.78 -	while (ring->cons < ring->prod) {
   12.79 -		if (xencons_receiver != NULL) {
   12.80 -			xencons_receiver(ring->buf + XENCONS_IDX(ring->cons),
   12.81 -					 1, regs);
   12.82 -		}
   12.83 -		ring->cons++;
   12.84 +	struct xencons_interface *intf = xencons_interface();
   12.85 +
   12.86 +	while (intf->in_cons != intf->in_prod) {
   12.87 +		if (xencons_receiver != NULL)
   12.88 +			xencons_receiver(
   12.89 +				intf->in + MASK_XENCONS_IDX(intf->in_cons,
   12.90 +							    intf->in),
   12.91 +				1, regs);
   12.92 +		intf->in_cons++;
   12.93  	}
   12.94 +
   12.95  	return IRQ_HANDLED;
   12.96  }
   12.97  
   12.98 @@ -96,7 +75,7 @@ int xencons_ring_init(void)
   12.99  	int err;
  12.100  
  12.101  	if (xencons_irq)
  12.102 -		unbind_evtchn_from_irqhandler(xencons_irq, inring());
  12.103 +		unbind_evtchn_from_irqhandler(xencons_irq, NULL);
  12.104  	xencons_irq = 0;
  12.105  
  12.106  	if (!xen_start_info->console_evtchn)
  12.107 @@ -104,7 +83,7 @@ int xencons_ring_init(void)
  12.108  
  12.109  	err = bind_evtchn_to_irqhandler(
  12.110  		xen_start_info->console_evtchn,
  12.111 -		handle_input, 0, "xencons", inring());
  12.112 +		handle_input, 0, "xencons", NULL);
  12.113  	if (err <= 0) {
  12.114  		xprintk("XEN console request irq failed %i\n", err);
  12.115  		return err;
    13.1 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Tue Oct 11 15:50:21 2005 -0600
    13.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c	Tue Oct 11 16:57:44 2005 -0600
    13.3 @@ -69,15 +69,15 @@ static void frontend_changed(struct xenb
    13.4  	int i;
    13.5  
    13.6  	/* If other end is gone, delete ourself. */
    13.7 -	if (vec && !xenbus_exists(be->frontpath, "")) {
    13.8 -		xenbus_rm(be->dev->nodename, "");
    13.9 +	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
   13.10 +		xenbus_rm(NULL, be->dev->nodename, "");
   13.11  		device_unregister(&be->dev->dev);
   13.12  		return;
   13.13  	}
   13.14  	if (be->netif == NULL || be->netif->status == CONNECTED)
   13.15  		return;
   13.16  
   13.17 -	mac = xenbus_read(be->frontpath, "mac", NULL);
   13.18 +	mac = xenbus_read(NULL, be->frontpath, "mac", NULL);
   13.19  	if (IS_ERR(mac)) {
   13.20  		err = PTR_ERR(mac);
   13.21  		xenbus_dev_error(be->dev, err, "reading %s/mac",
   13.22 @@ -98,7 +98,8 @@ static void frontend_changed(struct xenb
   13.23  	}
   13.24  	kfree(mac);
   13.25  
   13.26 -	err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref,
   13.27 +	err = xenbus_gather(NULL, be->frontpath,
   13.28 +			    "tx-ring-ref", "%lu", &tx_ring_ref,
   13.29  			    "rx-ring-ref", "%lu", &rx_ring_ref,
   13.30  			    "event-channel", "%u", &evtchn, NULL);
   13.31  	if (err) {
   13.32 @@ -137,7 +138,7 @@ static void backend_changed(struct xenbu
   13.33  	struct xenbus_device *dev = be->dev;
   13.34  	u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
   13.35  
   13.36 -	err = xenbus_scanf(dev->nodename, "handle", "%li", &handle);
   13.37 +	err = xenbus_scanf(NULL, dev->nodename, "handle", "%li", &handle);
   13.38  	if (XENBUS_EXIST_ERR(err))
   13.39  		return;
   13.40  	if (err < 0) {
   13.41 @@ -188,7 +189,7 @@ static int netback_hotplug(struct xenbus
   13.42  
   13.43  	key = env_vars;
   13.44  	while (*key != NULL) {
   13.45 -		val = xenbus_read(xdev->nodename, *key, NULL);
   13.46 +		val = xenbus_read(NULL, xdev->nodename, *key, NULL);
   13.47  		if (!IS_ERR(val)) {
   13.48  			char buf[strlen(*key) + 4];
   13.49  			sprintf(buf, "%s=%%s", *key);
   13.50 @@ -220,7 +221,7 @@ static int netback_probe(struct xenbus_d
   13.51  	memset(be, 0, sizeof(*be));
   13.52  
   13.53  	frontend = NULL;
   13.54 -	err = xenbus_gather(dev->nodename,
   13.55 +	err = xenbus_gather(NULL, dev->nodename,
   13.56  			    "frontend-id", "%li", &be->frontend_id,
   13.57  			    "frontend", NULL, &frontend,
   13.58  			    NULL);
   13.59 @@ -232,7 +233,7 @@ static int netback_probe(struct xenbus_d
   13.60  				 dev->nodename);
   13.61  		goto free_be;
   13.62  	}
   13.63 -	if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
   13.64 +	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
   13.65  		/* If we can't get a frontend path and a frontend-id,
   13.66  		 * then our bus-id is no longer valid and we need to
   13.67  		 * destroy the backend device.
    14.1 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Tue Oct 11 15:50:21 2005 -0600
    14.2 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c	Tue Oct 11 16:57:44 2005 -0600
    14.3 @@ -1083,10 +1083,11 @@ static int talk_to_backend(struct xenbus
    14.4  {
    14.5  	char *backend, *mac, *e, *s;
    14.6  	const char *message;
    14.7 +	struct xenbus_transaction *xbt;
    14.8  	int err, i;
    14.9  
   14.10  	backend = NULL;
   14.11 -	err = xenbus_gather(dev->nodename,
   14.12 +	err = xenbus_gather(NULL, dev->nodename,
   14.13  			    "backend-id", "%i", &info->backend_id,
   14.14  			    "backend", NULL, &backend,
   14.15  			    NULL);
   14.16 @@ -1102,7 +1103,7 @@ static int talk_to_backend(struct xenbus
   14.17  		goto out;
   14.18  	}
   14.19  
   14.20 -	mac = xenbus_read(dev->nodename, "mac", NULL);
   14.21 +	mac = xenbus_read(NULL, dev->nodename, "mac", NULL);
   14.22  	if (IS_ERR(mac)) {
   14.23  		err = PTR_ERR(mac);
   14.24  		xenbus_dev_error(dev, err, "reading %s/mac",
   14.25 @@ -1131,32 +1132,32 @@ static int talk_to_backend(struct xenbus
   14.26  	}
   14.27  
   14.28  again:
   14.29 -	err = xenbus_transaction_start();
   14.30 -	if (err) {
   14.31 +	xbt = xenbus_transaction_start();
   14.32 +	if (IS_ERR(xbt)) {
   14.33  		xenbus_dev_error(dev, err, "starting transaction");
   14.34  		goto destroy_ring;
   14.35  	}
   14.36  
   14.37 -	err = xenbus_printf(dev->nodename, "tx-ring-ref","%u",
   14.38 +	err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u",
   14.39  			    info->tx_ring_ref);
   14.40  	if (err) {
   14.41  		message = "writing tx ring-ref";
   14.42  		goto abort_transaction;
   14.43  	}
   14.44 -	err = xenbus_printf(dev->nodename, "rx-ring-ref","%u",
   14.45 +	err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u",
   14.46  			    info->rx_ring_ref);
   14.47  	if (err) {
   14.48  		message = "writing rx ring-ref";
   14.49  		goto abort_transaction;
   14.50  	}
   14.51 -	err = xenbus_printf(dev->nodename,
   14.52 +	err = xenbus_printf(xbt, dev->nodename,
   14.53  			    "event-channel", "%u", info->evtchn);
   14.54  	if (err) {
   14.55  		message = "writing event-channel";
   14.56  		goto abort_transaction;
   14.57  	}
   14.58  
   14.59 -	err = xenbus_transaction_end(0);
   14.60 +	err = xenbus_transaction_end(xbt, 0);
   14.61  	if (err) {
   14.62  		if (err == -EAGAIN)
   14.63  			goto again;
   14.64 @@ -1177,8 +1178,7 @@ again:
   14.65  	return 0;
   14.66  
   14.67   abort_transaction:
   14.68 -	xenbus_transaction_end(1);
   14.69 -	/* Have to do this *outside* transaction.  */
   14.70 +	xenbus_transaction_end(xbt, 1);
   14.71  	xenbus_dev_error(dev, err, "%s", message);
   14.72   destroy_ring:
   14.73  	shutdown_device(info);
   14.74 @@ -1201,7 +1201,7 @@ static int netfront_probe(struct xenbus_
   14.75  	struct netfront_info *info;
   14.76  	unsigned int handle;
   14.77  
   14.78 -	err = xenbus_scanf(dev->nodename, "handle", "%u", &handle);
   14.79 +	err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle);
   14.80  	if (XENBUS_EXIST_ERR(err))
   14.81  		return err;
   14.82  	if (err < 0) {
    15.1 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Tue Oct 11 15:50:21 2005 -0600
    15.2 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Tue Oct 11 16:57:44 2005 -0600
    15.3 @@ -246,7 +246,10 @@ static int privcmd_ioctl(struct inode *i
    15.4  				   PAGE_SHIFT);
    15.5  		ret = xen_start_info->store_mfn;
    15.6  
    15.7 -		/* We'll return then this will wait for daemon to answer */
    15.8 +		/* 
    15.9 +		** Complete initialization of xenbus (viz. set up the 
   15.10 +		** connection to xenstored now that it has started). 
   15.11 +		*/
   15.12  		kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
   15.13  	}
   15.14  	break;
    16.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Tue Oct 11 15:50:21 2005 -0600
    16.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c	Tue Oct 11 16:57:44 2005 -0600
    16.3 @@ -66,12 +66,13 @@ static void frontend_changed(struct xenb
    16.4  	unsigned int evtchn;
    16.5  	unsigned long ready = 1;
    16.6  	int err;
    16.7 +	struct xenbus_transaction *xbt;
    16.8  	struct backend_info *be
    16.9  		= container_of(watch, struct backend_info, watch);
   16.10  
   16.11  	/* If other end is gone, delete ourself. */
   16.12 -	if (vec && !xenbus_exists(be->frontpath, "")) {
   16.13 -		xenbus_rm(be->dev->nodename, "");
   16.14 +	if (vec && !xenbus_exists(NULL, be->frontpath, "")) {
   16.15 +		xenbus_rm(NULL, be->dev->nodename, "");
   16.16  		device_unregister(&be->dev->dev);
   16.17  		return;
   16.18  	}
   16.19 @@ -79,7 +80,7 @@ static void frontend_changed(struct xenb
   16.20  	if (be->tpmif == NULL || be->tpmif->status == CONNECTED)
   16.21  		return;
   16.22  
   16.23 -	err = xenbus_gather(be->frontpath,
   16.24 +	err = xenbus_gather(NULL, be->frontpath,
   16.25  	                    "ring-ref", "%lu", &ringref,
   16.26  			    "event-channel", "%u", &evtchn, NULL);
   16.27  	if (err) {
   16.28 @@ -115,20 +116,20 @@ static void frontend_changed(struct xenb
   16.29  	 * unless something bad happens
   16.30  	 */
   16.31  again:
   16.32 -	err = xenbus_transaction_start();
   16.33 -	if (err) {
   16.34 +	xbt = xenbus_transaction_start();
   16.35 +	if (IS_ERR(xbt)) {
   16.36  		xenbus_dev_error(be->dev, err, "starting transaction");
   16.37  		return;
   16.38  	}
   16.39  
   16.40 -	err = xenbus_printf(be->dev->nodename,
   16.41 +	err = xenbus_printf(xbt, be->dev->nodename,
   16.42  	                    "ready", "%lu", ready);
   16.43  	if (err) {
   16.44  		xenbus_dev_error(be->dev, err, "writing 'ready'");
   16.45  		goto abort;
   16.46  	}
   16.47  
   16.48 -	err = xenbus_transaction_end(0);
   16.49 +	err = xenbus_transaction_end(xbt, 0);
   16.50  	if (err == -EAGAIN)
   16.51  		goto again;
   16.52  	if (err) {
   16.53 @@ -139,7 +140,7 @@ again:
   16.54  	xenbus_dev_ok(be->dev);
   16.55  	return;
   16.56  abort:
   16.57 -	xenbus_transaction_end(1);
   16.58 +	xenbus_transaction_end(xbt, 1);
   16.59  }
   16.60  
   16.61  
   16.62 @@ -152,7 +153,7 @@ static void backend_changed(struct xenbu
   16.63  		= container_of(watch, struct backend_info, backend_watch);
   16.64  	struct xenbus_device *dev = be->dev;
   16.65  
   16.66 -	err = xenbus_scanf(dev->nodename, "instance", "%li", &instance);
   16.67 +	err = xenbus_scanf(NULL, dev->nodename, "instance", "%li", &instance);
   16.68  	if (XENBUS_EXIST_ERR(err))
   16.69  		return;
   16.70  	if (err < 0) {
   16.71 @@ -205,7 +206,7 @@ static int tpmback_probe(struct xenbus_d
   16.72  	memset(be, 0, sizeof(*be));
   16.73  
   16.74  	frontend = NULL;
   16.75 -	err = xenbus_gather(dev->nodename,
   16.76 +	err = xenbus_gather(NULL, dev->nodename,
   16.77  			    "frontend-id", "%li", &be->frontend_id,
   16.78  			    "frontend", NULL, &frontend,
   16.79  			    NULL);
   16.80 @@ -217,7 +218,7 @@ static int tpmback_probe(struct xenbus_d
   16.81  				 dev->nodename);
   16.82  		goto free_be;
   16.83  	}
   16.84 -	if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) {
   16.85 +	if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) {
   16.86  		/* If we can't get a frontend path and a frontend-id,
   16.87  		 * then our bus-id is no longer valid and we need to
   16.88  		 * destroy the backend device.
    17.1 --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c	Tue Oct 11 15:50:21 2005 -0600
    17.2 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c	Tue Oct 11 16:57:44 2005 -0600
    17.3 @@ -226,7 +226,7 @@ static void watch_for_status(struct xenb
    17.4  	if (tp->connected)
    17.5  		return;
    17.6  
    17.7 -	err = xenbus_gather(watch->node,
    17.8 +	err = xenbus_gather(NULL, watch->node,
    17.9  	                    "ready", "%lu", &ready,
   17.10  	                    NULL);
   17.11  	if (err) {
   17.12 @@ -311,9 +311,10 @@ static int talk_to_backend(struct xenbus
   17.13  	const char *message;
   17.14  	int err;
   17.15  	int backend_id;
   17.16 +	struct xenbus_transaction *xbt;
   17.17  
   17.18  	backend = NULL;
   17.19 -	err = xenbus_gather(dev->nodename,
   17.20 +	err = xenbus_gather(NULL, dev->nodename,
   17.21  			    "backend-id", "%i", &backend_id,
   17.22  			    "backend", NULL, &backend,
   17.23  			    NULL);
   17.24 @@ -339,27 +340,27 @@ static int talk_to_backend(struct xenbus
   17.25  	}
   17.26  
   17.27  again:
   17.28 -	err = xenbus_transaction_start();
   17.29 -	if (err) {
   17.30 +	xbt = xenbus_transaction_start();
   17.31 +	if (IS_ERR(xbt)) {
   17.32  		xenbus_dev_error(dev, err, "starting transaction");
   17.33  		goto destroy_tpmring;
   17.34  	}
   17.35  
   17.36 -	err = xenbus_printf(dev->nodename,
   17.37 +	err = xenbus_printf(xbt, dev->nodename,
   17.38  	                    "ring-ref","%u", info->ring_ref);
   17.39  	if (err) {
   17.40  		message = "writing ring-ref";
   17.41  		goto abort_transaction;
   17.42  	}
   17.43  
   17.44 -	err = xenbus_printf(dev->nodename,
   17.45 +	err = xenbus_printf(xbt, dev->nodename,
   17.46  			    "event-channel", "%u", my_private.evtchn);
   17.47  	if (err) {
   17.48  		message = "writing event-channel";
   17.49  		goto abort_transaction;
   17.50  	}
   17.51  
   17.52 -	err = xenbus_transaction_end(0);
   17.53 +	err = xenbus_transaction_end(xbt, 0);
   17.54  	if (err == -EAGAIN)
   17.55  		goto again;
   17.56  	if (err) {
   17.57 @@ -380,8 +381,7 @@ again:
   17.58  	return 0;
   17.59  
   17.60  abort_transaction:
   17.61 -	xenbus_transaction_end(1);
   17.62 -	/* Have to do this *outside* transaction.  */
   17.63 +	xenbus_transaction_end(xbt, 1);
   17.64  	xenbus_dev_error(dev, err, "%s", message);
   17.65  destroy_tpmring:
   17.66  	destroy_tpmring(info, &my_private);
   17.67 @@ -399,7 +399,7 @@ static int tpmfront_probe(struct xenbus_
   17.68  	struct tpmfront_info *info;
   17.69  	int handle;
   17.70  
   17.71 -	err = xenbus_scanf(dev->nodename,
   17.72 +	err = xenbus_scanf(NULL, dev->nodename,
   17.73  	                   "handle", "%i", &handle);
   17.74  	if (XENBUS_EXIST_ERR(err))
   17.75  		return err;
    18.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Tue Oct 11 15:50:21 2005 -0600
    18.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c	Tue Oct 11 16:57:44 2005 -0600
    18.3 @@ -128,19 +128,16 @@ int xb_write(const void *data, unsigned 
    18.4  		void *dst;
    18.5  		unsigned int avail;
    18.6  
    18.7 -		wait_event(xb_waitq, output_avail(out));
    18.8 +		wait_event_interruptible(xb_waitq, output_avail(out));
    18.9  
   18.10 -		/* Read, then check: not that we don't trust store.
   18.11 -		 * Hell, some of my best friends are daemons.  But,
   18.12 -		 * in this post-911 world... */
   18.13 +		mb();
   18.14  		h = *out;
   18.15 -		mb();
   18.16 -		if (!check_buffer(&h)) {
   18.17 -			set_current_state(TASK_RUNNING);
   18.18 -			return -EIO; /* ETERRORIST! */
   18.19 -		}
   18.20 +		if (!check_buffer(&h))
   18.21 +			return -EIO;
   18.22  
   18.23  		dst = get_output_chunk(&h, out->buf, &avail);
   18.24 +		if (avail == 0)
   18.25 +			continue;
   18.26  		if (avail > len)
   18.27  			avail = len;
   18.28  		memcpy(dst, data, avail);
   18.29 @@ -172,15 +169,16 @@ int xb_read(void *data, unsigned len)
   18.30  		unsigned int avail;
   18.31  		const char *src;
   18.32  
   18.33 -		wait_event(xb_waitq, xs_input_avail());
   18.34 -		h = *in;
   18.35 +		wait_event_interruptible(xb_waitq, xs_input_avail());
   18.36 +
   18.37  		mb();
   18.38 -		if (!check_buffer(&h)) {
   18.39 -			set_current_state(TASK_RUNNING);
   18.40 +		h = *in;
   18.41 +		if (!check_buffer(&h))
   18.42  			return -EIO;
   18.43 -		}
   18.44  
   18.45  		src = get_input_chunk(&h, in->buf, &avail);
   18.46 +		if (avail == 0)
   18.47 +			continue;
   18.48  		if (avail > len)
   18.49  			avail = len;
   18.50  		was_full = !output_avail(&h);
   18.51 @@ -195,10 +193,6 @@ int xb_read(void *data, unsigned len)
   18.52  			notify_remote_via_evtchn(xen_start_info->store_evtchn);
   18.53  	}
   18.54  
   18.55 -	/* If we left something, wake watch thread to deal with it. */
   18.56 -	if (xs_input_avail())
   18.57 -		wake_up(&xb_waitq);
   18.58 -
   18.59  	return 0;
   18.60  }
   18.61  
    19.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Tue Oct 11 15:50:21 2005 -0600
    19.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c	Tue Oct 11 16:57:44 2005 -0600
    19.3 @@ -45,86 +45,132 @@
    19.4  #include <asm-xen/xen_proc.h>
    19.5  #include <asm/hypervisor.h>
    19.6  
    19.7 +struct xenbus_dev_transaction {
    19.8 +	struct list_head list;
    19.9 +	struct xenbus_transaction *handle;
   19.10 +};
   19.11 +
   19.12  struct xenbus_dev_data {
   19.13 -	/* Are there bytes left to be read in this message? */
   19.14 -	int bytes_left;
   19.15 -	/* Are we still waiting for the reply to a message we wrote? */
   19.16 -	int awaiting_reply;
   19.17 -	/* Buffer for outgoing messages. */
   19.18 +	/* In-progress transaction. */
   19.19 +	struct list_head transactions;
   19.20 +
   19.21 +	/* Partial request. */
   19.22  	unsigned int len;
   19.23  	union {
   19.24  		struct xsd_sockmsg msg;
   19.25  		char buffer[PAGE_SIZE];
   19.26  	} u;
   19.27 +
   19.28 +	/* Response queue. */
   19.29 +#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
   19.30 +	char read_buffer[PAGE_SIZE];
   19.31 +	unsigned int read_cons, read_prod;
   19.32 +	wait_queue_head_t read_waitq;
   19.33  };
   19.34  
   19.35  static struct proc_dir_entry *xenbus_dev_intf;
   19.36  
   19.37 -/* Reply can be long (dir, getperm): don't buffer, just examine
   19.38 - * headers so we can discard rest if they die. */
   19.39  static ssize_t xenbus_dev_read(struct file *filp,
   19.40  			       char __user *ubuf,
   19.41  			       size_t len, loff_t *ppos)
   19.42  {
   19.43 -	struct xenbus_dev_data *data = filp->private_data;
   19.44 -	struct xsd_sockmsg msg;
   19.45 -	int err;
   19.46 -
   19.47 -	/* Refill empty buffer? */
   19.48 -	if (data->bytes_left == 0) {
   19.49 -		if (len < sizeof(msg))
   19.50 -			return -EINVAL;
   19.51 +	struct xenbus_dev_data *u = filp->private_data;
   19.52 +	int i;
   19.53  
   19.54 -		err = xb_read(&msg, sizeof(msg));
   19.55 -		if (err)
   19.56 -			return err;
   19.57 -		data->bytes_left = msg.len;
   19.58 -		if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0)
   19.59 -			return -EFAULT;
   19.60 -		/* We can receive spurious XS_WATCH_EVENT messages. */
   19.61 -		if (msg.type != XS_WATCH_EVENT)
   19.62 -			data->awaiting_reply = 0;
   19.63 -		return sizeof(msg);
   19.64 +	if (wait_event_interruptible(u->read_waitq,
   19.65 +				     u->read_prod != u->read_cons))
   19.66 +		return -EINTR;
   19.67 +
   19.68 +	for (i = 0; i < len; i++) {
   19.69 +		if (u->read_cons == u->read_prod)
   19.70 +			break;
   19.71 +		put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i);
   19.72 +		u->read_cons++;
   19.73  	}
   19.74  
   19.75 -	/* Don't read over next header, or over temporary buffer. */
   19.76 -	if (len > sizeof(data->u.buffer))
   19.77 -		len = sizeof(data->u.buffer);
   19.78 -	if (len > data->bytes_left)
   19.79 -		len = data->bytes_left;
   19.80 -
   19.81 -	err = xb_read(data->u.buffer, len);
   19.82 -	if (err)
   19.83 -		return err;
   19.84 -
   19.85 -	data->bytes_left -= len;
   19.86 -	if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0)
   19.87 -		return -EFAULT;
   19.88 -	return len;
   19.89 +	return i;
   19.90  }
   19.91  
   19.92 -/* We do v. basic sanity checking so they don't screw up kernel later. */
   19.93 +static void queue_reply(struct xenbus_dev_data *u,
   19.94 +			char *data, unsigned int len)
   19.95 +{
   19.96 +	int i;
   19.97 +
   19.98 +	for (i = 0; i < len; i++, u->read_prod++)
   19.99 +		u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
  19.100 +
  19.101 +	BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
  19.102 +
  19.103 +	wake_up(&u->read_waitq);
  19.104 +}
  19.105 +
  19.106  static ssize_t xenbus_dev_write(struct file *filp,
  19.107  				const char __user *ubuf,
  19.108  				size_t len, loff_t *ppos)
  19.109  {
  19.110 -	struct xenbus_dev_data *data = filp->private_data;
  19.111 -	int err;
  19.112 +	struct xenbus_dev_data *u = filp->private_data;
  19.113 +	struct xenbus_dev_transaction *trans;
  19.114 +	void *reply;
  19.115 +	int err = 0;
  19.116  
  19.117 -	/* We gather data in buffer until we're ready to send it. */
  19.118 -	if (len > data->len + sizeof(data->u))
  19.119 +	if ((len + u->len) > sizeof(u->u.buffer))
  19.120  		return -EINVAL;
  19.121 -	if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0)
  19.122 +
  19.123 +	if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0)
  19.124  		return -EFAULT;
  19.125 -	data->len += len;
  19.126 -	if (data->len >= sizeof(data->u.msg) + data->u.msg.len) {
  19.127 -		err = xb_write(data->u.buffer, data->len);
  19.128 -		if (err)
  19.129 -			return err;
  19.130 -		data->len = 0;
  19.131 -		data->awaiting_reply = 1;
  19.132 +
  19.133 +	u->len += len;
  19.134 +	if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
  19.135 +		return len;
  19.136 +
  19.137 +	switch (u->u.msg.type) {
  19.138 +	case XS_TRANSACTION_START:
  19.139 +	case XS_TRANSACTION_END:
  19.140 +	case XS_DIRECTORY:
  19.141 +	case XS_READ:
  19.142 +	case XS_GET_PERMS:
  19.143 +	case XS_RELEASE:
  19.144 +	case XS_GET_DOMAIN_PATH:
  19.145 +	case XS_WRITE:
  19.146 +	case XS_MKDIR:
  19.147 +	case XS_RM:
  19.148 +	case XS_SET_PERMS:
  19.149 +		reply = xenbus_dev_request_and_reply(&u->u.msg);
  19.150 +		if (IS_ERR(reply)) {
  19.151 +			err = PTR_ERR(reply);
  19.152 +		} else {
  19.153 +			if (u->u.msg.type == XS_TRANSACTION_START) {
  19.154 +				trans = kmalloc(sizeof(*trans), GFP_KERNEL);
  19.155 +				trans->handle = (struct xenbus_transaction *)
  19.156 +					simple_strtoul(reply, NULL, 0);
  19.157 +				list_add(&trans->list, &u->transactions);
  19.158 +			} else if (u->u.msg.type == XS_TRANSACTION_END) {
  19.159 +				list_for_each_entry(trans, &u->transactions,
  19.160 +						    list)
  19.161 +					if ((unsigned long)trans->handle ==
  19.162 +					    (unsigned long)u->u.msg.tx_id)
  19.163 +						break;
  19.164 +				BUG_ON(&trans->list == &u->transactions);
  19.165 +				list_del(&trans->list);
  19.166 +				kfree(trans);
  19.167 +			}
  19.168 +			queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
  19.169 +			queue_reply(u, (char *)reply, u->u.msg.len);
  19.170 +			kfree(reply);
  19.171 +		}
  19.172 +		break;
  19.173 +
  19.174 +	default:
  19.175 +		err = -EINVAL;
  19.176 +		break;
  19.177  	}
  19.178 -	return len;
  19.179 +
  19.180 +	if (err == 0) {
  19.181 +		u->len = 0;
  19.182 +		err = len;
  19.183 +	}
  19.184 +
  19.185 +	return err;
  19.186  }
  19.187  
  19.188  static int xenbus_dev_open(struct inode *inode, struct file *filp)
  19.189 @@ -134,7 +180,6 @@ static int xenbus_dev_open(struct inode 
  19.190  	if (xen_start_info->store_evtchn == 0)
  19.191  		return -ENOENT;
  19.192  
  19.193 -	/* Don't try seeking. */
  19.194  	nonseekable_open(inode, filp);
  19.195  
  19.196  	u = kmalloc(sizeof(*u), GFP_KERNEL);
  19.197 @@ -142,28 +187,26 @@ static int xenbus_dev_open(struct inode 
  19.198  		return -ENOMEM;
  19.199  
  19.200  	memset(u, 0, sizeof(*u));
  19.201 +	INIT_LIST_HEAD(&u->transactions);
  19.202 +	init_waitqueue_head(&u->read_waitq);
  19.203  
  19.204  	filp->private_data = u;
  19.205  
  19.206 -	down(&xenbus_lock);
  19.207 -
  19.208  	return 0;
  19.209  }
  19.210  
  19.211  static int xenbus_dev_release(struct inode *inode, struct file *filp)
  19.212  {
  19.213 -	struct xenbus_dev_data *data = filp->private_data;
  19.214 -
  19.215 -	/* Discard any unread replies. */
  19.216 -	while (data->bytes_left || data->awaiting_reply)
  19.217 -		xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL);
  19.218 +	struct xenbus_dev_data *u = filp->private_data;
  19.219 +	struct xenbus_dev_transaction *trans, *tmp;
  19.220  
  19.221 -	/* Harmless if no transaction in progress. */
  19.222 -	xenbus_transaction_end(1);
  19.223 +	list_for_each_entry_safe(trans, tmp, &u->transactions, list) {
  19.224 +		xenbus_transaction_end(trans->handle, 1);
  19.225 +		list_del(&trans->list);
  19.226 +		kfree(trans);
  19.227 +	}
  19.228  
  19.229 -	up(&xenbus_lock);
  19.230 -
  19.231 -	kfree(data);
  19.232 +	kfree(u);
  19.233  
  19.234  	return 0;
  19.235  }
    20.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Tue Oct 11 15:50:21 2005 -0600
    20.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c	Tue Oct 11 16:57:44 2005 -0600
    20.3 @@ -125,7 +125,7 @@ static int backend_bus_id(char bus_id[BU
    20.4  
    20.5  	devid = strrchr(nodename, '/') + 1;
    20.6  
    20.7 -	err = xenbus_gather(nodename, "frontend-id", "%i", &domid,
    20.8 +	err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
    20.9  			    "frontend", NULL, &frontend,
   20.10  			    NULL);
   20.11  	if (err)
   20.12 @@ -133,7 +133,7 @@ static int backend_bus_id(char bus_id[BU
   20.13  	if (strlen(frontend) == 0)
   20.14  		err = -ERANGE;
   20.15  
   20.16 -	if (!err && !xenbus_exists(frontend, ""))
   20.17 +	if (!err && !xenbus_exists(NULL, frontend, ""))
   20.18  		err = -ENOENT;
   20.19  
   20.20  	if (err) {
   20.21 @@ -229,18 +229,13 @@ static int xenbus_dev_remove(struct devi
   20.22  static int xenbus_register_driver_common(struct xenbus_driver *drv,
   20.23  					 struct xen_bus_type *bus)
   20.24  {
   20.25 -	int err;
   20.26 -
   20.27  	drv->driver.name = drv->name;
   20.28  	drv->driver.bus = &bus->bus;
   20.29  	drv->driver.owner = drv->owner;
   20.30  	drv->driver.probe = xenbus_dev_probe;
   20.31  	drv->driver.remove = xenbus_dev_remove;
   20.32  
   20.33 -	down(&xenbus_lock);
   20.34 -	err = driver_register(&drv->driver);
   20.35 -	up(&xenbus_lock);
   20.36 -	return err;
   20.37 +	return driver_register(&drv->driver);
   20.38  }
   20.39  
   20.40  int xenbus_register_driver(struct xenbus_driver *drv)
   20.41 @@ -256,9 +251,7 @@ int xenbus_register_backend(struct xenbu
   20.42  
   20.43  void xenbus_unregister_driver(struct xenbus_driver *drv)
   20.44  {
   20.45 -	down(&xenbus_lock);
   20.46  	driver_unregister(&drv->driver);
   20.47 -	up(&xenbus_lock);
   20.48  }
   20.49  EXPORT_SYMBOL(xenbus_unregister_driver);
   20.50  
   20.51 @@ -447,7 +440,7 @@ static int xenbus_probe_backend(const ch
   20.52  	if (!nodename)
   20.53  		return -ENOMEM;
   20.54  
   20.55 -	dir = xenbus_directory(nodename, "", &dir_n);
   20.56 +	dir = xenbus_directory(NULL, nodename, "", &dir_n);
   20.57  	if (IS_ERR(dir)) {
   20.58  		kfree(nodename);
   20.59  		return PTR_ERR(dir);
   20.60 @@ -470,7 +463,7 @@ static int xenbus_probe_device_type(stru
   20.61  	unsigned int dir_n = 0;
   20.62  	int i;
   20.63  
   20.64 -	dir = xenbus_directory(bus->root, type, &dir_n);
   20.65 +	dir = xenbus_directory(NULL, bus->root, type, &dir_n);
   20.66  	if (IS_ERR(dir))
   20.67  		return PTR_ERR(dir);
   20.68  
   20.69 @@ -489,7 +482,7 @@ static int xenbus_probe_devices(struct x
   20.70  	char **dir;
   20.71  	unsigned int i, dir_n;
   20.72  
   20.73 -	dir = xenbus_directory(bus->root, "", &dir_n);
   20.74 +	dir = xenbus_directory(NULL, bus->root, "", &dir_n);
   20.75  	if (IS_ERR(dir))
   20.76  		return PTR_ERR(dir);
   20.77  
   20.78 @@ -535,7 +528,7 @@ static void dev_changed(const char *node
   20.79  	if (char_count(node, '/') < 2)
   20.80   		return;
   20.81  
   20.82 -	exists = xenbus_exists(node, "");
   20.83 +	exists = xenbus_exists(NULL, node, "");
   20.84  	if (!exists) {
   20.85  		xenbus_cleanup_devices(node, &bus->bus);
   20.86  		return;
   20.87 @@ -621,53 +614,49 @@ static int resume_dev(struct device *dev
   20.88  
   20.89  void xenbus_suspend(void)
   20.90  {
   20.91 -	/* We keep lock, so no comms can happen as page moves. */
   20.92 -	down(&xenbus_lock);
   20.93  	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
   20.94  	bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
   20.95 +	xs_suspend();
   20.96  }
   20.97  
   20.98  void xenbus_resume(void)
   20.99  {
  20.100  	xb_init_comms();
  20.101 -	reregister_xenbus_watches();
  20.102 +	xs_resume();
  20.103  	bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
  20.104  	bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
  20.105 -	up(&xenbus_lock);
  20.106  }
  20.107  
  20.108  int register_xenstore_notifier(struct notifier_block *nb)
  20.109  {
  20.110  	int ret = 0;
  20.111  
  20.112 -	down(&xenbus_lock);
  20.113 -
  20.114  	if (xen_start_info->store_evtchn) {
  20.115  		ret = nb->notifier_call(nb, 0, NULL);
  20.116  	} else {
  20.117  		notifier_chain_register(&xenstore_chain, nb);
  20.118  	}
  20.119  
  20.120 -	up(&xenbus_lock);
  20.121 -
  20.122  	return ret;
  20.123  }
  20.124  EXPORT_SYMBOL(register_xenstore_notifier);
  20.125  
  20.126  void unregister_xenstore_notifier(struct notifier_block *nb)
  20.127  {
  20.128 -	down(&xenbus_lock);
  20.129  	notifier_chain_unregister(&xenstore_chain, nb);
  20.130 -	up(&xenbus_lock);
  20.131  }
  20.132  EXPORT_SYMBOL(unregister_xenstore_notifier);
  20.133  
  20.134 -/* called from a thread in privcmd/privcmd.c */
  20.135 +/* 
  20.136 +** Called either from below xenbus_probe_init() initcall (for domUs) 
  20.137 +** or, for dom0, from a thread created in privcmd/privcmd.c (after 
  20.138 +** the user-space tools have invoked initDomainStore()) 
  20.139 +*/
  20.140  int do_xenbus_probe(void *unused)
  20.141  {
  20.142  	int err = 0;
  20.143  
  20.144 -	/* Initialize xenstore comms unless already done. */
  20.145 +	/* Initialize the interface to xenstore. */
  20.146  	err = xs_init();
  20.147  	if (err) {
  20.148  		printk("XENBUS: Error initializing xenstore comms:"
  20.149 @@ -675,16 +664,17 @@ int do_xenbus_probe(void *unused)
  20.150  		return err;
  20.151  	}
  20.152  
  20.153 -	down(&xenbus_lock);
  20.154  	/* Enumerate devices in xenstore. */
  20.155  	xenbus_probe_devices(&xenbus_frontend);
  20.156  	xenbus_probe_devices(&xenbus_backend);
  20.157 +
  20.158  	/* Watch for changes. */
  20.159  	register_xenbus_watch(&fe_watch);
  20.160  	register_xenbus_watch(&be_watch);
  20.161 +
  20.162  	/* Notify others that xenstore is up */
  20.163  	notifier_call_chain(&xenstore_chain, 0, 0);
  20.164 -	up(&xenbus_lock);
  20.165 +
  20.166  	return 0;
  20.167  }
  20.168  
  20.169 @@ -698,6 +688,10 @@ static int __init xenbus_probe_init(void
  20.170  	device_register(&xenbus_frontend.dev);
  20.171  	device_register(&xenbus_backend.dev);
  20.172  
  20.173 +	/* 
  20.174 +	** Domain0 doesn't have a store_evtchn yet - this will
  20.175 +	** be set up later by xend invoking initDomainStore() 
  20.176 +	*/
  20.177  	if (!xen_start_info->store_evtchn)
  20.178  		return 0;
  20.179  
    21.1 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Tue Oct 11 15:50:21 2005 -0600
    21.2 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c	Tue Oct 11 16:57:44 2005 -0600
    21.3 @@ -42,11 +42,58 @@
    21.4  
    21.5  #define streq(a, b) (strcmp((a), (b)) == 0)
    21.6  
    21.7 -static char printf_buffer[4096];
    21.8 +struct xs_stored_msg {
    21.9 +	struct list_head list;
   21.10 +
   21.11 +	struct xsd_sockmsg hdr;
   21.12 +
   21.13 +	union {
   21.14 +		/* Queued replies. */
   21.15 +		struct {
   21.16 +			char *body;
   21.17 +		} reply;
   21.18 +
   21.19 +		/* Queued watch events. */
   21.20 +		struct {
   21.21 +			struct xenbus_watch *handle;
   21.22 +			char **vec;
   21.23 +			unsigned int vec_size;
   21.24 +		} watch;
   21.25 +	} u;
   21.26 +};
   21.27 +
   21.28 +struct xs_handle {
   21.29 +	/* A list of replies. Currently only one will ever be outstanding. */
   21.30 +	struct list_head reply_list;
   21.31 +	spinlock_t reply_lock;
   21.32 +	wait_queue_head_t reply_waitq;
   21.33 +
   21.34 +	/* One request at a time. */
   21.35 +	struct semaphore request_mutex;
   21.36 +
   21.37 +	/* Protect transactions against save/restore. */
   21.38 +	struct rw_semaphore suspend_mutex;
   21.39 +};
   21.40 +
   21.41 +static struct xs_handle xs_state;
   21.42 +
   21.43 +/* List of registered watches, and a lock to protect it. */
   21.44  static LIST_HEAD(watches);
   21.45 +static DEFINE_SPINLOCK(watches_lock);
   21.46  
   21.47 -DECLARE_MUTEX(xenbus_lock);
   21.48 -EXPORT_SYMBOL(xenbus_lock);
   21.49 +/* List of pending watch calbback events, and a lock to protect it. */
   21.50 +static LIST_HEAD(watch_events);
   21.51 +static DEFINE_SPINLOCK(watch_events_lock);
   21.52 +
   21.53 +/*
   21.54 + * Details of the xenwatch callback kernel thread. The thread waits on the
   21.55 + * watch_events_waitq for work to do (queued on watch_events list). When it
   21.56 + * wakes up it acquires the xenwatch_mutex before reading the list and
   21.57 + * carrying out work.
   21.58 + */
   21.59 +static pid_t xenwatch_pid;
   21.60 +static DECLARE_MUTEX(xenwatch_mutex);
   21.61 +static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);
   21.62  
   21.63  static int get_error(const char *errorstring)
   21.64  {
   21.65 @@ -65,47 +112,82 @@ static int get_error(const char *errorst
   21.66  
   21.67  static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
   21.68  {
   21.69 -	struct xsd_sockmsg msg;
   21.70 -	void *ret;
   21.71 -	int err;
   21.72 -
   21.73 -	err = xb_read(&msg, sizeof(msg));
   21.74 -	if (err)
   21.75 -		return ERR_PTR(err);
   21.76 +	struct xs_stored_msg *msg;
   21.77 +	char *body;
   21.78  
   21.79 -	ret = kmalloc(msg.len + 1, GFP_KERNEL);
   21.80 -	if (!ret)
   21.81 -		return ERR_PTR(-ENOMEM);
   21.82 +	spin_lock(&xs_state.reply_lock);
   21.83  
   21.84 -	err = xb_read(ret, msg.len);
   21.85 -	if (err) {
   21.86 -		kfree(ret);
   21.87 -		return ERR_PTR(err);
   21.88 +	while (list_empty(&xs_state.reply_list)) {
   21.89 +		spin_unlock(&xs_state.reply_lock);
   21.90 +		wait_event_interruptible(xs_state.reply_waitq,
   21.91 +					 !list_empty(&xs_state.reply_list));
   21.92 +		spin_lock(&xs_state.reply_lock);
   21.93  	}
   21.94 -	((char*)ret)[msg.len] = '\0';
   21.95  
   21.96 -	*type = msg.type;
   21.97 +	msg = list_entry(xs_state.reply_list.next,
   21.98 +			 struct xs_stored_msg, list);
   21.99 +	list_del(&msg->list);
  21.100 +
  21.101 +	spin_unlock(&xs_state.reply_lock);
  21.102 +
  21.103 +	*type = msg->hdr.type;
  21.104  	if (len)
  21.105 -		*len = msg.len;
  21.106 -	return ret;
  21.107 +		*len = msg->hdr.len;
  21.108 +	body = msg->u.reply.body;
  21.109 +
  21.110 +	kfree(msg);
  21.111 +
  21.112 +	return body;
  21.113  }
  21.114  
  21.115  /* Emergency write. */
  21.116  void xenbus_debug_write(const char *str, unsigned int count)
  21.117  {
  21.118 -	struct xsd_sockmsg msg;
  21.119 +	struct xsd_sockmsg msg = { 0 };
  21.120  
  21.121  	msg.type = XS_DEBUG;
  21.122  	msg.len = sizeof("print") + count + 1;
  21.123  
  21.124 +	down(&xs_state.request_mutex);
  21.125  	xb_write(&msg, sizeof(msg));
  21.126  	xb_write("print", sizeof("print"));
  21.127  	xb_write(str, count);
  21.128  	xb_write("", 1);
  21.129 +	up(&xs_state.request_mutex);
  21.130 +}
  21.131 +
  21.132 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
  21.133 +{
  21.134 +	void *ret;
  21.135 +	struct xsd_sockmsg req_msg = *msg;
  21.136 +	int err;
  21.137 +
  21.138 +	if (req_msg.type == XS_TRANSACTION_START)
  21.139 +		down_read(&xs_state.suspend_mutex);
  21.140 +
  21.141 +	down(&xs_state.request_mutex);
  21.142 +
  21.143 +	err = xb_write(msg, sizeof(*msg) + msg->len);
  21.144 +	if (err) {
  21.145 +		msg->type = XS_ERROR;
  21.146 +		ret = ERR_PTR(err);
  21.147 +	} else {
  21.148 +		ret = read_reply(&msg->type, &msg->len);
  21.149 +	}
  21.150 +
  21.151 +	up(&xs_state.request_mutex);
  21.152 +
  21.153 +	if ((msg->type == XS_TRANSACTION_END) ||
  21.154 +	    ((req_msg.type == XS_TRANSACTION_START) &&
  21.155 +	     (msg->type == XS_ERROR)))
  21.156 +		up_read(&xs_state.suspend_mutex);
  21.157 +
  21.158 +	return ret;
  21.159  }
  21.160  
  21.161  /* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
  21.162 -static void *xs_talkv(enum xsd_sockmsg_type type,
  21.163 +static void *xs_talkv(struct xenbus_transaction *t,
  21.164 +		      enum xsd_sockmsg_type type,
  21.165  		      const struct kvec *iovec,
  21.166  		      unsigned int num_vecs,
  21.167  		      unsigned int *len)
  21.168 @@ -115,31 +197,34 @@ static void *xs_talkv(enum xsd_sockmsg_t
  21.169  	unsigned int i;
  21.170  	int err;
  21.171  
  21.172 -	WARN_ON(down_trylock(&xenbus_lock) == 0);
  21.173 -
  21.174 +	msg.tx_id = (u32)(unsigned long)t;
  21.175  	msg.type = type;
  21.176  	msg.len = 0;
  21.177  	for (i = 0; i < num_vecs; i++)
  21.178  		msg.len += iovec[i].iov_len;
  21.179  
  21.180 +	down(&xs_state.request_mutex);
  21.181 +
  21.182  	err = xb_write(&msg, sizeof(msg));
  21.183 -	if (err)
  21.184 +	if (err) {
  21.185 +		up(&xs_state.request_mutex);
  21.186  		return ERR_PTR(err);
  21.187 +	}
  21.188  
  21.189  	for (i = 0; i < num_vecs; i++) {
  21.190  		err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
  21.191 -		if (err)
  21.192 +		if (err) {
  21.193 +			up(&xs_state.request_mutex);
  21.194  			return ERR_PTR(err);
  21.195 +		}
  21.196  	}
  21.197  
  21.198 -	/* Watches can have fired before reply comes: daemon detects
  21.199 -	 * and re-transmits, so we can ignore this. */
  21.200 -	do {
  21.201 -		kfree(ret);
  21.202 -		ret = read_reply(&msg.type, len);
  21.203 -		if (IS_ERR(ret))
  21.204 -			return ret;
  21.205 -	} while (msg.type == XS_WATCH_EVENT);
  21.206 +	ret = read_reply(&msg.type, len);
  21.207 +
  21.208 +	up(&xs_state.request_mutex);
  21.209 +
  21.210 +	if (IS_ERR(ret))
  21.211 +		return ret;
  21.212  
  21.213  	if (msg.type == XS_ERROR) {
  21.214  		err = get_error(ret);
  21.215 @@ -152,14 +237,16 @@ static void *xs_talkv(enum xsd_sockmsg_t
  21.216  }
  21.217  
  21.218  /* Simplified version of xs_talkv: single message. */
  21.219 -static void *xs_single(enum xsd_sockmsg_type type,
  21.220 -		       const char *string, unsigned int *len)
  21.221 +static void *xs_single(struct xenbus_transaction *t,
  21.222 +		       enum xsd_sockmsg_type type,
  21.223 +		       const char *string,
  21.224 +		       unsigned int *len)
  21.225  {
  21.226  	struct kvec iovec;
  21.227  
  21.228  	iovec.iov_base = (void *)string;
  21.229  	iovec.iov_len = strlen(string) + 1;
  21.230 -	return xs_talkv(type, &iovec, 1, len);
  21.231 +	return xs_talkv(t, type, &iovec, 1, len);
  21.232  }
  21.233  
  21.234  /* Many commands only need an ack, don't care what it says. */
  21.235 @@ -182,20 +269,22 @@ static unsigned int count_strings(const 
  21.236  	return num;
  21.237  }
  21.238  
  21.239 -/* Return the path to dir with /name appended. */ 
  21.240 +/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ 
  21.241  static char *join(const char *dir, const char *name)
  21.242  {
  21.243 -	static char buffer[4096];
  21.244 +	char *buffer;
  21.245  
  21.246 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
  21.247 -	/* XXX FIXME: might not be correct if name == "" */
  21.248 -	BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
  21.249 +	buffer = kmalloc(strlen(dir) + strlen("/") + strlen(name) + 1,
  21.250 +			 GFP_KERNEL);
  21.251 +	if (buffer == NULL)
  21.252 +		return ERR_PTR(-ENOMEM);
  21.253  
  21.254  	strcpy(buffer, dir);
  21.255  	if (!streq(name, "")) {
  21.256  		strcat(buffer, "/");
  21.257  		strcat(buffer, name);
  21.258  	}
  21.259 +
  21.260  	return buffer;
  21.261  }
  21.262  
  21.263 @@ -207,7 +296,7 @@ static char **split(char *strings, unsig
  21.264  	*num = count_strings(strings, len);
  21.265  
  21.266  	/* Transfer to one big alloc for easy freeing. */
  21.267 -	ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
  21.268 +	ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL);
  21.269  	if (!ret) {
  21.270  		kfree(strings);
  21.271  		return ERR_PTR(-ENOMEM);
  21.272 @@ -222,12 +311,18 @@ static char **split(char *strings, unsig
  21.273  	return ret;
  21.274  }
  21.275  
  21.276 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
  21.277 +char **xenbus_directory(struct xenbus_transaction *t,
  21.278 +			const char *dir, const char *node, unsigned int *num)
  21.279  {
  21.280 -	char *strings;
  21.281 +	char *strings, *path;
  21.282  	unsigned int len;
  21.283  
  21.284 -	strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
  21.285 +	path = join(dir, node);
  21.286 +	if (IS_ERR(path))
  21.287 +		return (char **)path;
  21.288 +
  21.289 +	strings = xs_single(t, XS_DIRECTORY, path, &len);
  21.290 +	kfree(path);
  21.291  	if (IS_ERR(strings))
  21.292  		return (char **)strings;
  21.293  
  21.294 @@ -236,12 +331,13 @@ char **xenbus_directory(const char *dir,
  21.295  EXPORT_SYMBOL(xenbus_directory);
  21.296  
  21.297  /* Check if a path exists. Return 1 if it does. */
  21.298 -int xenbus_exists(const char *dir, const char *node)
  21.299 +int xenbus_exists(struct xenbus_transaction *t,
  21.300 +		  const char *dir, const char *node)
  21.301  {
  21.302  	char **d;
  21.303  	int dir_n;
  21.304  
  21.305 -	d = xenbus_directory(dir, node, &dir_n);
  21.306 +	d = xenbus_directory(t, dir, node, &dir_n);
  21.307  	if (IS_ERR(d))
  21.308  		return 0;
  21.309  	kfree(d);
  21.310 @@ -253,78 +349,133 @@ EXPORT_SYMBOL(xenbus_exists);
  21.311   * Returns a kmalloced value: call free() on it after use.
  21.312   * len indicates length in bytes.
  21.313   */
  21.314 -void *xenbus_read(const char *dir, const char *node, unsigned int *len)
  21.315 +void *xenbus_read(struct xenbus_transaction *t,
  21.316 +		  const char *dir, const char *node, unsigned int *len)
  21.317  {
  21.318 -	return xs_single(XS_READ, join(dir, node), len);
  21.319 +	char *path;
  21.320 +	void *ret;
  21.321 +
  21.322 +	path = join(dir, node);
  21.323 +	if (IS_ERR(path))
  21.324 +		return (void *)path;
  21.325 +
  21.326 +	ret = xs_single(t, XS_READ, path, len);
  21.327 +	kfree(path);
  21.328 +	return ret;
  21.329  }
  21.330  EXPORT_SYMBOL(xenbus_read);
  21.331  
  21.332  /* Write the value of a single file.
  21.333   * Returns -err on failure.
  21.334   */
  21.335 -int xenbus_write(const char *dir, const char *node, const char *string)
  21.336 +int xenbus_write(struct xenbus_transaction *t,
  21.337 +		 const char *dir, const char *node, const char *string)
  21.338  {
  21.339  	const char *path;
  21.340  	struct kvec iovec[2];
  21.341 +	int ret;
  21.342  
  21.343  	path = join(dir, node);
  21.344 +	if (IS_ERR(path))
  21.345 +		return PTR_ERR(path);
  21.346  
  21.347  	iovec[0].iov_base = (void *)path;
  21.348  	iovec[0].iov_len = strlen(path) + 1;
  21.349  	iovec[1].iov_base = (void *)string;
  21.350  	iovec[1].iov_len = strlen(string);
  21.351  
  21.352 -	return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
  21.353 +	ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
  21.354 +	kfree(path);
  21.355 +	return ret;
  21.356  }
  21.357  EXPORT_SYMBOL(xenbus_write);
  21.358  
  21.359  /* Create a new directory. */
  21.360 -int xenbus_mkdir(const char *dir, const char *node)
  21.361 +int xenbus_mkdir(struct xenbus_transaction *t,
  21.362 +		 const char *dir, const char *node)
  21.363  {
  21.364 -	return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
  21.365 +	char *path;
  21.366 +	int ret;
  21.367 +
  21.368 +	path = join(dir, node);
  21.369 +	if (IS_ERR(path))
  21.370 +		return PTR_ERR(path);
  21.371 +
  21.372 +	ret = xs_error(xs_single(t, XS_MKDIR, path, NULL));
  21.373 +	kfree(path);
  21.374 +	return ret;
  21.375  }
  21.376  EXPORT_SYMBOL(xenbus_mkdir);
  21.377  
  21.378  /* Destroy a file or directory (directories must be empty). */
  21.379 -int xenbus_rm(const char *dir, const char *node)
  21.380 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
  21.381  {
  21.382 -	return xs_error(xs_single(XS_RM, join(dir, node), NULL));
  21.383 +	char *path;
  21.384 +	int ret;
  21.385 +
  21.386 +	path = join(dir, node);
  21.387 +	if (IS_ERR(path))
  21.388 +		return PTR_ERR(path);
  21.389 +
  21.390 +	ret = xs_error(xs_single(t, XS_RM, path, NULL));
  21.391 +	kfree(path);
  21.392 +	return ret;
  21.393  }
  21.394  EXPORT_SYMBOL(xenbus_rm);
  21.395  
  21.396  /* Start a transaction: changes by others will not be seen during this
  21.397   * transaction, and changes will not be visible to others until end.
  21.398 - * You can only have one transaction at any time.
  21.399   */
  21.400 -int xenbus_transaction_start(void)
  21.401 +struct xenbus_transaction *xenbus_transaction_start(void)
  21.402  {
  21.403 -	return xs_error(xs_single(XS_TRANSACTION_START, "", NULL));
  21.404 +	char *id_str;
  21.405 +	unsigned long id;
  21.406 +
  21.407 +	down_read(&xs_state.suspend_mutex);
  21.408 +
  21.409 +	id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL);
  21.410 +	if (IS_ERR(id_str)) {
  21.411 +		up_read(&xs_state.suspend_mutex);
  21.412 +		return (struct xenbus_transaction *)id_str;
  21.413 +	}
  21.414 +
  21.415 +	id = simple_strtoul(id_str, NULL, 0);
  21.416 +	kfree(id_str);
  21.417 +
  21.418 +	return (struct xenbus_transaction *)id;
  21.419  }
  21.420  EXPORT_SYMBOL(xenbus_transaction_start);
  21.421  
  21.422  /* End a transaction.
  21.423   * If abandon is true, transaction is discarded instead of committed.
  21.424   */
  21.425 -int xenbus_transaction_end(int abort)
  21.426 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort)
  21.427  {
  21.428  	char abortstr[2];
  21.429 +	int err;
  21.430  
  21.431  	if (abort)
  21.432  		strcpy(abortstr, "F");
  21.433  	else
  21.434  		strcpy(abortstr, "T");
  21.435 -	return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
  21.436 +
  21.437 +	err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
  21.438 +
  21.439 +	up_read(&xs_state.suspend_mutex);
  21.440 +
  21.441 +	return err;
  21.442  }
  21.443  EXPORT_SYMBOL(xenbus_transaction_end);
  21.444  
  21.445  /* Single read and scanf: returns -errno or num scanned. */
  21.446 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
  21.447 +int xenbus_scanf(struct xenbus_transaction *t,
  21.448 +		 const char *dir, const char *node, const char *fmt, ...)
  21.449  {
  21.450  	va_list ap;
  21.451  	int ret;
  21.452  	char *val;
  21.453  
  21.454 -	val = xenbus_read(dir, node, NULL);
  21.455 +	val = xenbus_read(t, dir, node, NULL);
  21.456  	if (IS_ERR(val))
  21.457  		return PTR_ERR(val);
  21.458  
  21.459 @@ -340,18 +491,28 @@ int xenbus_scanf(const char *dir, const 
  21.460  EXPORT_SYMBOL(xenbus_scanf);
  21.461  
  21.462  /* Single printf and write: returns -errno or 0. */
  21.463 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
  21.464 +int xenbus_printf(struct xenbus_transaction *t,
  21.465 +		  const char *dir, const char *node, const char *fmt, ...)
  21.466  {
  21.467  	va_list ap;
  21.468  	int ret;
  21.469 +#define PRINTF_BUFFER_SIZE 4096
  21.470 +	char *printf_buffer;
  21.471  
  21.472 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
  21.473 +	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
  21.474 +	if (printf_buffer == NULL)
  21.475 +		return -ENOMEM;
  21.476 +
  21.477  	va_start(ap, fmt);
  21.478 -	ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
  21.479 +	ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
  21.480  	va_end(ap);
  21.481  
  21.482 -	BUG_ON(ret > sizeof(printf_buffer)-1);
  21.483 -	return xenbus_write(dir, node, printf_buffer);
  21.484 +	BUG_ON(ret > PRINTF_BUFFER_SIZE-1);
  21.485 +	ret = xenbus_write(t, dir, node, printf_buffer);
  21.486 +
  21.487 +	kfree(printf_buffer);
  21.488 +
  21.489 +	return ret;
  21.490  }
  21.491  EXPORT_SYMBOL(xenbus_printf);
  21.492  
  21.493 @@ -361,19 +522,28 @@ void xenbus_dev_error(struct xenbus_devi
  21.494  	va_list ap;
  21.495  	int ret;
  21.496  	unsigned int len;
  21.497 +	char *printf_buffer;
  21.498  
  21.499 -	BUG_ON(down_trylock(&xenbus_lock) == 0);
  21.500 +	printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
  21.501 +	if (printf_buffer == NULL)
  21.502 +		goto fail;
  21.503  
  21.504  	len = sprintf(printf_buffer, "%i ", -err);
  21.505  	va_start(ap, fmt);
  21.506 -	ret = vsnprintf(printf_buffer+len, sizeof(printf_buffer)-len, fmt, ap);
  21.507 +	ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
  21.508  	va_end(ap);
  21.509  
  21.510 -	BUG_ON(len + ret > sizeof(printf_buffer)-1);
  21.511 +	BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
  21.512  	dev->has_error = 1;
  21.513 -	if (xenbus_write(dev->nodename, "error", printf_buffer) != 0)
  21.514 -		printk("xenbus: failed to write error node for %s (%s)\n",
  21.515 -		       dev->nodename, printf_buffer);
  21.516 +	if (xenbus_write(NULL, dev->nodename, "error", printf_buffer) != 0)
  21.517 +		goto fail;
  21.518 +
  21.519 +	kfree(printf_buffer);
  21.520 +	return;
  21.521 +
  21.522 + fail:
  21.523 +	printk("xenbus: failed to write error node for %s (%s)\n",
  21.524 +	       dev->nodename, printf_buffer);
  21.525  }
  21.526  EXPORT_SYMBOL(xenbus_dev_error);
  21.527  
  21.528 @@ -381,7 +551,7 @@ EXPORT_SYMBOL(xenbus_dev_error);
  21.529  void xenbus_dev_ok(struct xenbus_device *dev)
  21.530  {
  21.531  	if (dev->has_error) {
  21.532 -		if (xenbus_rm(dev->nodename, "error") != 0)
  21.533 +		if (xenbus_rm(NULL, dev->nodename, "error") != 0)
  21.534  			printk("xenbus: failed to clear error node for %s\n",
  21.535  			       dev->nodename);
  21.536  		else
  21.537 @@ -391,7 +561,7 @@ void xenbus_dev_ok(struct xenbus_device 
  21.538  EXPORT_SYMBOL(xenbus_dev_ok);
  21.539  	
  21.540  /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
  21.541 -int xenbus_gather(const char *dir, ...)
  21.542 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...)
  21.543  {
  21.544  	va_list ap;
  21.545  	const char *name;
  21.546 @@ -403,7 +573,7 @@ int xenbus_gather(const char *dir, ...)
  21.547  		void *result = va_arg(ap, void *);
  21.548  		char *p;
  21.549  
  21.550 -		p = xenbus_read(dir, name, NULL);
  21.551 +		p = xenbus_read(t, dir, name, NULL);
  21.552  		if (IS_ERR(p)) {
  21.553  			ret = PTR_ERR(p);
  21.554  			break;
  21.555 @@ -429,27 +599,8 @@ static int xs_watch(const char *path, co
  21.556  	iov[1].iov_base = (void *)token;
  21.557  	iov[1].iov_len = strlen(token) + 1;
  21.558  
  21.559 -	return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
  21.560 -}
  21.561 -
  21.562 -static char **xs_read_watch(unsigned int *num)
  21.563 -{
  21.564 -	enum xsd_sockmsg_type type;
  21.565 -	char *strings;
  21.566 -	unsigned int len;
  21.567 -
  21.568 -	strings = read_reply(&type, &len);
  21.569 -	if (IS_ERR(strings))
  21.570 -		return (char **)strings;
  21.571 -
  21.572 -	BUG_ON(type != XS_WATCH_EVENT);
  21.573 -
  21.574 -	return split(strings, len, num);
  21.575 -}
  21.576 -
  21.577 -static int xs_acknowledge_watch(const char *token)
  21.578 -{
  21.579 -	return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
  21.580 +	return xs_error(xs_talkv(NULL, XS_WATCH, iov,
  21.581 +				 ARRAY_SIZE(iov), NULL));
  21.582  }
  21.583  
  21.584  static int xs_unwatch(const char *path, const char *token)
  21.585 @@ -461,10 +612,10 @@ static int xs_unwatch(const char *path, 
  21.586  	iov[1].iov_base = (char *)token;
  21.587  	iov[1].iov_len = strlen(token) + 1;
  21.588  
  21.589 -	return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
  21.590 +	return xs_error(xs_talkv(NULL, XS_UNWATCH, iov,
  21.591 +				 ARRAY_SIZE(iov), NULL));
  21.592  }
  21.593  
  21.594 -/* A little paranoia: we don't just trust token. */
  21.595  static struct xenbus_watch *find_watch(const char *token)
  21.596  {
  21.597  	struct xenbus_watch *i, *cmp;
  21.598 @@ -474,6 +625,7 @@ static struct xenbus_watch *find_watch(c
  21.599  	list_for_each_entry(i, &watches, list)
  21.600  		if (i == cmp)
  21.601  			return i;
  21.602 +
  21.603  	return NULL;
  21.604  }
  21.605  
  21.606 @@ -485,92 +637,223 @@ int register_xenbus_watch(struct xenbus_
  21.607  	int err;
  21.608  
  21.609  	sprintf(token, "%lX", (long)watch);
  21.610 +
  21.611 +	down_read(&xs_state.suspend_mutex);
  21.612 +
  21.613 +	spin_lock(&watches_lock);
  21.614  	BUG_ON(find_watch(token));
  21.615 +	spin_unlock(&watches_lock);
  21.616  
  21.617  	err = xs_watch(watch->node, token);
  21.618 -	if (!err)
  21.619 +
  21.620 +	/* Ignore errors due to multiple registration. */
  21.621 +	if ((err == 0) || (err == -EEXIST)) {
  21.622 +		spin_lock(&watches_lock);
  21.623  		list_add(&watch->list, &watches);
  21.624 +		spin_unlock(&watches_lock);
  21.625 +	}
  21.626 +
  21.627 +	up_read(&xs_state.suspend_mutex);
  21.628 +
  21.629  	return err;
  21.630  }
  21.631  EXPORT_SYMBOL(register_xenbus_watch);
  21.632  
  21.633  void unregister_xenbus_watch(struct xenbus_watch *watch)
  21.634  {
  21.635 +	struct xs_stored_msg *msg, *tmp;
  21.636  	char token[sizeof(watch) * 2 + 1];
  21.637  	int err;
  21.638  
  21.639  	sprintf(token, "%lX", (long)watch);
  21.640 +
  21.641 +	down_read(&xs_state.suspend_mutex);
  21.642 +
  21.643 +	spin_lock(&watches_lock);
  21.644  	BUG_ON(!find_watch(token));
  21.645 +	list_del(&watch->list);
  21.646 +	spin_unlock(&watches_lock);
  21.647  
  21.648  	err = xs_unwatch(watch->node, token);
  21.649 -	list_del(&watch->list);
  21.650 -
  21.651  	if (err)
  21.652  		printk(KERN_WARNING
  21.653  		       "XENBUS Failed to release watch %s: %i\n",
  21.654  		       watch->node, err);
  21.655 +
  21.656 +	up_read(&xs_state.suspend_mutex);
  21.657 +
  21.658 +	/* Cancel pending watch events. */
  21.659 +	spin_lock(&watch_events_lock);
  21.660 +	list_for_each_entry_safe(msg, tmp, &watch_events, list) {
  21.661 +		if (msg->u.watch.handle != watch)
  21.662 +			continue;
  21.663 +		list_del(&msg->list);
  21.664 +		kfree(msg->u.watch.vec);
  21.665 +		kfree(msg);
  21.666 +	}
  21.667 +	spin_unlock(&watch_events_lock);
  21.668 +
  21.669 +	/* Flush any currently-executing callback, unless we are it. :-) */
  21.670 +	if (current->pid != xenwatch_pid) {
  21.671 +		down(&xenwatch_mutex);
  21.672 +		up(&xenwatch_mutex);
  21.673 +	}
  21.674  }
  21.675  EXPORT_SYMBOL(unregister_xenbus_watch);
  21.676  
  21.677 -/* Re-register callbacks to all watches. */
  21.678 -void reregister_xenbus_watches(void)
  21.679 +void xs_suspend(void)
  21.680 +{
  21.681 +	down_write(&xs_state.suspend_mutex);
  21.682 +	down(&xs_state.request_mutex);
  21.683 +}
  21.684 +
  21.685 +void xs_resume(void)
  21.686  {
  21.687  	struct xenbus_watch *watch;
  21.688  	char token[sizeof(watch) * 2 + 1];
  21.689  
  21.690 +	up(&xs_state.request_mutex);
  21.691 +
  21.692 +	/* No need for watches_lock: the suspend_mutex is sufficient. */
  21.693  	list_for_each_entry(watch, &watches, list) {
  21.694  		sprintf(token, "%lX", (long)watch);
  21.695  		xs_watch(watch->node, token);
  21.696  	}
  21.697 +
  21.698 +	up_write(&xs_state.suspend_mutex);
  21.699  }
  21.700  
  21.701 -static int watch_thread(void *unused)
  21.702 +static int xenwatch_thread(void *unused)
  21.703  {
  21.704 -	for (;;) {
  21.705 -		char **vec = NULL;
  21.706 -		unsigned int num;
  21.707 -
  21.708 -		wait_event(xb_waitq, xs_input_avail());
  21.709 -
  21.710 -		/* If this is a spurious wakeup caused by someone
  21.711 -		 * doing an op, they'll hold the lock and the buffer
  21.712 -		 * will be empty by the time we get there.		 
  21.713 -		 */
  21.714 -		down(&xenbus_lock);
  21.715 -		if (xs_input_avail())
  21.716 -			vec = xs_read_watch(&num);
  21.717 +	struct list_head *ent;
  21.718 +	struct xs_stored_msg *msg;
  21.719  
  21.720 -		if (vec && !IS_ERR(vec)) {
  21.721 -			struct xenbus_watch *w;
  21.722 -			int err;
  21.723 +	for (;;) {
  21.724 +		wait_event_interruptible(watch_events_waitq,
  21.725 +					 !list_empty(&watch_events));
  21.726  
  21.727 -			err = xs_acknowledge_watch(vec[XS_WATCH_TOKEN]);
  21.728 -			if (err)
  21.729 -				printk(KERN_WARNING "XENBUS ack %s fail %i\n",
  21.730 -				       vec[XS_WATCH_TOKEN], err);
  21.731 -			w = find_watch(vec[XS_WATCH_TOKEN]);
  21.732 -			BUG_ON(!w);
  21.733 -			w->callback(w, (const char **)vec, num);
  21.734 -			kfree(vec);
  21.735 -		} else if (vec)
  21.736 -			printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
  21.737 -			       PTR_ERR(vec));
  21.738 -		up(&xenbus_lock);
  21.739 +		down(&xenwatch_mutex);
  21.740 +
  21.741 +		spin_lock(&watch_events_lock);
  21.742 +		ent = watch_events.next;
  21.743 +		if (ent != &watch_events)
  21.744 +			list_del(ent);
  21.745 +		spin_unlock(&watch_events_lock);
  21.746 +
  21.747 +		if (ent != &watch_events) {
  21.748 +			msg = list_entry(ent, struct xs_stored_msg, list);
  21.749 +			msg->u.watch.handle->callback(
  21.750 +				msg->u.watch.handle,
  21.751 +				(const char **)msg->u.watch.vec,
  21.752 +				msg->u.watch.vec_size);
  21.753 +			kfree(msg->u.watch.vec);
  21.754 +			kfree(msg);
  21.755 +		}
  21.756 +
  21.757 +		up(&xenwatch_mutex);
  21.758 +	}
  21.759 +}
  21.760 +
  21.761 +static int process_msg(void)
  21.762 +{
  21.763 +	struct xs_stored_msg *msg;
  21.764 +	char *body;
  21.765 +	int err;
  21.766 +
  21.767 +	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
  21.768 +	if (msg == NULL)
  21.769 +		return -ENOMEM;
  21.770 +
  21.771 +	err = xb_read(&msg->hdr, sizeof(msg->hdr));
  21.772 +	if (err) {
  21.773 +		kfree(msg);
  21.774 +		return err;
  21.775 +	}
  21.776 +
  21.777 +	body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
  21.778 +	if (body == NULL) {
  21.779 +		kfree(msg);
  21.780 +		return -ENOMEM;
  21.781 +	}
  21.782 +
  21.783 +	err = xb_read(body, msg->hdr.len);
  21.784 +	if (err) {
  21.785 +		kfree(body);
  21.786 +		kfree(msg);
  21.787 +		return err;
  21.788 +	}
  21.789 +	body[msg->hdr.len] = '\0';
  21.790 +
  21.791 +	if (msg->hdr.type == XS_WATCH_EVENT) {
  21.792 +		msg->u.watch.vec = split(body, msg->hdr.len,
  21.793 +					 &msg->u.watch.vec_size);
  21.794 +		if (IS_ERR(msg->u.watch.vec)) {
  21.795 +			kfree(msg);
  21.796 +			return PTR_ERR(msg->u.watch.vec);
  21.797 +		}
  21.798 +
  21.799 +		spin_lock(&watches_lock);
  21.800 +		msg->u.watch.handle = find_watch(
  21.801 +			msg->u.watch.vec[XS_WATCH_TOKEN]);
  21.802 +		if (msg->u.watch.handle != NULL) {
  21.803 +			spin_lock(&watch_events_lock);
  21.804 +			list_add_tail(&msg->list, &watch_events);
  21.805 +			wake_up(&watch_events_waitq);
  21.806 +			spin_unlock(&watch_events_lock);
  21.807 +		} else {
  21.808 +			kfree(msg->u.watch.vec);
  21.809 +			kfree(msg);
  21.810 +		}
  21.811 +		spin_unlock(&watches_lock);
  21.812 +	} else {
  21.813 +		msg->u.reply.body = body;
  21.814 +		spin_lock(&xs_state.reply_lock);
  21.815 +		list_add_tail(&msg->list, &xs_state.reply_list);
  21.816 +		spin_unlock(&xs_state.reply_lock);
  21.817 +		wake_up(&xs_state.reply_waitq);
  21.818 +	}
  21.819 +
  21.820 +	return 0;
  21.821 +}
  21.822 +
  21.823 +static int xenbus_thread(void *unused)
  21.824 +{
  21.825 +	int err;
  21.826 +
  21.827 +	for (;;) {
  21.828 +		err = process_msg();
  21.829 +		if (err)
  21.830 +			printk(KERN_WARNING "XENBUS error %d while reading "
  21.831 +			       "message\n", err);
  21.832  	}
  21.833  }
  21.834  
  21.835  int xs_init(void)
  21.836  {
  21.837  	int err;
  21.838 -	struct task_struct *watcher;
  21.839 +	struct task_struct *task;
  21.840  
  21.841 +	INIT_LIST_HEAD(&xs_state.reply_list);
  21.842 +	spin_lock_init(&xs_state.reply_lock);
  21.843 +	init_waitqueue_head(&xs_state.reply_waitq);
  21.844 +
  21.845 +	init_MUTEX(&xs_state.request_mutex);
  21.846 +	init_rwsem(&xs_state.suspend_mutex);
  21.847 +
  21.848 +	/* Initialize the shared memory rings to talk to xenstored */
  21.849  	err = xb_init_comms();
  21.850  	if (err)
  21.851  		return err;
  21.852 -	
  21.853 -	watcher = kthread_run(watch_thread, NULL, "kxbwatch");
  21.854 -	if (IS_ERR(watcher))
  21.855 -		return PTR_ERR(watcher);
  21.856 +
  21.857 +	task = kthread_run(xenwatch_thread, NULL, "xenwatch");
  21.858 +	if (IS_ERR(task))
  21.859 +		return PTR_ERR(task);
  21.860 +	xenwatch_pid = task->pid;
  21.861 +
  21.862 +	task = kthread_run(xenbus_thread, NULL, "xenbus");
  21.863 +	if (IS_ERR(task))
  21.864 +		return PTR_ERR(task);
  21.865 +
  21.866  	return 0;
  21.867  }
  21.868  
    22.1 --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Tue Oct 11 15:50:21 2005 -0600
    22.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h	Tue Oct 11 16:57:44 2005 -0600
    22.3 @@ -78,30 +78,35 @@ int xenbus_register_driver(struct xenbus
    22.4  int xenbus_register_backend(struct xenbus_driver *drv);
    22.5  void xenbus_unregister_driver(struct xenbus_driver *drv);
    22.6  
    22.7 -/* Caller must hold this lock to call these functions: it's also held
    22.8 - * across watch callbacks. */
    22.9 -extern struct semaphore xenbus_lock;
   22.10 +struct xenbus_transaction;
   22.11  
   22.12 -char **xenbus_directory(const char *dir, const char *node, unsigned int *num);
   22.13 -void *xenbus_read(const char *dir, const char *node, unsigned int *len);
   22.14 -int xenbus_write(const char *dir, const char *node, const char *string);
   22.15 -int xenbus_mkdir(const char *dir, const char *node);
   22.16 -int xenbus_exists(const char *dir, const char *node);
   22.17 -int xenbus_rm(const char *dir, const char *node);
   22.18 -int xenbus_transaction_start(void);
   22.19 -int xenbus_transaction_end(int abort);
   22.20 +char **xenbus_directory(struct xenbus_transaction *t,
   22.21 +			const char *dir, const char *node, unsigned int *num);
   22.22 +void *xenbus_read(struct xenbus_transaction *t,
   22.23 +		  const char *dir, const char *node, unsigned int *len);
   22.24 +int xenbus_write(struct xenbus_transaction *t,
   22.25 +		 const char *dir, const char *node, const char *string);
   22.26 +int xenbus_mkdir(struct xenbus_transaction *t,
   22.27 +		 const char *dir, const char *node);
   22.28 +int xenbus_exists(struct xenbus_transaction *t,
   22.29 +		  const char *dir, const char *node);
   22.30 +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node);
   22.31 +struct xenbus_transaction *xenbus_transaction_start(void);
   22.32 +int xenbus_transaction_end(struct xenbus_transaction *t, int abort);
   22.33  
   22.34  /* Single read and scanf: returns -errno or num scanned if > 0. */
   22.35 -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
   22.36 -	__attribute__((format(scanf, 3, 4)));
   22.37 +int xenbus_scanf(struct xenbus_transaction *t,
   22.38 +		 const char *dir, const char *node, const char *fmt, ...)
   22.39 +	__attribute__((format(scanf, 4, 5)));
   22.40  
   22.41  /* Single printf and write: returns -errno or 0. */
   22.42 -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
   22.43 -	__attribute__((format(printf, 3, 4)));
   22.44 +int xenbus_printf(struct xenbus_transaction *t,
   22.45 +		  const char *dir, const char *node, const char *fmt, ...)
   22.46 +	__attribute__((format(printf, 4, 5)));
   22.47  
   22.48  /* Generic read function: NULL-terminated triples of name,
   22.49   * sprintf-style type string, and pointer. Returns 0 or errno.*/
   22.50 -int xenbus_gather(const char *dir, ...);
   22.51 +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...);
   22.52  
   22.53  /* Report a (negative) errno into the store, with explanation. */
   22.54  void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,...);
   22.55 @@ -113,7 +118,11 @@ void xenbus_dev_ok(struct xenbus_device 
   22.56  struct xenbus_watch
   22.57  {
   22.58  	struct list_head list;
   22.59 +
   22.60 +	/* Path being watched. */
   22.61  	char *node;
   22.62 +
   22.63 +	/* Callback (executed in a process context with no locks held). */
   22.64  	void (*callback)(struct xenbus_watch *,
   22.65  			 const char **vec, unsigned int len);
   22.66  };
   22.67 @@ -124,7 +133,11 @@ void unregister_xenstore_notifier(struct
   22.68  
   22.69  int register_xenbus_watch(struct xenbus_watch *watch);
   22.70  void unregister_xenbus_watch(struct xenbus_watch *watch);
   22.71 -void reregister_xenbus_watches(void);
   22.72 +void xs_suspend(void);
   22.73 +void xs_resume(void);
   22.74 +
   22.75 +/* Used by xenbus_dev to borrow kernel's store connection. */
   22.76 +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
   22.77  
   22.78  /* Called from xen core code. */
   22.79  void xenbus_suspend(void);
    23.1 --- a/tools/blktap/xenbus.c	Tue Oct 11 15:50:21 2005 -0600
    23.2 +++ b/tools/blktap/xenbus.c	Tue Oct 11 16:57:44 2005 -0600
    23.3 @@ -260,10 +260,6 @@ int xs_fire_next_watch(struct xs_handle 
    23.4      node  = res[XS_WATCH_PATH];
    23.5      token = res[XS_WATCH_TOKEN];
    23.6  
    23.7 -    er = xs_acknowledge_watch(h, token);
    23.8 -    if (er == 0)
    23.9 -        warn("Couldn't acknowledge watch (%s)", token);
   23.10 -
   23.11      w = find_watch(token);
   23.12      if (!w)
   23.13      {
    24.1 --- a/tools/console/Makefile	Tue Oct 11 15:50:21 2005 -0600
    24.2 +++ b/tools/console/Makefile	Tue Oct 11 16:57:44 2005 -0600
    24.3 @@ -3,7 +3,7 @@ XEN_ROOT=../..
    24.4  include $(XEN_ROOT)/tools/Rules.mk
    24.5  
    24.6  DAEMON_INSTALL_DIR = /usr/sbin
    24.7 -CLIENT_INSTALL_DIR = /usr/libexec/xen
    24.8 +CLIENT_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
    24.9  
   24.10  INSTALL         = install
   24.11  INSTALL_PROG    = $(INSTALL) -m0755
    25.1 --- a/tools/console/client/main.c	Tue Oct 11 15:50:21 2005 -0600
    25.2 +++ b/tools/console/client/main.c	Tue Oct 11 16:57:44 2005 -0600
    25.3 @@ -220,7 +220,7 @@ int main(int argc, char **argv)
    25.4  	if (path == NULL)
    25.5  		err(ENOMEM, "realloc");
    25.6  	strcat(path, "/console/tty");
    25.7 -	str_pty = xs_read(xs, path, &len);
    25.8 +	str_pty = xs_read(xs, NULL, path, &len);
    25.9  
   25.10  	/* FIXME consoled currently does not assume domain-0 doesn't have a
   25.11  	   console which is good when we break domain-0 up.  To keep us
   25.12 @@ -245,7 +245,7 @@ int main(int argc, char **argv)
   25.13  		struct timeval tv = { 0, 500 };
   25.14  		select(0, NULL, NULL, NULL, &tv); /* pause briefly */
   25.15  
   25.16 -		str_pty = xs_read(xs, path, &len);
   25.17 +		str_pty = xs_read(xs, NULL, path, &len);
   25.18  	}
   25.19  
   25.20  	if (str_pty == NULL) {
    26.1 --- a/tools/console/daemon/io.c	Tue Oct 11 15:50:21 2005 -0600
    26.2 +++ b/tools/console/daemon/io.c	Tue Oct 11 16:57:44 2005 -0600
    26.3 @@ -25,6 +25,7 @@
    26.4  #include <xenctrl.h>
    26.5  #include <xs.h>
    26.6  #include <xen/linux/evtchn.h>
    26.7 +#include <xen/io/console.h>
    26.8  
    26.9  #include <malloc.h>
   26.10  #include <stdlib.h>
   26.11 @@ -62,25 +63,12 @@ struct domain
   26.12  	char *conspath;
   26.13  	int ring_ref;
   26.14  	int local_port;
   26.15 -	char *page;
   26.16  	int evtchn_fd;
   26.17 +	struct xencons_interface *interface;
   26.18  };
   26.19  
   26.20  static struct domain *dom_head;
   26.21  
   26.22 -struct ring_head
   26.23 -{
   26.24 -	u32 cons;
   26.25 -	u32 prod;
   26.26 -	char buf[0];
   26.27 -} __attribute__((packed));
   26.28 -
   26.29 -#define PAGE_SIZE (getpagesize())
   26.30 -#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head))
   26.31 -#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE)
   26.32 -#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE)
   26.33 -#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons))
   26.34 -
   26.35  static void evtchn_notify(struct domain *dom)
   26.36  {
   26.37  	struct ioctl_evtchn_notify notify;
   26.38 @@ -91,12 +79,12 @@ static void evtchn_notify(struct domain 
   26.39  static void buffer_append(struct domain *dom)
   26.40  {
   26.41  	struct buffer *buffer = &dom->buffer;
   26.42 -	struct ring_head *ring = (struct ring_head *)dom->page;
   26.43  	size_t size;
   26.44 -	u32 oldcons;
   26.45 +	XENCONS_RING_IDX oldcons;
   26.46  	int notify = 0;
   26.47 +	struct xencons_interface *intf = dom->interface;
   26.48  
   26.49 -	while ((size = ring->prod - ring->cons) != 0) {
   26.50 +	while ((size = (intf->out_prod - intf->out_cons)) != 0) {
   26.51  		notify = 1;
   26.52  
   26.53  		if ((buffer->capacity - buffer->size) < size) {
   26.54 @@ -108,12 +96,12 @@ static void buffer_append(struct domain 
   26.55  			}
   26.56  		}
   26.57  
   26.58 -		oldcons = ring->cons;
   26.59 -		while (ring->cons < (oldcons + size)) {
   26.60 -			buffer->data[buffer->size] =
   26.61 -				ring->buf[XENCONS_IDX(ring->cons)];
   26.62 +		oldcons = intf->out_cons;
   26.63 +		while ((intf->out_cons - oldcons) < size) {
   26.64 +			buffer->data[buffer->size] = intf->out[
   26.65 +				MASK_XENCONS_IDX(intf->out_cons, intf->out)];
   26.66  			buffer->size++;
   26.67 -			ring->cons++;
   26.68 +			intf->out_cons++;
   26.69  		}
   26.70  
   26.71  		if (buffer->max_capacity &&
   26.72 @@ -179,7 +167,7 @@ static int domain_create_tty(struct doma
   26.73  		success = asprintf(&path, "%s/tty", dom->conspath) != -1;
   26.74  		if (!success)
   26.75  			goto out;
   26.76 -		success = xs_write(xs, path, slave, strlen(slave));
   26.77 +		success = xs_write(xs, NULL, path, slave, strlen(slave));
   26.78  		free(path);
   26.79  		if (!success)
   26.80  			goto out;
   26.81 @@ -187,7 +175,7 @@ static int domain_create_tty(struct doma
   26.82  		success = asprintf(&path, "%s/limit", dom->conspath) != -1;
   26.83  		if (!success)
   26.84  			goto out;
   26.85 -		data = xs_read(xs, path, &len);
   26.86 +		data = xs_read(xs, NULL, path, &len);
   26.87  		if (data) {
   26.88  			dom->buffer.max_capacity = strtoul(data, 0, 0);
   26.89  			free(data);
   26.90 @@ -216,7 +204,7 @@ int xs_gather(struct xs_handle *xs, cons
   26.91  		char *p;
   26.92  
   26.93  		asprintf(&path, "%s/%s", dir, name);
   26.94 -		p = xs_read(xs, path, NULL);
   26.95 +		p = xs_read(xs, NULL, path, NULL);
   26.96  		free(path);
   26.97  		if (p == NULL) {
   26.98  			ret = ENOENT;
   26.99 @@ -246,12 +234,13 @@ static int domain_create_ring(struct dom
  26.100  		goto out;
  26.101  
  26.102  	if (ring_ref != dom->ring_ref) {
  26.103 -		if (dom->page)
  26.104 -			munmap(dom->page, getpagesize());
  26.105 -		dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(),
  26.106 -						 PROT_READ|PROT_WRITE,
  26.107 -						 (unsigned long)ring_ref);
  26.108 -		if (dom->page == NULL) {
  26.109 +		if (dom->interface != NULL)
  26.110 +			munmap(dom->interface, getpagesize());
  26.111 +		dom->interface = xc_map_foreign_range(
  26.112 +			xc, dom->domid, getpagesize(),
  26.113 +			PROT_READ|PROT_WRITE,
  26.114 +			(unsigned long)ring_ref);
  26.115 +		if (dom->interface == NULL) {
  26.116  			err = EINVAL;
  26.117  			goto out;
  26.118  		}
  26.119 @@ -334,7 +323,7 @@ static struct domain *create_domain(int 
  26.120  
  26.121  	dom->ring_ref = -1;
  26.122  	dom->local_port = -1;
  26.123 -	dom->page = NULL;
  26.124 +	dom->interface = NULL;
  26.125  	dom->evtchn_fd = -1;
  26.126  
  26.127  	if (!watch_domain(dom, true))
  26.128 @@ -396,9 +385,9 @@ static void shutdown_domain(struct domai
  26.129  {
  26.130  	d->is_dead = true;
  26.131  	watch_domain(d, false);
  26.132 -	if (d->page)
  26.133 -		munmap(d->page, getpagesize());
  26.134 -	d->page = NULL;
  26.135 +	if (d->interface != NULL)
  26.136 +		munmap(d->interface, getpagesize());
  26.137 +	d->interface = NULL;
  26.138  	if (d->evtchn_fd != -1)
  26.139  		close(d->evtchn_fd);
  26.140  	d->evtchn_fd = -1;
  26.141 @@ -426,13 +415,21 @@ void enum_domains(void)
  26.142  
  26.143  static void handle_tty_read(struct domain *dom)
  26.144  {
  26.145 -	ssize_t len;
  26.146 +	ssize_t len = 0;
  26.147  	char msg[80];
  26.148 -	struct ring_head *inring =
  26.149 -		(struct ring_head *)(dom->page + PAGE_SIZE/2);
  26.150  	int i;
  26.151 +	struct xencons_interface *intf = dom->interface;
  26.152 +	XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons;
  26.153  
  26.154 -	len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg)));
  26.155 +	if (sizeof(intf->in) > filled)
  26.156 +		len = sizeof(intf->in) - filled;
  26.157 +	if (len > sizeof(msg))
  26.158 +		len = sizeof(msg);
  26.159 +
  26.160 +	if (len == 0)
  26.161 +		return;
  26.162 +
  26.163 +	len = read(dom->tty_fd, msg, len);
  26.164  	if (len < 1) {
  26.165  		close(dom->tty_fd);
  26.166  		dom->tty_fd = -1;
  26.167 @@ -444,8 +441,9 @@ static void handle_tty_read(struct domai
  26.168  		}
  26.169  	} else if (domain_is_valid(dom->domid)) {
  26.170  		for (i = 0; i < len; i++) {
  26.171 -			inring->buf[XENCONS_IDX(inring->prod)] = msg[i];
  26.172 -			inring->prod++;
  26.173 +			intf->in[MASK_XENCONS_IDX(intf->in_prod, intf->in)] =
  26.174 +				msg[i];
  26.175 +			intf->in_prod++;
  26.176  		}
  26.177  		evtchn_notify(dom);
  26.178  	} else {
  26.179 @@ -505,7 +503,6 @@ static void handle_xs(int fd)
  26.180  			domain_create_ring(dom);
  26.181  	}
  26.182  
  26.183 -	xs_acknowledge_watch(xs, vec[1]);
  26.184  	free(vec);
  26.185  }
  26.186  
  26.187 @@ -565,3 +562,13 @@ void handle_io(void)
  26.188  		}
  26.189  	} while (ret > -1);
  26.190  }
  26.191 +
  26.192 +/*
  26.193 + * Local variables:
  26.194 + *  c-file-style: "linux"
  26.195 + *  indent-tabs-mode: t
  26.196 + *  c-indent-level: 8
  26.197 + *  c-basic-offset: 8
  26.198 + *  tab-width: 8
  26.199 + * End:
  26.200 + */
    27.1 --- a/tools/examples/Makefile	Tue Oct 11 15:50:21 2005 -0600
    27.2 +++ b/tools/examples/Makefile	Tue Oct 11 16:57:44 2005 -0600
    27.3 @@ -24,6 +24,7 @@ XEN_SCRIPTS += network-route vif-route
    27.4  XEN_SCRIPTS += network-nat vif-nat
    27.5  XEN_SCRIPTS += block
    27.6  XEN_SCRIPTS += block-enbd
    27.7 +XEN_SCRIPTS += xen-hotplug-common.sh
    27.8  
    27.9  XEN_HOTPLUG_DIR = /etc/hotplug
   27.10  XEN_HOTPLUG_SCRIPTS = xen-backend.agent
    28.1 --- a/tools/examples/block	Tue Oct 11 15:50:21 2005 -0600
    28.2 +++ b/tools/examples/block	Tue Oct 11 16:57:44 2005 -0600
    28.3 @@ -1,8 +1,7 @@
    28.4  #!/bin/sh
    28.5  
    28.6 -set -e
    28.7 -
    28.8 -export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
    28.9 +dir=$(dirname "$0")
   28.10 +. "$dir/xen-hotplug-common.sh"
   28.11  
   28.12  expand_dev() {
   28.13    local dev
   28.14 @@ -25,15 +24,15 @@ write_dev() {
   28.15    major=$(stat -L -c %t "$1")
   28.16    minor=$(stat -L -c %T "$1")
   28.17    pdev=$(printf "0x%02x%02x" 0x$major 0x$minor)
   28.18 -  xenstore-write "$XENBUS_PATH"/physical-device $pdev \
   28.19 +  xenstore_write "$XENBUS_PATH"/physical-device $pdev \
   28.20        "$XENBUS_PATH"/node $1
   28.21  }
   28.22  
   28.23 -t=$(xenstore-read "$XENBUS_PATH"/type)
   28.24 +t=$(xenstore_read "$XENBUS_PATH"/type || true)
   28.25  
   28.26  case $1 in 
   28.27    bind)
   28.28 -    p=$(xenstore-read "$XENBUS_PATH"/params)
   28.29 +    p=$(xenstore_read "$XENBUS_PATH"/params)
   28.30      case $t in 
   28.31        phy)
   28.32          dev=$(expand_dev $p)
   28.33 @@ -60,7 +59,7 @@ case $1 in
   28.34      ;;
   28.35  
   28.36    unbind)
   28.37 -    node=$(xenstore-read "$XENBUS_PATH"/node)
   28.38 +    node=$(xenstore_read "$XENBUS_PATH"/node)
   28.39      case $t in 
   28.40        phy)
   28.41  	exit 0
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/examples/xen-hotplug-common.sh	Tue Oct 11 16:57:44 2005 -0600
    29.3 @@ -0,0 +1,26 @@
    29.4 +set -e
    29.5 +
    29.6 +export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH
    29.7 +
    29.8 +log() {
    29.9 +  local level="$1"
   29.10 +  shift
   29.11 +  logger -p "daemon.$level" -- "$0:" "$@" || echo "$0 $@" >&2
   29.12 +}
   29.13 +
   29.14 +xenstore_read() {
   29.15 +  local v=$(xenstore-read "$@" || true)
   29.16 +  if [ "$v" == "" ]
   29.17 +  then
   29.18 +    log error "xenstore-read $@ failed."
   29.19 +    exit 1
   29.20 +  fi
   29.21 +  echo "$v"
   29.22 +}
   29.23 +
   29.24 +xenstore_write() {
   29.25 +  log debug "Writing $@ to xenstore."
   29.26 +  xenstore-write "$@" || log error "Writing $@ to xenstore failed."
   29.27 +}
   29.28 +
   29.29 +log debug "$@" "XENBUS_PATH=$XENBUS_PATH"
    30.1 --- a/tools/libxc/xc_linux_save.c	Tue Oct 11 15:50:21 2005 -0600
    30.2 +++ b/tools/libxc/xc_linux_save.c	Tue Oct 11 16:57:44 2005 -0600
    30.3 @@ -35,7 +35,7 @@
    30.4  #define DEBUG 0
    30.5  
    30.6  #if 1
    30.7 -#define ERR(_f, _a...) do { fprintf(stderr, _f , ## _a); fflush(stderr); } while (0)
    30.8 +#define ERR(_f, _a...) do { fprintf(stderr, _f "\n" , ## _a); fflush(stderr); } while (0)
    30.9  #else
   30.10  #define ERR(_f, _a...) ((void)0)
   30.11  #endif
    31.1 --- a/tools/misc/xend	Tue Oct 11 15:50:21 2005 -0600
    31.2 +++ b/tools/misc/xend	Tue Oct 11 16:57:44 2005 -0600
    31.3 @@ -2,9 +2,10 @@
    31.4  #  -*- mode: python; -*-
    31.5  #============================================================================
    31.6  # Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    31.7 +# Copyright (C) 2005 XenSource Ltd
    31.8  #============================================================================
    31.9  
   31.10 -"""Xen management daemon. Lives in /usr/sbin.
   31.11 +"""Xen management daemon.
   31.12     Provides console server and HTTP management api.
   31.13  
   31.14     Run:
   31.15 @@ -67,14 +68,14 @@ def check_user():
   31.16  
   31.17  def start_xenstored():
   31.18      XENSTORED_TRACE = os.getenv("XENSTORED_TRACE")
   31.19 -    cmd = "/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid"
   31.20 +    cmd = "xenstored --pid-file=/var/run/xenstore.pid"
   31.21      if XENSTORED_TRACE:
   31.22          cmd += " -T /var/log/xenstored-trace.log"
   31.23      s,o = commands.getstatusoutput(cmd)
   31.24  
   31.25  def start_consoled():
   31.26      if os.fork() == 0:
   31.27 -        os.execvp('/usr/sbin/xenconsoled', ['/usr/sbin/xenconsoled'])
   31.28 +        os.execvp('xenconsoled', ['xenconsoled'])
   31.29              
   31.30  def main():
   31.31      try:
    32.1 --- a/tools/pygrub/src/fsys/reiser/reisermodule.c	Tue Oct 11 15:50:21 2005 -0600
    32.2 +++ b/tools/pygrub/src/fsys/reiser/reisermodule.c	Tue Oct 11 16:57:44 2005 -0600
    32.3 @@ -46,7 +46,7 @@ void file_dal_close(dal_t *dal) {
    32.4  
    32.5  	if (!dal) return;
    32.6  
    32.7 -	close((int)dal->dev);
    32.8 +	close((size_t)dal->dev);
    32.9  	dal_free(dal);
   32.10  }
   32.11  
    33.1 --- a/tools/python/xen/lowlevel/xs/xs.c	Tue Oct 11 15:50:21 2005 -0600
    33.2 +++ b/tools/python/xen/lowlevel/xs/xs.c	Tue Oct 11 16:57:44 2005 -0600
    33.3 @@ -80,8 +80,8 @@ static inline PyObject *pyvalue_str(char
    33.4  
    33.5  static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds)
    33.6  {
    33.7 -    static char *kwd_spec[] = { "path", NULL };
    33.8 -    static char *arg_spec = "s|";
    33.9 +    static char *kwd_spec[] = { "transaction", "path", NULL };
   33.10 +    static char *arg_spec = "ss";
   33.11      char *path = NULL;
   33.12  
   33.13      struct xs_handle *xh = xshandle(self);
   33.14 @@ -89,13 +89,19 @@ static PyObject *xspy_read(PyObject *sel
   33.15      unsigned int xsval_n = 0;
   33.16      PyObject *val = NULL;
   33.17  
   33.18 +    struct xs_transaction_handle *th;
   33.19 +    char *thstr;
   33.20 +
   33.21      if (!xh)
   33.22          goto exit;
   33.23      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   33.24 -                                     &path))
   33.25 +                                     &thstr, &path))
   33.26          goto exit;
   33.27 +
   33.28 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   33.29 +
   33.30      Py_BEGIN_ALLOW_THREADS
   33.31 -    xsval = xs_read(xh, path, &xsval_n);
   33.32 +    xsval = xs_read(xh, th, path, &xsval_n);
   33.33      Py_END_ALLOW_THREADS
   33.34      if (!xsval) {
   33.35          if (errno == ENOENT) {
   33.36 @@ -123,8 +129,8 @@ static PyObject *xspy_read(PyObject *sel
   33.37  
   33.38  static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds)
   33.39  {
   33.40 -    static char *kwd_spec[] = { "path", "data", NULL };
   33.41 -    static char *arg_spec = "ss#";
   33.42 +    static char *kwd_spec[] = { "transaction", "path", "data", NULL };
   33.43 +    static char *arg_spec = "sss#";
   33.44      char *path = NULL;
   33.45      char *data = NULL;
   33.46      int data_n = 0;
   33.47 @@ -133,13 +139,19 @@ static PyObject *xspy_write(PyObject *se
   33.48      PyObject *val = NULL;
   33.49      int xsval = 0;
   33.50  
   33.51 +    struct xs_transaction_handle *th;
   33.52 +    char *thstr;
   33.53 +
   33.54      if (!xh)
   33.55          goto exit;
   33.56      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   33.57 -                                     &path, &data, &data_n))
   33.58 +                                     &thstr, &path, &data, &data_n))
   33.59          goto exit;
   33.60 +
   33.61 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   33.62 +
   33.63      Py_BEGIN_ALLOW_THREADS
   33.64 -    xsval = xs_write(xh, path, data, data_n);
   33.65 +    xsval = xs_write(xh, th, path, data, data_n);
   33.66      Py_END_ALLOW_THREADS
   33.67      if (!xsval) {
   33.68          PyErr_SetFromErrno(PyExc_RuntimeError);
   33.69 @@ -162,8 +174,8 @@ static PyObject *xspy_write(PyObject *se
   33.70  
   33.71  static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds)
   33.72  {
   33.73 -    static char *kwd_spec[] = { "path", NULL };
   33.74 -    static char *arg_spec = "s|";
   33.75 +    static char *kwd_spec[] = { "transaction", "path", NULL };
   33.76 +    static char *arg_spec = "ss";
   33.77      char *path = NULL;
   33.78  
   33.79      struct xs_handle *xh = xshandle(self);
   33.80 @@ -172,12 +184,20 @@ static PyObject *xspy_ls(PyObject *self,
   33.81      unsigned int xsval_n = 0;
   33.82      int i;
   33.83  
   33.84 +    struct xs_transaction_handle *th;
   33.85 +    char *thstr;
   33.86 +
   33.87      if (!xh)
   33.88          goto exit;
   33.89 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
   33.90 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
   33.91 +                                     &thstr, &path))
   33.92          goto exit;
   33.93 +
   33.94 +
   33.95 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
   33.96 +
   33.97      Py_BEGIN_ALLOW_THREADS
   33.98 -    xsval = xs_directory(xh, path, &xsval_n);
   33.99 +    xsval = xs_directory(xh, th, path, &xsval_n);
  33.100      Py_END_ALLOW_THREADS
  33.101      if (!xsval) {
  33.102          if (errno == ENOENT) {
  33.103 @@ -205,20 +225,27 @@ static PyObject *xspy_ls(PyObject *self,
  33.104  
  33.105  static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds)
  33.106  {
  33.107 -    static char *kwd_spec[] = { "path", NULL };
  33.108 -    static char *arg_spec = "s|";
  33.109 +    static char *kwd_spec[] = { "transaction", "path", NULL };
  33.110 +    static char *arg_spec = "ss";
  33.111      char *path = NULL;
  33.112  
  33.113      struct xs_handle *xh = xshandle(self);
  33.114      PyObject *val = NULL;
  33.115      int xsval = 0;
  33.116  
  33.117 +    struct xs_transaction_handle *th;
  33.118 +    char *thstr;
  33.119 +
  33.120      if (!xh)
  33.121          goto exit;
  33.122 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  33.123 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  33.124 +                                     &thstr, &path))
  33.125          goto exit;
  33.126 +
  33.127 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  33.128 +
  33.129      Py_BEGIN_ALLOW_THREADS
  33.130 -    xsval = xs_mkdir(xh, path);
  33.131 +    xsval = xs_mkdir(xh, th, path);
  33.132      Py_END_ALLOW_THREADS
  33.133      if (!xsval) {
  33.134          PyErr_SetFromErrno(PyExc_RuntimeError);
  33.135 @@ -240,20 +267,27 @@ static PyObject *xspy_mkdir(PyObject *se
  33.136  
  33.137  static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds)
  33.138  {
  33.139 -    static char *kwd_spec[] = { "path", NULL };
  33.140 -    static char *arg_spec = "s|";
  33.141 +    static char *kwd_spec[] = { "transaction", "path", NULL };
  33.142 +    static char *arg_spec = "ss";
  33.143      char *path = NULL;
  33.144  
  33.145      struct xs_handle *xh = xshandle(self);
  33.146      PyObject *val = NULL;
  33.147      int xsval = 0;
  33.148  
  33.149 +    struct xs_transaction_handle *th;
  33.150 +    char *thstr;
  33.151 +
  33.152      if (!xh)
  33.153          goto exit;
  33.154 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  33.155 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  33.156 +                                     &thstr, &path))
  33.157          goto exit;
  33.158 +
  33.159 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  33.160 +
  33.161      Py_BEGIN_ALLOW_THREADS
  33.162 -    xsval = xs_rm(xh, path);
  33.163 +    xsval = xs_rm(xh, th, path);
  33.164      Py_END_ALLOW_THREADS
  33.165      if (!xsval && errno != ENOENT) {
  33.166          PyErr_SetFromErrno(PyExc_RuntimeError);
  33.167 @@ -276,8 +310,8 @@ static PyObject *xspy_rm(PyObject *self,
  33.168  static PyObject *xspy_get_permissions(PyObject *self, PyObject *args,
  33.169                                        PyObject *kwds)
  33.170  {
  33.171 -    static char *kwd_spec[] = { "path", NULL };
  33.172 -    static char *arg_spec = "s|";
  33.173 +    static char *kwd_spec[] = { "transaction", "path", NULL };
  33.174 +    static char *arg_spec = "ss";
  33.175      char *path = NULL;
  33.176  
  33.177      struct xs_handle *xh = xshandle(self);
  33.178 @@ -286,12 +320,19 @@ static PyObject *xspy_get_permissions(Py
  33.179      unsigned int perms_n = 0;
  33.180      int i;
  33.181  
  33.182 +    struct xs_transaction_handle *th;
  33.183 +    char *thstr;
  33.184 +
  33.185      if (!xh)
  33.186          goto exit;
  33.187 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  33.188 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  33.189 +                                     &thstr, &path))
  33.190          goto exit;
  33.191 +
  33.192 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  33.193 +
  33.194      Py_BEGIN_ALLOW_THREADS
  33.195 -    perms = xs_get_permissions(xh, path, &perms_n);
  33.196 +    perms = xs_get_permissions(xh, th, path, &perms_n);
  33.197      Py_END_ALLOW_THREADS
  33.198      if (!perms) {
  33.199          PyErr_SetFromErrno(PyExc_RuntimeError);
  33.200 @@ -321,8 +362,8 @@ static PyObject *xspy_get_permissions(Py
  33.201  static PyObject *xspy_set_permissions(PyObject *self, PyObject *args,
  33.202                                        PyObject *kwds)
  33.203  {
  33.204 -    static char *kwd_spec[] = { "path", "perms", NULL };
  33.205 -    static char *arg_spec = "sO";
  33.206 +    static char *kwd_spec[] = { "transaction", "path", "perms", NULL };
  33.207 +    static char *arg_spec = "ssO";
  33.208      char *path = NULL;
  33.209      PyObject *perms = NULL;
  33.210      static char *perm_names[] = { "dom", "read", "write", NULL };
  33.211 @@ -335,11 +376,17 @@ static PyObject *xspy_set_permissions(Py
  33.212      PyObject *tuple0 = NULL;
  33.213      PyObject *val = NULL;
  33.214  
  33.215 +    struct xs_transaction_handle *th;
  33.216 +    char *thstr;
  33.217 +
  33.218      if (!xh)
  33.219          goto exit;
  33.220      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  33.221 -                                     &path, &perms))
  33.222 +                                     &thstr, &path, &perms))
  33.223          goto exit;
  33.224 +
  33.225 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  33.226 +
  33.227      if (!PyList_Check(perms)) {
  33.228          PyErr_SetString(PyExc_RuntimeError, "perms must be a list");
  33.229          goto exit;
  33.230 @@ -369,7 +416,7 @@ static PyObject *xspy_set_permissions(Py
  33.231              xsperms[i].perms |= XS_PERM_WRITE;
  33.232      }
  33.233      Py_BEGIN_ALLOW_THREADS
  33.234 -    xsval = xs_set_permissions(xh, path, xsperms, xsperms_n);
  33.235 +    xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n);
  33.236      Py_END_ALLOW_THREADS
  33.237      if (!xsval) {
  33.238          PyErr_SetFromErrno(PyExc_RuntimeError);
  33.239 @@ -442,9 +489,6 @@ static PyObject *xspy_watch(PyObject *se
  33.240  
  33.241  #define xspy_read_watch_doc "\n"				\
  33.242  	"Read a watch notification.\n"				\
  33.243 -	"The notification must be acknowledged by passing\n"	\
  33.244 -	"the token to acknowledge_watch().\n"			\
  33.245 -	" path [string]: xenstore path.\n"			\
  33.246  	"\n"							\
  33.247  	"Returns: [tuple] (path, token).\n"			\
  33.248  	"Raises RuntimeError on error.\n"			\
  33.249 @@ -495,44 +539,6 @@ static PyObject *xspy_read_watch(PyObjec
  33.250      return val;
  33.251  }
  33.252  
  33.253 -#define xspy_acknowledge_watch_doc "\n"					\
  33.254 -	"Acknowledge a watch notification that has been read.\n"	\
  33.255 -	" token [string] : from the watch notification\n"		\
  33.256 -	"\n"								\
  33.257 -	"Returns None on success.\n"					\
  33.258 -	"Raises RuntimeError on error.\n"				\
  33.259 -	"\n"
  33.260 -
  33.261 -static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args,
  33.262 -                                        PyObject *kwds)
  33.263 -{
  33.264 -    static char *kwd_spec[] = { "token", NULL };
  33.265 -    static char *arg_spec = "O";
  33.266 -    PyObject *token;
  33.267 -    char token_str[MAX_STRLEN(unsigned long) + 1];
  33.268 -
  33.269 -    struct xs_handle *xh = xshandle(self);
  33.270 -    PyObject *val = NULL;
  33.271 -    int xsval = 0;
  33.272 -
  33.273 -    if (!xh)
  33.274 -        goto exit;
  33.275 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token))
  33.276 -        goto exit;
  33.277 -    sprintf(token_str, "%li", (unsigned long)token);
  33.278 -    Py_BEGIN_ALLOW_THREADS
  33.279 -    xsval = xs_acknowledge_watch(xh, token_str);
  33.280 -    Py_END_ALLOW_THREADS
  33.281 -    if (!xsval) {
  33.282 -        PyErr_SetFromErrno(PyExc_RuntimeError);
  33.283 -        goto exit;
  33.284 -    }
  33.285 -    Py_INCREF(Py_None);
  33.286 -    val = Py_None;
  33.287 - exit:
  33.288 -    return val;
  33.289 -}
  33.290 -
  33.291  #define xspy_unwatch_doc "\n"				\
  33.292  	"Stop watching a path.\n"			\
  33.293  	" path  [string] : xenstore path.\n"		\
  33.294 @@ -584,9 +590,8 @@ static PyObject *xspy_unwatch(PyObject *
  33.295  
  33.296  #define xspy_transaction_start_doc "\n"				\
  33.297  	"Start a transaction.\n"				\
  33.298 -	"Only one transaction can be active at a time.\n"	\
  33.299  	"\n"							\
  33.300 -	"Returns None on success.\n"				\
  33.301 +	"Returns transaction handle on success.\n"		\
  33.302  	"Raises RuntimeError on error.\n"			\
  33.303  	"\n"
  33.304  
  33.305 @@ -599,21 +604,23 @@ static PyObject *xspy_transaction_start(
  33.306  
  33.307      struct xs_handle *xh = xshandle(self);
  33.308      PyObject *val = NULL;
  33.309 -    int xsval = 0;
  33.310 +    struct xs_transaction_handle *th;
  33.311 +    char thstr[20];
  33.312  
  33.313      if (!xh)
  33.314          goto exit;
  33.315      if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path))
  33.316          goto exit;
  33.317      Py_BEGIN_ALLOW_THREADS
  33.318 -    xsval = xs_transaction_start(xh);
  33.319 +    th = xs_transaction_start(xh);
  33.320      Py_END_ALLOW_THREADS
  33.321 -    if (!xsval) {
  33.322 +    if (th == NULL) {
  33.323          PyErr_SetFromErrno(PyExc_RuntimeError);
  33.324          goto exit;
  33.325      }
  33.326 -    Py_INCREF(Py_None);
  33.327 -    val = Py_None;
  33.328 +
  33.329 +    sprintf(thstr, "%lX", (unsigned long)th);
  33.330 +    val = PyString_FromString(thstr);
  33.331   exit:
  33.332      return val;
  33.333  }
  33.334 @@ -630,20 +637,27 @@ static PyObject *xspy_transaction_start(
  33.335  static PyObject *xspy_transaction_end(PyObject *self, PyObject *args,
  33.336                                        PyObject *kwds)
  33.337  {
  33.338 -    static char *kwd_spec[] = { "abort", NULL };
  33.339 -    static char *arg_spec = "|i";
  33.340 +    static char *kwd_spec[] = { "transaction", "abort", NULL };
  33.341 +    static char *arg_spec = "s|i";
  33.342      int abort = 0;
  33.343  
  33.344      struct xs_handle *xh = xshandle(self);
  33.345      PyObject *val = NULL;
  33.346      int xsval = 0;
  33.347  
  33.348 +    struct xs_transaction_handle *th;
  33.349 +    char *thstr;
  33.350 +
  33.351      if (!xh)
  33.352          goto exit;
  33.353 -    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort))
  33.354 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec,
  33.355 +                                     &thstr, &abort))
  33.356          goto exit;
  33.357 +
  33.358 +    th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16);
  33.359 +
  33.360      Py_BEGIN_ALLOW_THREADS
  33.361 -    xsval = xs_transaction_end(xh, abort);
  33.362 +    xsval = xs_transaction_end(xh, th, abort);
  33.363      Py_END_ALLOW_THREADS
  33.364      if (!xsval) {
  33.365  	if (errno == EAGAIN) {
  33.366 @@ -833,7 +847,6 @@ static PyMethodDef xshandle_methods[] = 
  33.367       XSPY_METH(set_permissions),
  33.368       XSPY_METH(watch),
  33.369       XSPY_METH(read_watch),
  33.370 -     XSPY_METH(acknowledge_watch),
  33.371       XSPY_METH(unwatch),
  33.372       XSPY_METH(transaction_start),
  33.373       XSPY_METH(transaction_end),
    34.1 --- a/tools/python/xen/util/Brctl.py	Tue Oct 11 15:50:21 2005 -0600
    34.2 +++ b/tools/python/xen/util/Brctl.py	Tue Oct 11 16:57:44 2005 -0600
    34.3 @@ -5,7 +5,6 @@ import os.path
    34.4  import re
    34.5  import sys
    34.6  
    34.7 -os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin'
    34.8  CMD_IFCONFIG = 'ifconfig'
    34.9  CMD_ROUTE    = 'route'
   34.10  CMD_BRCTL    = 'brctl'
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/python/xen/util/asserts.py	Tue Oct 11 16:57:44 2005 -0600
    35.3 @@ -0,0 +1,27 @@
    35.4 +#===========================================================================
    35.5 +# This library is free software; you can redistribute it and/or
    35.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    35.7 +# License as published by the Free Software Foundation.
    35.8 +#
    35.9 +# This library is distributed in the hope that it will be useful,
   35.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   35.12 +# Lesser General Public License for more details.
   35.13 +#
   35.14 +# You should have received a copy of the GNU Lesser General Public
   35.15 +# License along with this library; if not, write to the Free Software
   35.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   35.17 +#============================================================================
   35.18 +# Copyright (C) 2005 XenSource Ltd
   35.19 +#============================================================================
   35.20 +
   35.21 +
   35.22 +def isCharConvertible(c):
   35.23 +    """Assert that the given value is convertible to a character using the %c
   35.24 +    conversion.  This implies that c is either an integer, or a character
   35.25 +    (i.e. a string of length 1).
   35.26 +    """
   35.27 +    
   35.28 +    assert (isinstance(c, int) or
   35.29 +            (isinstance(c, str) and
   35.30 +             len(c) == 1)), "%s is not convertible to a character" % c
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/python/xen/util/auxbin.py	Tue Oct 11 16:57:44 2005 -0600
    36.3 @@ -0,0 +1,44 @@
    36.4 +#============================================================================
    36.5 +# This library is free software; you can redistribute it and/or
    36.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    36.7 +# License as published by the Free Software Foundation.
    36.8 +#
    36.9 +# This library is distributed in the hope that it will be useful,
   36.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   36.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   36.12 +# Lesser General Public License for more details.
   36.13 +#
   36.14 +# You should have received a copy of the GNU Lesser General Public
   36.15 +# License along with this library; if not, write to the Free Software
   36.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   36.17 +#============================================================================
   36.18 +# Copyright (C) 2005 XenSource Ltd
   36.19 +#============================================================================
   36.20 +
   36.21 +
   36.22 +LIB_BIN_32 = "/usr/lib/xen/bin"
   36.23 +LIB_BIN_64 = "/usr/lib64/xen/bin"
   36.24 +
   36.25 +
   36.26 +import os
   36.27 +import os.path
   36.28 +
   36.29 +
   36.30 +def execute(exe, args = None):
   36.31 +    exepath = pathTo(exe)
   36.32 +    a = [ exepath ]
   36.33 +    if args:
   36.34 +        a.extend(args)
   36.35 +    os.execv(exepath, a)
   36.36 +
   36.37 +
   36.38 +def pathTo(exe):
   36.39 +    return os.path.join(path(), exe)
   36.40 +
   36.41 +
   36.42 +def path():
   36.43 +    machine = os.uname()[4]
   36.44 +    if machine.find('64') != -1 and os.path.exists(LIB_BIN_64):
   36.45 +        return LIB_BIN_64
   36.46 +    else:
   36.47 +        return LIB_BIN_32
    37.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Tue Oct 11 15:50:21 2005 -0600
    37.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Tue Oct 11 16:57:44 2005 -0600
    37.3 @@ -14,6 +14,8 @@ from struct import pack, unpack, calcsiz
    37.4  
    37.5  from xen.util.xpopen import xPopen3
    37.6  
    37.7 +import xen.util.auxbin
    37.8 +
    37.9  import xen.lowlevel.xc
   37.10  
   37.11  from xen.xend.xenstore.xsutil import IntroduceDomain
   37.12 @@ -21,9 +23,11 @@ from xen.xend.xenstore.xsutil import Int
   37.13  from XendError import XendError
   37.14  from XendLogging import log
   37.15  
   37.16 +
   37.17  SIGNATURE = "LinuxGuestRecord"
   37.18 -PATH_XC_SAVE = "/usr/libexec/xen/xc_save"
   37.19 -PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore"
   37.20 +XC_SAVE = "xc_save"
   37.21 +XC_RESTORE = "xc_restore"
   37.22 +
   37.23  
   37.24  sizeof_int = calcsize("i")
   37.25  sizeof_unsigned_long = calcsize("L")
   37.26 @@ -64,7 +68,7 @@ def save(fd, dominfo, live):
   37.27          # enabled. Passing "0" simply uses the defaults compiled into
   37.28          # libxenguest; see the comments and/or code in xc_linux_save() for
   37.29          # more information.
   37.30 -        cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd),
   37.31 +        cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(xc.handle()), str(fd),
   37.32                 str(dominfo.getDomid()), "0", "0", str(int(live)) ]
   37.33          log.debug("[xc_save]: %s", string.join(cmd))
   37.34  
   37.35 @@ -129,7 +133,7 @@ def restore(xd, fd):
   37.36          store_evtchn = dominfo.store_channel
   37.37          console_evtchn = dominfo.console_channel
   37.38  
   37.39 -        cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd),
   37.40 +        cmd = [xen.util.auxbin.pathTo(XC_RESTORE), str(xc.handle()), str(fd),
   37.41                 str(dominfo.getDomid()), str(nr_pfns),
   37.42                 str(store_evtchn), str(console_evtchn)]
   37.43          log.debug("[xc_restore]: %s", string.join(cmd))
    38.1 --- a/tools/python/xen/xend/XendClient.py	Tue Oct 11 15:50:21 2005 -0600
    38.2 +++ b/tools/python/xen/xend/XendClient.py	Tue Oct 11 16:57:44 2005 -0600
    38.3 @@ -196,6 +196,9 @@ class Xend:
    38.4      def xend_domains(self):
    38.5          return self.xendGet(self.domainurl())
    38.6  
    38.7 +    def xend_list_domains(self):
    38.8 +        return self.xendGet(self.domainurl(), {'detail': '1'})
    38.9 +
   38.10      def xend_domain_create(self, conf):
   38.11          return self.xendPost(self.domainurl(),
   38.12                               {'op'      : 'create',
    39.1 --- a/tools/python/xen/xend/XendDomain.py	Tue Oct 11 15:50:21 2005 -0600
    39.2 +++ b/tools/python/xen/xend/XendDomain.py	Tue Oct 11 16:57:44 2005 -0600
    39.3 @@ -359,20 +359,6 @@ class XendDomain:
    39.4              raise XendError(str(ex))
    39.5  
    39.6  
    39.7 -    def domain_shutdown(self, domid, reason = 'poweroff'):
    39.8 -        """Shutdown domain (nicely).
    39.9 -
   39.10 -        @param reason: shutdown reason: poweroff, reboot, suspend, halt
   39.11 -        """
   39.12 -        self.callInfo(domid, XendDomainInfo.XendDomainInfo.shutdown, reason)
   39.13 -
   39.14 -
   39.15 -    def domain_sysrq(self, domid, key):
   39.16 -        """Send a SysRq to the specified domain."""
   39.17 -        return self.callInfo(domid, XendDomainInfo.XendDomainInfo.send_sysrq,
   39.18 -                             key)
   39.19 -
   39.20 -
   39.21      def domain_destroy(self, domid):
   39.22          """Terminate domain immediately."""
   39.23  
   39.24 @@ -475,37 +461,6 @@ class XendDomain:
   39.25              raise XendError(str(ex))
   39.26  
   39.27  
   39.28 -    def domain_device_create(self, domid, devconfig):
   39.29 -        """Create a new device for the specified domain.
   39.30 -        """
   39.31 -        return self.callInfo(domid,
   39.32 -                             XendDomainInfo.XendDomainInfo.device_create,
   39.33 -                             devconfig)
   39.34 -
   39.35 -
   39.36 -    def domain_device_configure(self, domid, devconfig, devid):
   39.37 -        """Configure an existing device in the specified domain.
   39.38 -        @return: updated device configuration
   39.39 -        """
   39.40 -        return self.callInfo(domid,
   39.41 -                             XendDomainInfo.XendDomainInfo.device_configure,
   39.42 -                             devconfig, devid)
   39.43 -
   39.44 -    
   39.45 -    def domain_device_destroy(self, domid, devtype, devid):
   39.46 -        """Destroy a device."""
   39.47 -        return self.callInfo(domid,
   39.48 -                             XendDomainInfo.XendDomainInfo.destroyDevice,
   39.49 -                             devtype, devid)
   39.50 -
   39.51 -
   39.52 -    def domain_devtype_ls(self, domid, devtype):
   39.53 -        """Get list of device sxprs for the specified domain."""
   39.54 -        return self.callInfo(domid,
   39.55 -                             XendDomainInfo.XendDomainInfo.getDeviceSxprs,
   39.56 -                             devtype)
   39.57 -
   39.58 -
   39.59      def domain_vif_limit_set(self, domid, vif, credit, period):
   39.60          """Limit the vif's transmission rate
   39.61          """
   39.62 @@ -537,44 +492,6 @@ class XendDomain:
   39.63          except Exception, ex:
   39.64              raise XendError(str(ex))
   39.65  
   39.66 -    def domain_mem_target_set(self, domid, mem):
   39.67 -        """Set the memory target for a domain.
   39.68 -
   39.69 -        @param mem: memory target (in MiB)
   39.70 -        """
   39.71 -        self.callInfo(domid, XendDomainInfo.XendDomainInfo.setMemoryTarget,
   39.72 -                      mem << 10)
   39.73 -
   39.74 -
   39.75 -    def domain_vcpu_hotplug(self, domid, vcpu, state):
   39.76 -        """Enable or disable specified VCPU in specified domain
   39.77 -
   39.78 -        @param vcpu: target VCPU in domain
   39.79 -        @param state: which state VCPU will become
   39.80 -        """
   39.81 -        self.callInfo(domid, XendDomainInfo.XendDomainInfo.vcpu_hotplug, vcpu,
   39.82 -                      state)
   39.83 -
   39.84 -
   39.85 -    def domain_dumpcore(self, domid):
   39.86 -        """Save a core dump for a crashed domain."""
   39.87 -        self.callInfo(domid, XendDomainInfo.XendDomainInfo.dumpCore)
   39.88 -
   39.89 -
   39.90 -    ## private:
   39.91 -
   39.92 -    def callInfo(self, domid, fn, *args, **kwargs):
   39.93 -        try:
   39.94 -            self.refresh()
   39.95 -            dominfo = self.domains.get(domid)
   39.96 -            if dominfo:
   39.97 -                return fn(dominfo, *args, **kwargs)
   39.98 -        except XendError:
   39.99 -            raise
  39.100 -        except Exception, exn:
  39.101 -            log.exception("")
  39.102 -            raise XendError(str(exn))
  39.103 -
  39.104  
  39.105  def instance():
  39.106      """Singleton constructor. Use this instead of the class constructor.
    40.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Oct 11 15:50:21 2005 -0600
    40.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Oct 11 16:57:44 2005 -0600
    40.3 @@ -30,6 +30,7 @@ import threading
    40.4  import errno
    40.5  
    40.6  import xen.lowlevel.xc
    40.7 +from xen.util import asserts
    40.8  from xen.util.blkif import blkdev_uname_to_file
    40.9  
   40.10  from xen.xend import image
   40.11 @@ -41,7 +42,8 @@ from xen.xend.XendLogging import log
   40.12  from xen.xend.XendError import XendError, VmError
   40.13  from xen.xend.XendRoot import get_component
   40.14  
   40.15 -from xen.xend.uuid import getUuid
   40.16 +from uuid import getUuid
   40.17 +
   40.18  from xen.xend.xenstore.xstransact import xstransact
   40.19  from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain
   40.20  
   40.21 @@ -217,17 +219,12 @@ def recreate(xeninfo):
   40.22  def restore(config):
   40.23      """Create a domain and a VM object to do a restore.
   40.24  
   40.25 -    @param config:    domain configuration
   40.26 +    @param config: domain configuration
   40.27      """
   40.28  
   40.29      log.debug("XendDomainInfo.restore(%s)", config)
   40.30  
   40.31 -    try:
   40.32 -        uuid    =     sxp.child_value(config, 'uuid')
   40.33 -        ssidref = int(sxp.child_value(config, 'ssidref'))
   40.34 -    except TypeError, exn:
   40.35 -        raise VmError('Invalid ssidref in config: %s' % exn)
   40.36 -
   40.37 +    uuid = sxp.child_value(config, 'uuid')
   40.38      vm = XendDomainInfo(uuid, parseConfig(config))
   40.39      try:
   40.40          vm.construct()
   40.41 @@ -257,7 +254,7 @@ def parseConfig(config):
   40.42              return val
   40.43  
   40.44  
   40.45 -    log.debug("parseConfig: config is %s" % str(config))
   40.46 +    log.debug("parseConfig: config is %s", config)
   40.47  
   40.48      result = {}
   40.49  
   40.50 @@ -315,7 +312,7 @@ def parseConfig(config):
   40.51              log.warn("Ignoring malformed and deprecated config option "
   40.52                       "restart = %s", restart)
   40.53  
   40.54 -    log.debug("parseConfig: result is %s" % str(result))
   40.55 +    log.debug("parseConfig: result is %s", result)
   40.56      return result
   40.57  
   40.58  
   40.59 @@ -529,7 +526,7 @@ class XendDomainInfo:
   40.60  
   40.61          except KeyError, exn:
   40.62              log.exception(exn)
   40.63 -            raise VmError('Unspecified domain detail: %s' % str(exn))
   40.64 +            raise VmError('Unspecified domain detail: %s' % exn)
   40.65  
   40.66  
   40.67      def readVm(self, *args):
   40.68 @@ -579,7 +576,7 @@ class XendDomainInfo:
   40.69              if self.infoIsSet(k):
   40.70                  to_store[k] = str(self.info[k])
   40.71  
   40.72 -        log.debug("Storing VM details: %s" % str(to_store))
   40.73 +        log.debug("Storing VM details: %s", to_store)
   40.74  
   40.75          self.writeVm(to_store)
   40.76  
   40.77 @@ -605,7 +602,7 @@ class XendDomainInfo:
   40.78          for v in range(0, self.info['vcpus']):
   40.79              to_store["cpu/%d/availability" % v] = availability(v)
   40.80  
   40.81 -        log.debug("Storing domain details: %s" % str(to_store))
   40.82 +        log.debug("Storing domain details: %s", to_store)
   40.83  
   40.84          self.writeDom(to_store)
   40.85  
   40.86 @@ -746,7 +743,7 @@ class XendDomainInfo:
   40.87  
   40.88      def shutdown(self, reason):
   40.89          if not reason in shutdown_reasons.values():
   40.90 -            raise XendError('invalid reason:' + reason)
   40.91 +            raise XendError('Invalid reason: %s' % reason)
   40.92          self.storeDom("control/shutdown", reason)
   40.93          if reason != 'suspend':
   40.94              self.storeDom('xend/shutdown_start_time', time.time())
   40.95 @@ -793,10 +790,12 @@ class XendDomainInfo:
   40.96  
   40.97      def setMemoryTarget(self, target):
   40.98          """Set the memory target of this domain.
   40.99 -        @param target In KiB.
  40.100 +        @param target In MiB.
  40.101          """
  40.102 -        self.info['memory_KiB'] = target
  40.103 -        self.storeDom("memory/target", target)
  40.104 +        # Internally we use KiB, but the command interface uses MiB.
  40.105 +        t = target << 10
  40.106 +        self.info['memory_KiB'] = t
  40.107 +        self.storeDom("memory/target", t)
  40.108  
  40.109  
  40.110      def update(self, info = None):
  40.111 @@ -986,8 +985,8 @@ class XendDomainInfo:
  40.112          """
  40.113  
  40.114          log.debug('XendDomainInfo.construct: %s %s',
  40.115 -                  str(self.domid),
  40.116 -                  str(self.info['ssidref']))
  40.117 +                  self.domid,
  40.118 +                  self.info['ssidref'])
  40.119  
  40.120          self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref'])
  40.121  
  40.122 @@ -1004,9 +1003,9 @@ class XendDomainInfo:
  40.123  
  40.124      def initDomain(self):
  40.125          log.debug('XendDomainInfo.initDomain: %s %s %s',
  40.126 -                  str(self.domid),
  40.127 -                  str(self.info['memory_KiB']),
  40.128 -                  str(self.info['cpu_weight']))
  40.129 +                  self.domid,
  40.130 +                  self.info['memory_KiB'],
  40.131 +                  self.info['cpu_weight'])
  40.132  
  40.133          if not self.infoIsSet('image'):
  40.134              raise VmError('Missing image in configuration')
  40.135 @@ -1085,14 +1084,15 @@ class XendDomainInfo:
  40.136      def destroy(self):
  40.137          """Cleanup VM and destroy domain.  Nothrow guarantee."""
  40.138  
  40.139 -        log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid))
  40.140 +        log.debug("XendDomainInfo.destroy: domid=%s", self.domid)
  40.141  
  40.142          self.cleanupVm()
  40.143 -        self.destroyDomain()
  40.144 +        if self.dompath is not None:
  40.145 +                self.destroyDomain()
  40.146  
  40.147  
  40.148      def destroyDomain(self):
  40.149 -        log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid))
  40.150 +        log.debug("XendDomainInfo.destroyDomain(%s)", self.domid)
  40.151  
  40.152          try:
  40.153              if self.domid is not None:
  40.154 @@ -1366,7 +1366,10 @@ class XendDomainInfo:
  40.155          self.storeVm('vcpu_avail', self.info['vcpu_avail'])
  40.156          self.storeDom("cpu/%d/availability" % vcpu, availability)
  40.157  
  40.158 -    def send_sysrq(self, key=0):
  40.159 +
  40.160 +    def send_sysrq(self, key):
  40.161 +        asserts.isCharConvertible(key)
  40.162 +
  40.163          self.storeDom("control/sysrq", '%c' % key)
  40.164  
  40.165  
  40.166 @@ -1388,18 +1391,18 @@ class XendDomainInfo:
  40.167          dom = 0
  40.168          # get max number of vcpus to use for dom0 from config
  40.169          target = int(xroot.get_dom0_vcpus())
  40.170 -        log.debug("number of vcpus to use is %d" % (target))
  40.171 +        log.debug("number of vcpus to use is %d", target)
  40.172     
  40.173          # target = 0 means use all processors
  40.174          if target > 0:
  40.175              # count the number of online vcpus (cpu values in v2c map >= 0)
  40.176              vcpu_to_cpu = dom_get(dom)['vcpu_to_cpu']
  40.177              vcpus_online = len(filter(lambda x: x >= 0, vcpu_to_cpu))
  40.178 -            log.debug("found %d vcpus online" % (vcpus_online))
  40.179 +            log.debug("found %d vcpus online", vcpus_online)
  40.180  
  40.181              # disable any extra vcpus that are online over the requested target
  40.182              for vcpu in range(target, vcpus_online):
  40.183 -                log.info("enforcement is disabling DOM%d VCPU%d" % (dom, vcpu))
  40.184 +                log.info("enforcement is disabling DOM%d VCPU%d", dom, vcpu)
  40.185                  self.vcpu_hotplug(vcpu, 0)
  40.186  
  40.187  
    41.1 --- a/tools/python/xen/xend/XendLogging.py	Tue Oct 11 15:50:21 2005 -0600
    41.2 +++ b/tools/python/xen/xend/XendLogging.py	Tue Oct 11 16:57:44 2005 -0600
    41.3 @@ -13,79 +13,84 @@
    41.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    41.5  #============================================================================
    41.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    41.7 +# Copyright (C) 2005 XenSource Ltd
    41.8  #============================================================================
    41.9  
   41.10 +
   41.11 +import tempfile
   41.12  import types
   41.13  import logging
   41.14 -from logging import Formatter, StreamHandler
   41.15 -from logging.handlers import RotatingFileHandler
   41.16 -
   41.17 -class XendLogging:
   41.18 -
   41.19 -    KB = 1024
   41.20 -    MB = 1024 * KB
   41.21 -    
   41.22 -    maxBytes = 1 * MB
   41.23 -    backupCount = 5
   41.24 -
   41.25 -    logStderrFormat = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
   41.26 -    logFileFormat   = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
   41.27 -    dateFormat = "%Y-%m-%d %H:%M:%S"
   41.28 -
   41.29 -    def __init__(self, filename, level=logging.INFO, maxBytes=None, backupCount=None):
   41.30 -        """Initialise logging. Logs to 'filename' by default, but does not log to
   41.31 -        stderr unless addLogStderr() is called.
   41.32 -        """
   41.33 -        self.setLevel(level)
   41.34 -        if maxBytes:
   41.35 -            self.maxBytes = maxBytes
   41.36 -        if backupCount:
   41.37 -            self.backupCount = backupCount
   41.38 -        self.initLogFile(filename)
   41.39 -        self.initLogStderr()
   41.40 -
   41.41 -    def setLevel(self, level):
   41.42 -        if isinstance(level, types.StringType):
   41.43 -            level = logging._levelNames[level]
   41.44 -        self.getLogger().setLevel(level)
   41.45 -        self.level = level
   41.46 +import logging.handlers
   41.47  
   41.48 -    def getLogger(self):
   41.49 -        return logging.getLogger("xend")
   41.50 -
   41.51 -    def initLogFile(self, filename):
   41.52 -        """Create the file logger and add it.
   41.53 -        """
   41.54 -        self.logfile = RotatingFileHandler(filename,
   41.55 -                                           mode='a',
   41.56 -                                           maxBytes=self.maxBytes,
   41.57 -                                           backupCount=self.backupCount)
   41.58 -        self.logfilename = filename
   41.59 -        self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat))
   41.60 -        self.getLogger().addHandler(self.logfile)
   41.61 -
   41.62 -    def getLogFile(self):
   41.63 -        return self.logfile
   41.64  
   41.65 -    def getLogFilename(self):
   41.66 -        return self.logfilename
   41.67 -
   41.68 -    def initLogStderr(self):
   41.69 -        """Create the stderr logger, but don't add it.
   41.70 -        """
   41.71 -        self.logstderr = StreamHandler()
   41.72 -        self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat))
   41.73 +__all__ = [ 'log', 'init', 'getLogFilename', 'addLogStderr',
   41.74 +            'removeLogStderr' ]
   41.75  
   41.76 -    def addLogStderr(self):
   41.77 -        """Add logging to stderr."""
   41.78 -        self.getLogger().addHandler(self.logstderr)
   41.79 -
   41.80 -    def removeLogStderr(self):
   41.81 -        """Remove logging to stderr."""
   41.82 -        self.getLogger().removeHandler(self.logstderr)
   41.83 -        
   41.84 -    def getLogStderr(self):
   41.85 -        return self.logstderr
   41.86  
   41.87  log = logging.getLogger("xend")
   41.88 -    
   41.89 +
   41.90 +
   41.91 +DEFAULT_MAX_BYTES = 1 << 20  # 1MB
   41.92 +DEFAULT_BACKUP_COUNT = 5
   41.93 +
   41.94 +STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
   41.95 +LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s"
   41.96 +DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
   41.97 +
   41.98 +
   41.99 +stderrHandler = logging.StreamHandler()
  41.100 +stderrHandler.setFormatter(logging.Formatter(STDERR_FORMAT, DATE_FORMAT))
  41.101 +
  41.102 +logfilename = None
  41.103 +
  41.104 +
  41.105 +def init(filename, level=logging.INFO, maxBytes=None, backupCount=None):
  41.106 +    """Initialise logging. Logs to 'filename' by default, but does not log to
  41.107 +    stderr unless addLogStderr() is called.
  41.108 +    """
  41.109 +
  41.110 +    global logfilename
  41.111 +
  41.112 +    def openFileHandler(fname):
  41.113 +        return logging.handlers.RotatingFileHandler(fname,
  41.114 +                                                    mode='a',
  41.115 +                                                    maxBytes=maxBytes,
  41.116 +                                                    backupCount=backupCount)
  41.117 +
  41.118 +    if not maxBytes:
  41.119 +        maxBytes = DEFAULT_MAX_BYTES
  41.120 +    if not backupCount:
  41.121 +        backupCount = DEFAULT_BACKUP_COUNT
  41.122 +
  41.123 +    # Rather unintuitively, getLevelName will get the number corresponding to
  41.124 +    # a level name, as well as getting the name corresponding to a level
  41.125 +    # number.  setLevel seems to take the number only though, so convert if we
  41.126 +    # are given a string.
  41.127 +    if isinstance(level, types.StringType):
  41.128 +        level = logging.getLevelName(level)
  41.129 +
  41.130 +    log.setLevel(level)
  41.131 +
  41.132 +    try:
  41.133 +        fileHandler = openFileHandler(filename)
  41.134 +        logfilename = filename
  41.135 +    except IOError:
  41.136 +        logfilename = tempfile.mkstemp("-xend.log")[1]
  41.137 +        fileHandler = openFileHandler(logfilename)
  41.138 +
  41.139 +    fileHandler.setFormatter(logging.Formatter(LOGFILE_FORMAT, DATE_FORMAT))
  41.140 +    log.addHandler(fileHandler)
  41.141 +
  41.142 +
  41.143 +def getLogFilename():
  41.144 +    return logfilename
  41.145 +
  41.146 +
  41.147 +def addLogStderr():
  41.148 +    """Add logging to stderr."""
  41.149 +    log.addHandler(stderrHandler)
  41.150 +
  41.151 +
  41.152 +def removeLogStderr():
  41.153 +    """Remove logging to stderr."""
  41.154 +    log.removeHandler(stderrHandler)
    42.1 --- a/tools/python/xen/xend/XendRoot.py	Tue Oct 11 15:50:21 2005 -0600
    42.2 +++ b/tools/python/xen/xend/XendRoot.py	Tue Oct 11 16:57:44 2005 -0600
    42.3 @@ -13,6 +13,7 @@
    42.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    42.5  #============================================================================
    42.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    42.7 +# Copyright (C) 2005 XenSource Ltd
    42.8  #============================================================================
    42.9  
   42.10  """Xend root class.
   42.11 @@ -29,7 +30,7 @@ import os.path
   42.12  import string
   42.13  import sys
   42.14  
   42.15 -from XendLogging import XendLogging
   42.16 +import XendLogging
   42.17  from XendError import XendError
   42.18  
   42.19  import sxp
   42.20 @@ -92,7 +93,6 @@ class XendRoot:
   42.21      def __init__(self):
   42.22          self.config_path = None
   42.23          self.config = None
   42.24 -        self.logging = None
   42.25          self.configure()
   42.26  
   42.27  
   42.28 @@ -114,84 +114,22 @@ class XendRoot:
   42.29          """
   42.30          return self.components.get(name)
   42.31  
   42.32 -    def _format(self, msg, args):
   42.33 -        if args:
   42.34 -            return str(msg) % args
   42.35 -        else:
   42.36 -            return str(msg)
   42.37 -
   42.38 -    def _log(self, mode, fmt, args):
   42.39 -        """Logging function that uses the logger if it exists, otherwise
   42.40 -        logs to stderr. We use this for XendRoot log messages because
   42.41 -        they may be logged before the logger has been configured.
   42.42 -        Other components can safely use the logger.
   42.43 -        """
   42.44 -        log = self.get_logger()
   42.45 -        if mode not in ['warning', 'info', 'debug', 'error']:
   42.46 -            mode = 'info'
   42.47 -        level = mode.upper()
   42.48 -        if log:
   42.49 -            getattr(log, mode)(fmt, *args)
   42.50 -        else:
   42.51 -            print >>sys.stderr, "xend", "[%s]" % level, self._format(fmt, args)
   42.52 -
   42.53 -    def logDebug(self, fmt, *args):
   42.54 -        """Log a debug message.
   42.55 -
   42.56 -        @param fmt: message format
   42.57 -        @param args: arguments
   42.58 +    def _logError(self, fmt, args):
   42.59 +        """Logging function to log to stderr. We use this for XendRoot log
   42.60 +        messages because they may be logged before the logger has been
   42.61 +        configured.  Other components can safely use the logger.
   42.62          """
   42.63 -        self._log('debug', fmt, args)
   42.64 -        
   42.65 -    def logInfo(self, fmt, *args):
   42.66 -        """Log an info message.
   42.67 -
   42.68 -        @param fmt: message format
   42.69 -        @param args: arguments
   42.70 -        """
   42.71 -        self._log('info', fmt, args)
   42.72 -
   42.73 -    def logWarning(self, fmt, *args):
   42.74 -        """Log a warning message.
   42.75 -
   42.76 -        @param fmt: message format
   42.77 -        @param args: arguments
   42.78 -        """
   42.79 -        self._log('warning', fmt, args)
   42.80 -        
   42.81 -    def logError(self, fmt, *args):
   42.82 -        """Log an error message.
   42.83 -
   42.84 -        @param fmt: message format
   42.85 -        @param args: arguments
   42.86 -        """
   42.87 -        self._log('error', fmt, args)
   42.88 -        
   42.89 -    def event_handler(self, event, val):
   42.90 -        self.logInfo("EVENT> %s %s", str(event), str(val))
   42.91 +        print >>sys.stderr, "xend [ERROR]", fmt % args
   42.92  
   42.93      def configure(self):
   42.94          self.set_config()
   42.95 -        self.configure_logger()
   42.96 -
   42.97 -    def configure_logger(self):
   42.98          logfile = self.get_config_value("logfile", self.logfile_default)
   42.99          loglevel = self.get_config_value("loglevel", self.loglevel_default)
  42.100 -        self.logging = XendLogging(logfile, level=loglevel)
  42.101 +        XendLogging.init(logfile, level = loglevel)
  42.102  
  42.103          from xen.xend.server import params
  42.104          if params.XEND_DEBUG:
  42.105 -            self.logging.addLogStderr()
  42.106 -
  42.107 -    def get_logging(self):
  42.108 -        """Get the XendLogging instance.
  42.109 -        """
  42.110 -        return self.logging
  42.111 -
  42.112 -    def get_logger(self):
  42.113 -        """Get the logger.
  42.114 -        """
  42.115 -        return self.logging and self.logging.getLogger()
  42.116 +            XendLogging.addLogStderr()
  42.117  
  42.118      def set_config(self):
  42.119          """If the config file exists, read it. If not, ignore it.
  42.120 @@ -200,7 +138,6 @@ class XendRoot:
  42.121          """
  42.122          self.config_path = os.getenv(self.config_var, self.config_default)
  42.123          if os.path.exists(self.config_path):
  42.124 -            #self.logInfo('Reading config file %s', self.config_path)
  42.125              try:
  42.126                  fin = file(self.config_path, 'rb')
  42.127                  try:
  42.128 @@ -210,10 +147,12 @@ class XendRoot:
  42.129                  config.insert(0, 'xend-config')
  42.130                  self.config = config
  42.131              except Exception, ex:
  42.132 -                self.logError('Reading config file %s: %s', self.config_path, str(ex))
  42.133 +                self._logError('Reading config file %s: %s',
  42.134 +                               self.config_path, str(ex))
  42.135                  raise
  42.136          else:
  42.137 -            self.logError('Config file does not exist: %s', self.config_path)
  42.138 +            self._logError('Config file does not exist: %s',
  42.139 +                           self.config_path)
  42.140              self.config = ['xend-config']
  42.141  
  42.142      def get_config(self, name=None):
  42.143 @@ -339,11 +278,6 @@ def instance():
  42.144          inst = XendRoot()
  42.145      return inst
  42.146  
  42.147 -def logger():
  42.148 -    """Get the logger.
  42.149 -    """
  42.150 -    return instance().get_logger()
  42.151 -
  42.152  def add_component(name, val):
  42.153      """Register a component with XendRoot.
  42.154      This is used to work-round import cycles.
    43.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Tue Oct 11 15:50:21 2005 -0600
    43.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Tue Oct 11 16:57:44 2005 -0600
    43.3 @@ -38,7 +38,7 @@ class Daemon:
    43.4          pythonex = '(?P<python>\S*python\S*)'
    43.5          cmdex = '(?P<cmd>.*)'
    43.6          procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$')
    43.7 -        xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$')
    43.8 +        xendre = re.compile('^\S+/xend\s*(start|restart)\s*.*$')
    43.9          procs = os.popen('ps -e -o pid,args 2>/dev/null')
   43.10          for proc in procs:
   43.11              pm = procre.match(proc)
    44.1 --- a/tools/python/xen/xend/server/SrvDomain.py	Tue Oct 11 15:50:21 2005 -0600
    44.2 +++ b/tools/python/xen/xend/server/SrvDomain.py	Tue Oct 11 16:57:44 2005 -0600
    44.3 @@ -51,40 +51,28 @@ class SrvDomain(SrvDir):
    44.4          val = self.xd.domain_pause(self.dom.domid)
    44.5          return val
    44.6  
    44.7 -    def op_shutdown(self, op, req):
    44.8 -        fn = FormFn(self.xd.domain_shutdown,
    44.9 -                    [['dom',    'int'],
   44.10 -                     ['reason', 'str']])
   44.11 -        val = fn(req.args, {'dom': self.dom.domid})
   44.12 +    def acceptCommand(self, req):
   44.13          req.setResponseCode(http.ACCEPTED)
   44.14          req.setHeader("Location", "%s/.." % req.prePathURL())
   44.15 -        return val
   44.16 +
   44.17 +    def op_shutdown(self, op, req):
   44.18 +        self.acceptCommand(req)
   44.19 +        return self.dom.shutdown(req.args['reason'][0])
   44.20  
   44.21      def op_sysrq(self, op, req):
   44.22 -        fn = FormFn(self.xd.domain_sysrq,
   44.23 -                    [['dom',    'int'],
   44.24 -                     ['key',    'int']])
   44.25 -        val = fn(req.args, {'dom' : self.dom.domid})
   44.26 -        req.setResponseCode(http.ACCEPTED)
   44.27 -        req.setHeader("Location", "%s/.." % req.prePathURL())
   44.28 -        return val
   44.29 +        self.acceptCommand(req)
   44.30 +        return self.dom.send_sysrq(int(req.args['key'][0]))
   44.31  
   44.32      def op_destroy(self, op, req):
   44.33 -        fn = FormFn(self.xd.domain_destroy,
   44.34 -                    [['dom',    'int']])
   44.35 -        val = fn(req.args, {'dom': self.dom.domid})
   44.36 -        req.setHeader("Location", "%s/.." % req.prePathURL())
   44.37 -        return val
   44.38 +        self.acceptCommand(req)
   44.39 +        return self.xd.domain_destroy(self.dom.domid)
   44.40  
   44.41      def op_save(self, op, req):
   44.42 +        self.acceptCommand(req)
   44.43          return req.threadRequest(self.do_save, op, req)
   44.44  
   44.45      def do_save(self, op, req):
   44.46 -        fn = FormFn(self.xd.domain_save,
   44.47 -                    [['dom',  'int'],
   44.48 -                     ['file', 'str']])
   44.49 -        val = fn(req.args, {'dom': self.dom.domid})
   44.50 -        return 0
   44.51 +        return self.xd.domain_save(self.dom.domid, req.args['file'][0])
   44.52  
   44.53      def op_migrate(self, op, req):
   44.54          return req.threadRequest(self.do_migrate, op, req)
   44.55 @@ -134,43 +122,39 @@ class SrvDomain(SrvDir):
   44.56                       ['memory', 'int']])
   44.57          val = fn(req.args, {'dom': self.dom.domid})
   44.58          return val
   44.59 +
   44.60      
   44.61 +    def call(self, fn, args, req):
   44.62 +        return FormFn(fn, args)(req.args)
   44.63 +
   44.64 +
   44.65      def op_mem_target_set(self, op, req):
   44.66 -        fn = FormFn(self.xd.domain_mem_target_set,
   44.67 -                    [['dom',    'int'],
   44.68 -                     ['target', 'int']])
   44.69 -        val = fn(req.args, {'dom': self.dom.domid})
   44.70 -        return val
   44.71 +        return self.call(self.dom.setMemoryTarget,
   44.72 +                         [['target', 'int']],
   44.73 +                         req)
   44.74  
   44.75      def op_devices(self, op, req):
   44.76 -        fn = FormFn(self.xd.domain_devtype_ls,
   44.77 -                    [['dom',    'int'],
   44.78 -                     ['type',   'str']])
   44.79 -        val = fn(req.args, {'dom': self.dom.domid})
   44.80 -        return val
   44.81 +        return self.call(self.dom.getDeviceSxprs,
   44.82 +                         [['type', 'str']],
   44.83 +                         req)
   44.84  
   44.85      def op_device_create(self, op, req):
   44.86 -        fn = FormFn(self.xd.domain_device_create,
   44.87 -                    [['dom',    'int'],
   44.88 -                     ['config', 'sxpr']])
   44.89 -        val = fn(req.args, {'dom': self.dom.domid})
   44.90 -        return val
   44.91 +        return self.call(self.dom.device_create,
   44.92 +                         [['config', 'sxpr']],
   44.93 +                         req)
   44.94  
   44.95      def op_device_destroy(self, op, req):
   44.96 -        fn = FormFn(self.xd.domain_device_destroy,
   44.97 -                    [['dom',  'int'],
   44.98 -                     ['type', 'str'],
   44.99 -                     ['dev',  'str']])
  44.100 -        val = fn(req.args, {'dom': self.dom.domid})
  44.101 -        return val
  44.102 +        return self.call(self.dom.destroyDevice,
  44.103 +                         [['type', 'str'],
  44.104 +                          ['dev',  'int']],
  44.105 +                         req)
  44.106                  
  44.107      def op_device_configure(self, op, req):
  44.108 -        fn = FormFn(self.xd.domain_device_configure,
  44.109 -                    [['dom',    'int'],
  44.110 -                     ['config', 'sxpr'],
  44.111 -                     ['dev',    'str']])
  44.112 -        val = fn(req.args, {'dom': self.dom.domid})
  44.113 -        return val
  44.114 +        return self.call(self.dom.device_configure,
  44.115 +                         [['config', 'sxpr'],
  44.116 +                          ['dev',    'int']],
  44.117 +                         req)
  44.118 +
  44.119  
  44.120      def op_vif_limit_set(self, op, req):
  44.121          fn = FormFn(self.xd.domain_vif_limit_set,
  44.122 @@ -182,12 +166,10 @@ class SrvDomain(SrvDir):
  44.123          return val
  44.124  
  44.125      def op_vcpu_hotplug(self, op, req):
  44.126 -        fn = FormFn(self.xd.domain_vcpu_hotplug,
  44.127 -                    [['dom', 'int'],
  44.128 -                     ['vcpu', 'int'],
  44.129 -                     ['state', 'int']])
  44.130 -        val = fn(req.args, {'dom': self.dom.domid})
  44.131 -        return val
  44.132 +        return self.call(self.dom.vcpu_hotplug,
  44.133 +                         [['vcpu', 'int'],
  44.134 +                          ['state', 'int']],
  44.135 +                         req)
  44.136  
  44.137      def render_POST(self, req):
  44.138          return self.perform(req)
  44.139 @@ -201,7 +183,6 @@ class SrvDomain(SrvDir):
  44.140          #
  44.141          # if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']:
  44.142          #    return self.perform(req)
  44.143 -        self.dom.update()
  44.144          if self.use_sxp(req):
  44.145              req.setHeader("Content-Type", sxp.mime_type)
  44.146              sxp.show(self.dom.sxpr(), out=req)
    45.1 --- a/tools/python/xen/xend/server/SrvDomainDir.py	Tue Oct 11 15:50:21 2005 -0600
    45.2 +++ b/tools/python/xen/xend/server/SrvDomainDir.py	Tue Oct 11 16:57:44 2005 -0600
    45.3 @@ -22,6 +22,7 @@ from xen.web import http
    45.4  
    45.5  from xen.xend import sxp
    45.6  from xen.xend import XendDomain
    45.7 +from xen.xend.XendDomainInfo import XendDomainInfo
    45.8  from xen.xend.Args import FormFn
    45.9  from xen.xend.XendError import XendError
   45.10  from xen.xend.XendLogging import log
   45.11 @@ -29,6 +30,7 @@ from xen.xend.XendLogging import log
   45.12  from xen.web.SrvDir import SrvDir
   45.13  from SrvDomain import SrvDomain
   45.14  
   45.15 +
   45.16  class SrvDomainDir(SrvDir):
   45.17      """Service that manages the domain directory.
   45.18      """
   45.19 @@ -124,28 +126,41 @@ class SrvDomainDir(SrvDir):
   45.20              out.close()
   45.21              return val
   45.22  
   45.23 +
   45.24 +    def op_list(self, _, req):
   45.25 +        """List the details for this domain."""
   45.26 +        self._list(req, True)
   45.27 +
   45.28 +
   45.29      def render_POST(self, req):
   45.30          return self.perform(req)
   45.31  
   45.32      def render_GET(self, req):
   45.33 +        self._list(req, 'detail' in req.args and req.args['detail'] == ['1'])
   45.34 +
   45.35 +
   45.36 +    def _list(self, req, detail):
   45.37          if self.use_sxp(req):
   45.38              req.setHeader("Content-Type", sxp.mime_type)
   45.39 -            self.ls_domain(req, 1)
   45.40 +            self.ls_domain(req, detail, True)
   45.41          else:
   45.42              req.write("<html><head></head><body>")
   45.43              self.print_path(req)
   45.44              self.ls(req)
   45.45 -            self.ls_domain(req)
   45.46 +            self.ls_domain(req, detail, False)
   45.47              self.form(req)
   45.48              req.write("</body></html>")
   45.49  
   45.50 -    def ls_domain(self, req, use_sxp=0):
   45.51 +
   45.52 +    def ls_domain(self, req, detail, use_sxp):
   45.53          url = req.prePathURL()
   45.54          if not url.endswith('/'):
   45.55              url += '/'
   45.56          if use_sxp:
   45.57 -            domains = self.xd.list_names()
   45.58 -            sxp.show(domains, out=req)
   45.59 +            if detail:
   45.60 +                sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req)
   45.61 +            else:
   45.62 +                sxp.show(self.xd.list_names(), out=req)
   45.63          else:
   45.64              domains = self.xd.list_sorted()
   45.65              req.write('<ul>')
   45.66 @@ -158,6 +173,7 @@ class SrvDomainDir(SrvDir):
   45.67                  req.write('</li>')
   45.68              req.write('</ul>')
   45.69  
   45.70 +
   45.71      def form(self, req):
   45.72          """Generate the form(s) for domain dir operations.
   45.73          """
    46.1 --- a/tools/python/xen/xend/server/SrvServer.py	Tue Oct 11 15:50:21 2005 -0600
    46.2 +++ b/tools/python/xen/xend/server/SrvServer.py	Tue Oct 11 16:57:44 2005 -0600
    46.3 @@ -1,4 +1,3 @@
    46.4 -#!/usr/bin/python
    46.5  #============================================================================
    46.6  # This library is free software; you can redistribute it and/or
    46.7  # modify it under the terms of version 2.1 of the GNU Lesser General Public
    47.1 --- a/tools/python/xen/xend/server/SrvXendLog.py	Tue Oct 11 15:50:21 2005 -0600
    47.2 +++ b/tools/python/xen/xend/server/SrvXendLog.py	Tue Oct 11 16:57:44 2005 -0600
    47.3 @@ -13,11 +13,12 @@
    47.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    47.5  #============================================================================
    47.6  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    47.7 +# Copyright (C) 2005 XenSource Ltd
    47.8  #============================================================================
    47.9  
   47.10  from xen.web import static
   47.11  
   47.12 -from xen.xend import XendRoot
   47.13 +from xen.xend import XendLogging
   47.14  
   47.15  from xen.web.SrvDir import SrvDir
   47.16  
   47.17 @@ -27,8 +28,8 @@ class SrvXendLog(SrvDir):
   47.18  
   47.19      def __init__(self):
   47.20          SrvDir.__init__(self)
   47.21 -        logging = XendRoot.instance().get_logging()
   47.22 -        self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain")
   47.23 +        self.logfile = static.File(XendLogging.getLogFilename(),
   47.24 +                                   defaultType="text/plain")
   47.25          self.logfile.type = "text/plain"
   47.26          self.logfile.encoding = None
   47.27  
    48.1 --- a/tools/python/xen/xend/server/event.py	Tue Oct 11 15:50:21 2005 -0600
    48.2 +++ b/tools/python/xen/xend/server/event.py	Tue Oct 11 16:57:44 2005 -0600
    48.3 @@ -25,6 +25,7 @@ from xen.xend import scheduler
    48.4  from xen.xend import sxp
    48.5  from xen.xend import PrettyPrint
    48.6  from xen.xend.XendError import XendError
    48.7 +from xen.xend import XendLogging
    48.8  from xen.xend import XendRoot
    48.9  
   48.10  
   48.11 @@ -146,11 +147,10 @@ class EventProtocol(protocol.Protocol):
   48.12  
   48.13      def op_log_stderr(self, _, v):
   48.14          mode = v[1]
   48.15 -        logging = xroot.get_logging()
   48.16          if mode == 'on':
   48.17 -            logging.addLogStderr()
   48.18 +            XendLogging.addLogStderr()
   48.19          else:
   48.20 -            logging.removeLogStderr()
   48.21 +            XendLogging.removeLogStderr()
   48.22  
   48.23      def op_domain_ls(self, _1, _2):
   48.24          xd = xroot.get_component("xen.xend.XendDomain")
    49.1 --- a/tools/python/xen/xend/sxp.py	Tue Oct 11 15:50:21 2005 -0600
    49.2 +++ b/tools/python/xen/xend/sxp.py	Tue Oct 11 16:57:44 2005 -0600
    49.3 @@ -1,4 +1,4 @@
    49.4 -#!/usr/bin/python
    49.5 +#!/usr/bin/env python
    49.6  #============================================================================
    49.7  # This library is free software; you can redistribute it and/or
    49.8  # modify it under the terms of version 2.1 of the GNU Lesser General Public
    50.1 --- a/tools/python/xen/xend/uuid.py	Tue Oct 11 15:50:21 2005 -0600
    50.2 +++ b/tools/python/xen/xend/uuid.py	Tue Oct 11 16:57:44 2005 -0600
    50.3 @@ -13,14 +13,19 @@
    50.4  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    50.5  #============================================================================
    50.6  # Copyright (C) 2005 Mike Wray <mike.wray@hp.com>
    50.7 +# Copyright (C) 2005 XenSource Ltd
    50.8  #============================================================================
    50.9  
   50.10 +
   50.11  """Universal(ly) Unique Identifiers (UUIDs).
   50.12  """
   50.13 +
   50.14 +
   50.15  import commands
   50.16  import random
   50.17  
   50.18 -def uuidgen(random=True):
   50.19 +
   50.20 +def getUuidUuidgen(random = True):
   50.21      """Generate a UUID using the command uuidgen.
   50.22  
   50.23      If random is true (default) generates a random uuid.
   50.24 @@ -33,50 +38,21 @@ def uuidgen(random=True):
   50.25          cmd += " -t"
   50.26      return commands.getoutput(cmd)
   50.27  
   50.28 -class UuidFactoryUuidgen:
   50.29 -
   50.30 -    """A uuid factory using uuidgen."""
   50.31 -
   50.32 -    def __init__(self):
   50.33 -        pass
   50.34 -
   50.35 -    def getUuid(self):
   50.36 -        return uuidgen()
   50.37 -
   50.38 -class UuidFactoryRandom:
   50.39 -
   50.40 -    """A random uuid factory."""
   50.41 -
   50.42 -    def __init__(self):
   50.43 -        f = file("/dev/urandom", "r")
   50.44 -        seed = f.read(16)
   50.45 -        f.close()
   50.46 -        self.rand = random.Random(seed)
   50.47  
   50.48 -    def randBytes(self, n):
   50.49 -        return [ self.rand.randint(0, 255) for i in range(0, n) ]
   50.50 -
   50.51 -    def getUuid(self):
   50.52 -        bytes = self.randBytes(16)
   50.53 -        # Encode the variant.
   50.54 -        bytes[6] = (bytes[6] & 0x0f) | 0x40
   50.55 -        bytes[8] = (bytes[8] & 0x3f) | 0x80
   50.56 -        f = "%02x"
   50.57 -        return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(bytes) )
   50.58 +def getUuidRandom():
   50.59 +    """Generate a random UUID."""
   50.60 +    
   50.61 +    bytes = [ random.randint(0, 255) for i in range(0, 16) ]
   50.62 +    # Encode the variant.
   50.63 +    bytes[6] = (bytes[6] & 0x0f) | 0x40
   50.64 +    bytes[8] = (bytes[8] & 0x3f) | 0x80
   50.65 +    f = "%02x"
   50.66 +    return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(bytes) )
   50.67  
   50.68 -def getFactory():
   50.69 -    """Get the factory to use for creating uuids.
   50.70 -    This is so it's easy to change the uuid factory.
   50.71 -    For example, for testing we might want repeatable uuids
   50.72 -    rather than the random ones we normally use.
   50.73 -    """
   50.74 -    global uuidFactory
   50.75 -    try:
   50.76 -        uuidFactory
   50.77 -    except:
   50.78 -        #uuidFactory = UuidFactoryUuidgen()
   50.79 -        uuidFactory = UuidFactoryRandom()
   50.80 -    return uuidFactory
   50.81 +
   50.82 +#uuidFactory = getUuidUuidgen
   50.83 +uuidFactory = getUuidRandom
   50.84 +
   50.85  
   50.86  def getUuid():
   50.87 -    return getFactory().getUuid()
   50.88 +    return uuidFactory()
    51.1 --- a/tools/python/xen/xend/xenstore/xstransact.py	Tue Oct 11 15:50:21 2005 -0600
    51.2 +++ b/tools/python/xen/xend/xenstore/xstransact.py	Tue Oct 11 16:57:44 2005 -0600
    51.3 @@ -14,29 +14,34 @@ from xen.xend.xenstore.xsutil import xsh
    51.4  class xstransact:
    51.5  
    51.6      def __init__(self, path):
    51.7 -        self.in_transaction = False
    51.8          self.path = path.rstrip("/")
    51.9 -        xshandle().transaction_start()
   51.10 +        self.transaction = xshandle().transaction_start()
   51.11          self.in_transaction = True
   51.12  
   51.13      def __del__(self):
   51.14          if self.in_transaction:
   51.15 -            xshandle().transaction_end(True)
   51.16 +            xshandle().transaction_end(self.transaction, True)
   51.17  
   51.18      def commit(self):
   51.19          if not self.in_transaction:
   51.20              raise RuntimeError
   51.21          self.in_transaction = False
   51.22 -        return xshandle().transaction_end(False)
   51.23 +        rc = xshandle().transaction_end(self.transaction, False)
   51.24 +        self.transaction = "0"
   51.25 +        return rc
   51.26  
   51.27      def abort(self):
   51.28 +        if not self.in_transaction:
   51.29 +            return True
   51.30          self.in_transaction = False
   51.31 -        return xshandle().transaction_end(True)
   51.32 +        rc = xshandle().transaction_end(self.transaction, True)
   51.33 +        self.transaction = "0"
   51.34 +        return rc
   51.35  
   51.36      def _read(self, key):
   51.37          path = "%s/%s" % (self.path, key)
   51.38          try:
   51.39 -            return xshandle().read(path)
   51.40 +            return xshandle().read(self.transaction, path)
   51.41          except RuntimeError, ex:
   51.42              raise RuntimeError(ex.args[0],
   51.43                                 '%s, while reading %s' % (ex.args[1], path))
   51.44 @@ -50,7 +55,7 @@ class xstransact:
   51.45          instead.
   51.46          """
   51.47          if len(args) == 0:
   51.48 -            return xshandle().read(self.path)
   51.49 +            return xshandle().read(self.transaction, self.path)
   51.50          if len(args) == 1:
   51.51              return self._read(args[0])
   51.52          ret = []
   51.53 @@ -61,7 +66,7 @@ class xstransact:
   51.54      def _write(self, key, data):
   51.55          path = "%s/%s" % (self.path, key)
   51.56          try:
   51.57 -            xshandle().write(path, data)
   51.58 +            xshandle().write(self.transaction, path, data)
   51.59          except RuntimeError, ex:
   51.60              raise RuntimeError(ex.args[0],
   51.61                                 ('%s, while writing %s : %s' %
   51.62 @@ -93,7 +98,7 @@ class xstransact:
   51.63  
   51.64      def _remove(self, key):
   51.65          path = "%s/%s" % (self.path, key)
   51.66 -        return xshandle().rm(path)
   51.67 +        return xshandle().rm(self.transaction, path)
   51.68  
   51.69      def remove(self, *args):
   51.70          """If no arguments are given, remove this transaction's path.
   51.71 @@ -101,14 +106,14 @@ class xstransact:
   51.72          path, and remove each of those instead.
   51.73          """
   51.74          if len(args) == 0:
   51.75 -            xshandle().rm(self.path)
   51.76 +            xshandle().rm(self.transaction, self.path)
   51.77          else:
   51.78              for key in args:
   51.79                  self._remove(key)
   51.80  
   51.81      def _list(self, key):
   51.82          path = "%s/%s" % (self.path, key)
   51.83 -        l = xshandle().ls(path)
   51.84 +        l = xshandle().ls(self.transaction, path)
   51.85          if l:
   51.86              return map(lambda x: key + "/" + x, l)
   51.87          return []
   51.88 @@ -120,7 +125,7 @@ class xstransact:
   51.89          path, and return the cumulative listing of each of those instead.
   51.90          """
   51.91          if len(args) == 0:
   51.92 -            ret = xshandle().ls(self.path)
   51.93 +            ret = xshandle().ls(self.transaction, self.path)
   51.94              if ret is None:
   51.95                  return []
   51.96              else:
   51.97 @@ -136,11 +141,11 @@ class xstransact:
   51.98          ret = []
   51.99          for key in keys:
  51.100              new_subdir = subdir + "/" + key
  51.101 -            l = xshandle().ls(new_subdir)
  51.102 +            l = xshandle().ls(self.transaction, new_subdir)
  51.103              if l:
  51.104                  ret.append([key, self.list_recursive_(new_subdir, l)])
  51.105              else:
  51.106 -                ret.append([key, xshandle().read(new_subdir)])
  51.107 +                ret.append([key, xshandle().read(self.transaction, new_subdir)])
  51.108          return ret
  51.109  
  51.110  
    52.1 --- a/tools/python/xen/xend/xenstore/xswatch.py	Tue Oct 11 15:50:21 2005 -0600
    52.2 +++ b/tools/python/xen/xend/xenstore/xswatch.py	Tue Oct 11 16:57:44 2005 -0600
    52.3 @@ -8,6 +8,7 @@
    52.4  import select
    52.5  import threading
    52.6  from xen.lowlevel import xs
    52.7 +from xen.xend.xenstore.xsutil import xshandle
    52.8  
    52.9  class xswatch:
   52.10  
   52.11 @@ -27,10 +28,7 @@ class xswatch:
   52.12          if cls.watchThread:
   52.13              cls.xslock.release()
   52.14              return
   52.15 -        # XXX: When we fix xenstored to have better watch semantics,
   52.16 -        # this can change to shared xshandle(). Currently that would result
   52.17 -        # in duplicate watch firings, thus failed extra xs.acknowledge_watch.
   52.18 -        cls.xs = xs.open()
   52.19 +        cls.xs = xshandle()
   52.20          cls.watchThread = threading.Thread(name="Watcher",
   52.21                                             target=cls.watchMain)
   52.22          cls.watchThread.setDaemon(True)
   52.23 @@ -43,11 +41,10 @@ class xswatch:
   52.24          while True:
   52.25              try:
   52.26                  we = cls.xs.read_watch()
   52.27 -                watch = we[1]
   52.28 -                cls.xs.acknowledge_watch(watch)
   52.29              except RuntimeError, ex:
   52.30                  print ex
   52.31                  raise
   52.32 +            watch = we[1]
   52.33              watch.fn(*watch.args, **watch.kwargs)
   52.34  
   52.35      watchMain = classmethod(watchMain)
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/tools/python/xen/xm/console.py	Tue Oct 11 16:57:44 2005 -0600
    53.3 @@ -0,0 +1,26 @@
    53.4 +#============================================================================
    53.5 +# This library is free software; you can redistribute it and/or
    53.6 +# modify it under the terms of version 2.1 of the GNU Lesser General Public
    53.7 +# License as published by the Free Software Foundation.
    53.8 +#
    53.9 +# This library is distributed in the hope that it will be useful,
   53.10 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.11 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   53.12 +# Lesser General Public License for more details.
   53.13 +#
   53.14 +# You should have received a copy of the GNU Lesser General Public
   53.15 +# License along with this library; if not, write to the Free Software
   53.16 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   53.17 +#============================================================================
   53.18 +# Copyright (C) 2005 XenSource Ltd
   53.19 +#============================================================================
   53.20 +
   53.21 +
   53.22 +XENCONSOLE = "xenconsole"
   53.23 +
   53.24 +
   53.25 +import xen.util.auxbin
   53.26 +
   53.27 +
   53.28 +def execConsole(domid):
   53.29 +    xen.util.auxbin.execute(XENCONSOLE, [str(domid)])
    54.1 --- a/tools/python/xen/xm/create.py	Tue Oct 11 15:50:21 2005 -0600
    54.2 +++ b/tools/python/xen/xm/create.py	Tue Oct 11 16:57:44 2005 -0600
    54.3 @@ -14,11 +14,14 @@
    54.4  #============================================================================
    54.5  # Copyright (C) 2004, 2005 Mike Wray <mike.wray@hp.com>
    54.6  # Copyright (C) 2005 Nguyen Anh Quynh <aquynh@gmail.com>
    54.7 +# Copyright (C) 2005 XenSource Ltd
    54.8  #============================================================================
    54.9  
   54.10  """Domain creation.
   54.11  """
   54.12  import random
   54.13 +import os
   54.14 +import os.path
   54.15  import string
   54.16  import sys
   54.17  import socket
   54.18 @@ -36,6 +39,9 @@ from xen.util import blkif
   54.19  
   54.20  from xen.xm.opts import *
   54.21  
   54.22 +import console
   54.23 +
   54.24 +
   54.25  gopts = Opts(use="""[options] [vars]
   54.26  
   54.27  Create a domain.
   54.28 @@ -879,8 +885,7 @@ def main(argv):
   54.29  
   54.30          dom = make_domain(opts, config)
   54.31          if opts.vals.console_autoconnect:
   54.32 -            cmd = "/usr/libexec/xen/xenconsole %d" % dom
   54.33 -            os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
   54.34 +            console.execConsole(dom)
   54.35          
   54.36  if __name__ == '__main__':
   54.37      main(sys.argv)
    55.1 --- a/tools/python/xen/xm/main.py	Tue Oct 11 15:50:21 2005 -0600
    55.2 +++ b/tools/python/xen/xm/main.py	Tue Oct 11 16:57:44 2005 -0600
    55.3 @@ -38,6 +38,8 @@ from xen.xend import PrettyPrint
    55.4  from xen.xend import sxp
    55.5  from xen.xm.opts import *
    55.6  
    55.7 +import console
    55.8 +
    55.9  
   55.10  shorthelp = """Usage: xm <subcommand> [args]
   55.11      Control, list, and manipulate Xen guest instances
   55.12 @@ -225,25 +227,22 @@ def xm_list(args):
   55.13          if k in ['-v', '--vcpus']:
   55.14              show_vcpus = 1
   55.15  
   55.16 -    domsinfo = []
   55.17      from xen.xend.XendClient import server
   55.18      if n == 0:
   55.19 -        doms = server.xend_domains()
   55.20 -        doms.sort()
   55.21 +        doms = server.xend_list_domains()
   55.22      else:
   55.23 -        doms = params
   55.24 -    for dom in doms:
   55.25 -        info = server.xend_domain(dom)
   55.26 -        domsinfo.append(parse_doms_info(info))
   55.27 +        doms = map(server.xend_domain, params)
   55.28                 
   55.29      if use_long:
   55.30          for dom in doms:
   55.31 -            info = server.xend_domain(dom)
   55.32 -            PrettyPrint.prettyprint(info)
   55.33 -    elif show_vcpus:
   55.34 -        xm_show_vcpus(domsinfo)
   55.35 +            PrettyPrint.prettyprint(doms)
   55.36      else:
   55.37 -        xm_brief_list(domsinfo)
   55.38 +        domsinfo = map(parse_doms_info, doms)
   55.39 +
   55.40 +        if show_vcpus:
   55.41 +            xm_show_vcpus(domsinfo)
   55.42 +        else:
   55.43 +            xm_brief_list(domsinfo)
   55.44  
   55.45  def parse_doms_info(info):
   55.46      dominfo = {}
   55.47 @@ -279,12 +278,12 @@ def parse_doms_info(info):
   55.48      return dominfo
   55.49          
   55.50  def xm_brief_list(domsinfo):
   55.51 -    print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)'
   55.52 +    print 'Name              ID  Mem(MiB)  CPU  VCPUs  State   Time(s)'
   55.53      for dominfo in domsinfo:
   55.54          if dominfo.has_key("ssidref1"):
   55.55 -            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
   55.56 +            print ("%(name)-16s %(dom)3d  %(mem)8d  %(cpu)3s  %(vcpus)5d  %(state)5s  %(cpu_time)7.1f     s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo)
   55.57          else:
   55.58 -            print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f" % dominfo)
   55.59 +            print ("%(name)-16s %(dom)3d  %(mem)8d  %(cpu)3s  %(vcpus)5d  %(state)5s  %(cpu_time)7.1f" % dominfo)
   55.60  
   55.61  def xm_show_vcpus(domsinfo):
   55.62      print 'Name              Id  VCPU  CPU  CPUMAP'
   55.63 @@ -445,12 +444,11 @@ def xm_console(args):
   55.64      from xen.xend.XendClient import server
   55.65      info = server.xend_domain(dom)
   55.66      domid = int(sxp.child_value(info, 'domid', '-1'))
   55.67 -    cmd = "/usr/libexec/xen/xenconsole %d" % domid
   55.68 -    os.execvp('/usr/libexec/xen/xenconsole', cmd.split())
   55.69 -    console = sxp.child(info, "console")
   55.70 +    console.execConsole(domid)
   55.71 +
   55.72  
   55.73  def xm_top(args):
   55.74 -    os.execv('/usr/sbin/xentop', ['/usr/sbin/xentop'])
   55.75 +    os.execvp('xentop', ['xentop'])
   55.76  
   55.77  def xm_dmesg(args):
   55.78      
    56.1 --- a/tools/python/xen/xm/sysrq.py	Tue Oct 11 15:50:21 2005 -0600
    56.2 +++ b/tools/python/xen/xm/sysrq.py	Tue Oct 11 16:57:44 2005 -0600
    56.3 @@ -1,17 +1,12 @@
    56.4  # (C) Matthew Bloch <matthew@bytemark.co.uk> 2004
    56.5 +# Copyright (C) 2005 XenSource Ltd
    56.6  
    56.7 -"""Domain shutdown.
    56.8 +"""Domain sysrq.
    56.9  """
   56.10 -import string
   56.11 -import sys
   56.12 -import time
   56.13  
   56.14  from xen.xend.XendClient import server
   56.15  from xen.xm.opts import *
   56.16  
   56.17 -DOM0_NAME = 'Domain-0'
   56.18 -DOM0_ID = '0'
   56.19 -
   56.20  gopts = Opts(use="""[DOM] [letter]
   56.21  
   56.22  Sends a Linux sysrq to a domain.
    57.1 --- a/tools/xcutils/Makefile	Tue Oct 11 15:50:21 2005 -0600
    57.2 +++ b/tools/xcutils/Makefile	Tue Oct 11 16:57:44 2005 -0600
    57.3 @@ -15,7 +15,7 @@ INSTALL_DIR	= $(INSTALL) -d -m0755
    57.4  XEN_ROOT	= ../..
    57.5  include $(XEN_ROOT)/tools/Rules.mk
    57.6  
    57.7 -PROGRAMS_INSTALL_DIR	= /usr/libexec/xen
    57.8 +PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin
    57.9  
   57.10  INCLUDES += -I $(XEN_LIBXC)
   57.11  
    58.1 --- a/tools/xenstore/Makefile	Tue Oct 11 15:50:21 2005 -0600
    58.2 +++ b/tools/xenstore/Makefile	Tue Oct 11 16:57:44 2005 -0600
    58.3 @@ -8,7 +8,7 @@ INSTALL_PROG    = $(INSTALL) -m0755
    58.4  INSTALL_DIR     = $(INSTALL) -d -m0755
    58.5  
    58.6  PROFILE=#-pg
    58.7 -BASECFLAGS=-Wall -W -g -Werror
    58.8 +BASECFLAGS=-Wall -g -Werror
    58.9  # Make gcc generate dependencies.
   58.10  BASECFLAGS += -Wp,-MD,.$(@F).d
   58.11  PROG_DEP = .*.d
   58.12 @@ -27,7 +27,7 @@ CLIENTS := xenstore-exists xenstore-list
   58.13  CLIENTS += xenstore-write
   58.14  CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS))
   58.15  
   58.16 -all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump
   58.17 +all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xsls
   58.18  
   58.19  testcode: xs_test xenstored_test xs_random
   58.20  
   58.21 @@ -40,6 +40,9 @@ xenstored: xenstored_core.o xenstored_wa
   58.22  $(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c
   58.23  	$(COMPILE.c) -DCLIENT_$(*F) -o $@ $<
   58.24  
   58.25 +xsls: xsls.o
   58.26 +	$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@
   58.27 +
   58.28  xenstored_test: xenstored_core_test.o xenstored_watch_test.o xenstored_domain_test.o xenstored_transaction_test.o xs_lib.o talloc_test.o fake_libxc.o utils.o tdb.o
   58.29  	$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
   58.30  
   58.31 @@ -126,7 +129,7 @@ TAGS:
   58.32  tarball: clean
   58.33  	cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/
   58.34  
   58.35 -install: libxenstore.so xenstored $(CLIENTS)
   58.36 +install: libxenstore.so xenstored xsls $(CLIENTS)
   58.37  	$(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored
   58.38  	$(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored
   58.39  	$(INSTALL_DIR) -p $(DESTDIR)/usr/bin
   58.40 @@ -134,6 +137,7 @@ install: libxenstore.so xenstored $(CLIE
   58.41  	$(INSTALL_DIR) -p $(DESTDIR)/usr/include
   58.42  	$(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin
   58.43  	$(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin
   58.44 +	$(INSTALL_PROG) xsls $(DESTDIR)/usr/bin
   58.45  	$(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
   58.46  	$(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR)
   58.47  	$(INSTALL_DATA) xs.h $(DESTDIR)/usr/include
    59.1 --- a/tools/xenstore/testsuite/07watch.test	Tue Oct 11 15:50:21 2005 -0600
    59.2 +++ b/tools/xenstore/testsuite/07watch.test	Tue Oct 11 16:57:44 2005 -0600
    59.3 @@ -5,7 +5,6 @@ 1 watch /test token
    59.4  2 write /test contents2
    59.5  expect 1:/test:token
    59.6  1 waitwatch
    59.7 -1 ackwatch token
    59.8  1 close
    59.9  
   59.10  # Check that reads don't set it off.
   59.11 @@ -22,15 +21,12 @@ 1 watch /dir token
   59.12  2 mkdir /dir/newdir
   59.13  expect 1:/dir/newdir:token
   59.14  1 waitwatch
   59.15 -1 ackwatch token
   59.16  2 setperm /dir/newdir 0 READ
   59.17  expect 1:/dir/newdir:token
   59.18  1 waitwatch
   59.19 -1 ackwatch token
   59.20  2 rm /dir/newdir
   59.21  expect 1:/dir/newdir:token
   59.22  1 waitwatch
   59.23 -1 ackwatch token
   59.24  1 close
   59.25  2 close
   59.26  
   59.27 @@ -49,7 +45,6 @@ expect contents
   59.28  read /dir/test
   59.29  expect /dir/test:token
   59.30  waitwatch
   59.31 -ackwatch token
   59.32  close
   59.33  
   59.34  # watch priority test: all simultaneous
   59.35 @@ -59,13 +54,10 @@ 2 watch /dir token2
   59.36  write /dir/test contents
   59.37  expect 3:/dir/test:token3
   59.38  3 waitwatch
   59.39 -3 ackwatch token3
   59.40  expect 2:/dir/test:token2
   59.41  2 waitwatch
   59.42 -2 ackwatch token2
   59.43  expect 1:/dir/test:token1
   59.44  1 waitwatch
   59.45 -1 ackwatch token1
   59.46  1 close
   59.47  2 close
   59.48  3 close
   59.49 @@ -79,7 +71,6 @@ 2 waitwatch
   59.50  2 close
   59.51  expect 1:/dir/test:token1
   59.52  1 waitwatch
   59.53 -1 ackwatch token1
   59.54  1 close
   59.55  
   59.56  # If one dies (without reading at all), the other should still get ack.
   59.57 @@ -89,7 +80,6 @@ write /dir/test contents
   59.58  2 close
   59.59  expect 1:/dir/test:token1
   59.60  1 waitwatch
   59.61 -1 ackwatch token1
   59.62  1 close
   59.63  2 close
   59.64  
   59.65 @@ -111,7 +101,6 @@ write /dir/test contents
   59.66  2 unwatch /dir token2
   59.67  expect 1:/dir/test:token1
   59.68  1 waitwatch
   59.69 -1 ackwatch token1
   59.70  1 close
   59.71  2 close
   59.72  
   59.73 @@ -123,14 +112,12 @@ 1 watch /dir/test token2
   59.74  write /dir/test contents2
   59.75  expect 1:/dir/test:token2
   59.76  1 waitwatch
   59.77 -1 ackwatch token2
   59.78  
   59.79  # check we only get notified once.
   59.80  1 watch /test token
   59.81  2 write /test contents2
   59.82  expect 1:/test:token
   59.83  1 waitwatch
   59.84 -1 ackwatch token
   59.85  expect 1: waitwatch failed: Connection timed out
   59.86  1 waitwatch
   59.87  1 close
   59.88 @@ -142,13 +129,10 @@ 2 write /test2 contents
   59.89  2 write /test3 contents
   59.90  expect 1:/test1:token
   59.91  1 waitwatch
   59.92 -1 ackwatch token
   59.93  expect 1:/test2:token
   59.94  1 waitwatch
   59.95 -1 ackwatch token
   59.96  expect 1:/test3:token
   59.97  1 waitwatch
   59.98 -1 ackwatch token
   59.99  1 close
  59.100  
  59.101  # Creation of subpaths should be covered correctly.
  59.102 @@ -157,10 +141,8 @@ 2 write /test/subnode contents2
  59.103  2 write /test/subnode/subnode contents2
  59.104  expect 1:/test/subnode:token
  59.105  1 waitwatch
  59.106 -1 ackwatch token
  59.107  expect 1:/test/subnode/subnode:token
  59.108  1 waitwatch
  59.109 -1 ackwatch token
  59.110  expect 1: waitwatch failed: Connection timed out
  59.111  1 waitwatch
  59.112  1 close
  59.113 @@ -171,7 +153,6 @@ 2 write /test/subnode contents2
  59.114  1 watchnoack / token2 0
  59.115  expect 1:/test/subnode:token
  59.116  1 waitwatch
  59.117 -1 ackwatch token
  59.118  expect 1:/:token2
  59.119  1 waitwatch
  59.120  expect 1: waitwatch failed: Connection timed out
  59.121 @@ -183,7 +164,6 @@ 1 watch /test/subnode token
  59.122  2 rm /test
  59.123  expect 1:/test/subnode:token
  59.124  1 waitwatch
  59.125 -1 ackwatch token
  59.126  
  59.127  # Watch should not double-send after we ack, even if we did something in between.
  59.128  1 watch /test2 token
  59.129 @@ -192,6 +172,5 @@ expect 1:/test2/foo:token
  59.130  1 waitwatch
  59.131  expect 1:contents2
  59.132  1 read /test2/foo
  59.133 -1 ackwatch token
  59.134  expect 1: waitwatch failed: Connection timed out
  59.135  1 waitwatch
    60.1 --- a/tools/xenstore/testsuite/08transaction.test	Tue Oct 11 15:50:21 2005 -0600
    60.2 +++ b/tools/xenstore/testsuite/08transaction.test	Tue Oct 11 16:57:44 2005 -0600
    60.3 @@ -68,7 +68,6 @@ 2 mkdir /test/dir/sub
    60.4  2 commit
    60.5  expect 1:/test/dir/sub:token
    60.6  1 waitwatch
    60.7 -1 ackwatch token
    60.8  1 close
    60.9  
   60.10  # Rm inside transaction works like rm outside: children get notified.
   60.11 @@ -78,7 +77,6 @@ 2 rm /test/dir
   60.12  2 commit
   60.13  expect 1:/test/dir/sub:token
   60.14  1 waitwatch
   60.15 -1 ackwatch token
   60.16  1 close
   60.17  
   60.18  # Multiple events from single transaction don't trigger assert
   60.19 @@ -89,8 +87,6 @@ 2 write /test/2 contents
   60.20  2 commit
   60.21  expect 1:/test/1:token
   60.22  1 waitwatch
   60.23 -1 ackwatch token
   60.24  expect 1:/test/2:token
   60.25  1 waitwatch
   60.26 -1 ackwatch token
   60.27  1 close
    61.1 --- a/tools/xenstore/testsuite/10domain-homedir.test	Tue Oct 11 15:50:21 2005 -0600
    61.2 +++ b/tools/xenstore/testsuite/10domain-homedir.test	Tue Oct 11 16:57:44 2005 -0600
    61.3 @@ -16,4 +16,3 @@ 1 watch foo token
    61.4  write /home/foo/bar contents
    61.5  expect 1:foo/bar:token
    61.6  1 waitwatch
    61.7 -1 ackwatch token
    62.1 --- a/tools/xenstore/testsuite/11domain-watch.test	Tue Oct 11 15:50:21 2005 -0600
    62.2 +++ b/tools/xenstore/testsuite/11domain-watch.test	Tue Oct 11 16:57:44 2005 -0600
    62.3 @@ -10,7 +10,6 @@ 1 watch /test token
    62.4  write /test contents2
    62.5  expect 1:/test:token
    62.6  1 waitwatch
    62.7 -1 ackwatch token
    62.8  1 unwatch /test token
    62.9  release 1
   62.10  1 close
   62.11 @@ -25,7 +24,6 @@ 1 write /dir/test3 contents3
   62.12  1 write /dir/test4 contents4
   62.13  expect 1:/dir/test:token
   62.14  1 waitwatch
   62.15 -1 ackwatch token
   62.16  release 1
   62.17  1 close
   62.18  
    63.1 --- a/tools/xenstore/testsuite/12readonly.test	Tue Oct 11 15:50:21 2005 -0600
    63.2 +++ b/tools/xenstore/testsuite/12readonly.test	Tue Oct 11 16:57:44 2005 -0600
    63.3 @@ -36,4 +36,3 @@ 1 readwrite
    63.4  1 write /test contents
    63.5  expect /test:token
    63.6  waitwatch
    63.7 -ackwatch token
    64.1 --- a/tools/xenstore/testsuite/13watch-ack.test	Tue Oct 11 15:50:21 2005 -0600
    64.2 +++ b/tools/xenstore/testsuite/13watch-ack.test	Tue Oct 11 16:57:44 2005 -0600
    64.3 @@ -18,5 +18,4 @@ expect 1:/test/2:token2
    64.4  1 waitwatch
    64.5  3 write /test/1 contents1
    64.6  4 write /test/3 contents3
    64.7 -1 ackwatch token2
    64.8  1 close
    65.1 --- a/tools/xenstore/utils.h	Tue Oct 11 15:50:21 2005 -0600
    65.2 +++ b/tools/xenstore/utils.h	Tue Oct 11 16:57:44 2005 -0600
    65.3 @@ -55,4 +55,34 @@ void xprintf(const char *fmt, ...);
    65.4  #define dprintf(_fmt, _args...) ((void)0)
    65.5  #endif
    65.6  
    65.7 +/*
    65.8 + * Mux errno values onto returned pointers.
    65.9 + */
   65.10 +
   65.11 +static inline void *ERR_PTR(long error)
   65.12 +{
   65.13 +	return (void *)error;
   65.14 +}
   65.15 +
   65.16 +static inline long PTR_ERR(const void *ptr)
   65.17 +{
   65.18 +	return (long)ptr;
   65.19 +}
   65.20 +
   65.21 +static inline long IS_ERR(const void *ptr)
   65.22 +{
   65.23 +	return ((unsigned long)ptr > (unsigned long)-1000L);
   65.24 +}
   65.25 +
   65.26 +
   65.27  #endif /* _UTILS_H */
   65.28 +
   65.29 +/*
   65.30 + * Local variables:
   65.31 + *  c-file-style: "linux"
   65.32 + *  indent-tabs-mode: t
   65.33 + *  c-indent-level: 8
   65.34 + *  c-basic-offset: 8
   65.35 + *  tab-width: 8
   65.36 + * End:
   65.37 + */
    66.1 --- a/tools/xenstore/xenstore_client.c	Tue Oct 11 15:50:21 2005 -0600
    66.2 +++ b/tools/xenstore/xenstore_client.c	Tue Oct 11 16:57:44 2005 -0600
    66.3 @@ -20,11 +20,11 @@ static void
    66.4  usage(const char *progname)
    66.5  {
    66.6  #if defined(CLIENT_read)
    66.7 -    errx(1, "Usage: %s [-h] [-p] key [...]", progname);
    66.8 +    errx(1, "Usage: %s [-h] [-p] [-s] key [...]", progname);
    66.9  #elif defined(CLIENT_write)
   66.10 -    errx(1, "Usage: %s [-h] key value [...]", progname);
   66.11 +    errx(1, "Usage: %s [-h] [-s] key value [...]", progname);
   66.12  #elif defined(CLIENT_rm) || defined(CLIENT_exists) || defined(CLIENT_list)
   66.13 -    errx(1, "Usage: %s [-h] key [...]", progname);
   66.14 +    errx(1, "Usage: %s [-h] [-s] key [...]", progname);
   66.15  #endif
   66.16  }
   66.17  
   66.18 @@ -32,16 +32,13 @@ int
   66.19  main(int argc, char **argv)
   66.20  {
   66.21      struct xs_handle *xsh;
   66.22 +    struct xs_transaction_handle *xth;
   66.23      bool success;
   66.24 -    int ret = 0;
   66.25 +    int ret = 0, socket = 0;
   66.26  #if defined(CLIENT_read) || defined(CLIENT_list)
   66.27      int prefix = 0;
   66.28  #endif
   66.29  
   66.30 -    xsh = xs_domain_open();
   66.31 -    if (xsh == NULL)
   66.32 -	err(1, "xs_domain_open");
   66.33 -
   66.34      while (1) {
   66.35  	int c, index = 0;
   66.36  	static struct option long_options[] = {
   66.37 @@ -49,10 +46,11 @@ main(int argc, char **argv)
   66.38  #if defined(CLIENT_read) || defined(CLIENT_list)
   66.39  	    {"prefix", 0, 0, 'p'},
   66.40  #endif
   66.41 +            {"socket", 0, 0, 's'},
   66.42  	    {0, 0, 0, 0}
   66.43  	};
   66.44  
   66.45 -	c = getopt_long(argc, argv, "h"
   66.46 +	c = getopt_long(argc, argv, "hs"
   66.47  #if defined(CLIENT_read) || defined(CLIENT_list)
   66.48  			"p"
   66.49  #endif
   66.50 @@ -64,6 +62,9 @@ main(int argc, char **argv)
   66.51  	case 'h':
   66.52  	    usage(argv[0]);
   66.53  	    /* NOTREACHED */
   66.54 +        case 's':
   66.55 +            socket = 1;
   66.56 +            break;
   66.57  #if defined(CLIENT_read) || defined(CLIENT_list)
   66.58  	case 'p':
   66.59  	    prefix = 1;
   66.60 @@ -83,14 +84,18 @@ main(int argc, char **argv)
   66.61      }
   66.62  #endif
   66.63  
   66.64 +    xsh = socket ? xs_daemon_open() : xs_domain_open();
   66.65 +    if (xsh == NULL)
   66.66 +	err(1, socket ? "xs_daemon_open" : "xs_domain_open");
   66.67 +
   66.68    again:
   66.69 -    success = xs_transaction_start(xsh);
   66.70 -    if (!success)
   66.71 +    xth = xs_transaction_start(xsh);
   66.72 +    if (xth == NULL)
   66.73  	errx(1, "couldn't start transaction");
   66.74  
   66.75      while (optind < argc) {
   66.76  #if defined(CLIENT_read)
   66.77 -	char *val = xs_read(xsh, argv[optind], NULL);
   66.78 +	char *val = xs_read(xsh, xth, argv[optind], NULL);
   66.79  	if (val == NULL) {
   66.80  	    warnx("couldn't read path %s", argv[optind]);
   66.81  	    ret = 1;
   66.82 @@ -102,7 +107,7 @@ main(int argc, char **argv)
   66.83  	free(val);
   66.84  	optind++;
   66.85  #elif defined(CLIENT_write)
   66.86 -	success = xs_write(xsh, argv[optind], argv[optind + 1],
   66.87 +	success = xs_write(xsh, xth, argv[optind], argv[optind + 1],
   66.88  			   strlen(argv[optind + 1]));
   66.89  	if (!success) {
   66.90  	    warnx("could not write path %s", argv[optind]);
   66.91 @@ -111,7 +116,7 @@ main(int argc, char **argv)
   66.92  	}
   66.93  	optind += 2;
   66.94  #elif defined(CLIENT_rm)
   66.95 -	success = xs_rm(xsh, argv[optind]);
   66.96 +	success = xs_rm(xsh, xth, argv[optind]);
   66.97  	if (!success) {
   66.98  	    warnx("could not remove path %s", argv[optind]);
   66.99  	    ret = 1;
  66.100 @@ -119,7 +124,7 @@ main(int argc, char **argv)
  66.101  	}
  66.102  	optind++;
  66.103  #elif defined(CLIENT_exists)
  66.104 -	char *val = xs_read(xsh, argv[optind], NULL);
  66.105 +	char *val = xs_read(xsh, xth, argv[optind], NULL);
  66.106  	if (val == NULL) {
  66.107  	    ret = 1;
  66.108  	    goto out;
  66.109 @@ -128,7 +133,7 @@ main(int argc, char **argv)
  66.110  	optind++;
  66.111  #elif defined(CLIENT_list)
  66.112  	unsigned int i, num;
  66.113 -	char **list = xs_directory(xsh, argv[optind], &num);
  66.114 +	char **list = xs_directory(xsh, xth, argv[optind], &num);
  66.115  	if (list == NULL) {
  66.116  	    warnx("could not list path %s", argv[optind]);
  66.117  	    ret = 1;
  66.118 @@ -145,7 +150,7 @@ main(int argc, char **argv)
  66.119      }
  66.120  
  66.121   out:
  66.122 -    success = xs_transaction_end(xsh, ret ? true : false);
  66.123 +    success = xs_transaction_end(xsh, xth, ret ? true : false);
  66.124      if (!success) {
  66.125  	if (ret == 0 && errno == EAGAIN)
  66.126  	    goto again;
    67.1 --- a/tools/xenstore/xenstored_core.c	Tue Oct 11 15:50:21 2005 -0600
    67.2 +++ b/tools/xenstore/xenstored_core.c	Tue Oct 11 16:57:44 2005 -0600
    67.3 @@ -154,7 +154,6 @@ static char *sockmsg_string(enum xsd_soc
    67.4  	case XS_READ: return "READ";
    67.5  	case XS_GET_PERMS: return "GET_PERMS";
    67.6  	case XS_WATCH: return "WATCH";
    67.7 -	case XS_WATCH_ACK: return "WATCH_ACK";
    67.8  	case XS_UNWATCH: return "UNWATCH";
    67.9  	case XS_TRANSACTION_START: return "TRANSACTION_START";
   67.10  	case XS_TRANSACTION_END: return "TRANSACTION_END";
   67.11 @@ -236,10 +235,14 @@ void trace(const char *fmt, ...)
   67.12  	talloc_free(str);
   67.13  }
   67.14  
   67.15 -static bool write_message(struct connection *conn)
   67.16 +static bool write_messages(struct connection *conn)
   67.17  {
   67.18  	int ret;
   67.19 -	struct buffered_data *out = conn->out;
   67.20 +	struct buffered_data *out;
   67.21 +
   67.22 +	out = list_top(&conn->out_list, struct buffered_data, list);
   67.23 +	if (out == NULL)
   67.24 +		return true;
   67.25  
   67.26  	if (out->inhdr) {
   67.27  		if (verbose)
   67.28 @@ -265,7 +268,6 @@ static bool write_message(struct connect
   67.29  
   67.30  	ret = conn->write(conn, out->buffer + out->used,
   67.31  			  out->hdr.msg.len - out->used);
   67.32 -
   67.33  	if (ret < 0)
   67.34  		return false;
   67.35  
   67.36 @@ -274,14 +276,10 @@ static bool write_message(struct connect
   67.37  		return true;
   67.38  
   67.39  	trace_io(conn, "OUT", out);
   67.40 -	conn->out = NULL;
   67.41 +
   67.42 +	list_del(&out->list);
   67.43  	talloc_free(out);
   67.44  
   67.45 -	queue_next_event(conn);
   67.46 -
   67.47 -	/* No longer busy? */
   67.48 -	if (!conn->out)
   67.49 -		conn->state = OK;
   67.50  	return true;
   67.51  }
   67.52  
   67.53 @@ -298,9 +296,9 @@ static int destroy_conn(void *_conn)
   67.54  		FD_SET(conn->fd, &set);
   67.55  		none.tv_sec = none.tv_usec = 0;
   67.56  
   67.57 -		while (conn->out
   67.58 +		while (!list_empty(&conn->out_list)
   67.59  		       && select(conn->fd+1, NULL, &set, NULL, &none) == 1)
   67.60 -			if (!write_message(conn))
   67.61 +			if (!write_messages(conn))
   67.62  				break;
   67.63  		close(conn->fd);
   67.64  	}
   67.65 @@ -327,9 +325,8 @@ static int initialize_set(fd_set *inset,
   67.66  	list_for_each_entry(i, &connections, list) {
   67.67  		if (i->domain)
   67.68  			continue;
   67.69 -		if (i->state == OK)
   67.70 -			FD_SET(i->fd, inset);
   67.71 -		if (i->out)
   67.72 +		FD_SET(i->fd, inset);
   67.73 +		if (!list_empty(&i->out_list))
   67.74  			FD_SET(i->fd, outset);
   67.75  		if (i->fd > max)
   67.76  			max = i->fd;
   67.77 @@ -542,6 +539,9 @@ static struct buffered_data *new_buffer(
   67.78  	struct buffered_data *data;
   67.79  
   67.80  	data = talloc(ctx, struct buffered_data);
   67.81 +	if (data == NULL)
   67.82 +		return NULL;
   67.83 +	
   67.84  	data->inhdr = true;
   67.85  	data->used = 0;
   67.86  	data->buffer = NULL;
   67.87 @@ -586,23 +586,25 @@ void send_reply(struct connection *conn,
   67.88  {
   67.89  	struct buffered_data *bdata;
   67.90  
   67.91 -	/* When data gets freed, we want list entry is destroyed (so
   67.92 -	 * list entry is a child). */
   67.93 +	/* Message is a child of the connection context for auto-cleanup. */
   67.94  	bdata = new_buffer(conn);
   67.95  	bdata->buffer = talloc_array(bdata, char, len);
   67.96  
   67.97 +	/* Echo request header in reply unless this is an async watch event. */
   67.98 +	if (type != XS_WATCH_EVENT) {
   67.99 +		memcpy(&bdata->hdr.msg, &conn->in->hdr.msg,
  67.100 +		       sizeof(struct xsd_sockmsg));
  67.101 +	} else {
  67.102 +		memset(&bdata->hdr.msg, 0, sizeof(struct xsd_sockmsg));
  67.103 +	}
  67.104 +
  67.105 +	/* Update relevant header fields and fill in the message body. */
  67.106  	bdata->hdr.msg.type = type;
  67.107  	bdata->hdr.msg.len = len;
  67.108  	memcpy(bdata->buffer, data, len);
  67.109  
  67.110 -	/* There might be an event going out now.  Queue behind it. */
  67.111 -	if (conn->out) {
  67.112 -		assert(conn->out->hdr.msg.type == XS_WATCH_EVENT);
  67.113 -		assert(!conn->waiting_reply);
  67.114 -		conn->waiting_reply = bdata;
  67.115 -	} else
  67.116 -		conn->out = bdata;
  67.117 -	conn->state = BUSY;
  67.118 +	/* Queue for later transmission. */
  67.119 +	list_add_tail(&bdata->list, &conn->out_list);
  67.120  }
  67.121  
  67.122  /* Some routines (write, mkdir, etc) just need a non-error return */
  67.123 @@ -1053,6 +1055,17 @@ static void do_set_perms(struct connecti
  67.124   */
  67.125  static void process_message(struct connection *conn, struct buffered_data *in)
  67.126  {
  67.127 +	struct transaction *trans;
  67.128 +
  67.129 +	trans = transaction_lookup(conn, in->hdr.msg.tx_id);
  67.130 +	if (IS_ERR(trans)) {
  67.131 +		send_error(conn, -PTR_ERR(trans));
  67.132 +		return;
  67.133 +	}
  67.134 +
  67.135 +	assert(conn->transaction == NULL);
  67.136 +	conn->transaction = trans;
  67.137 +
  67.138  	switch (in->hdr.msg.type) {
  67.139  	case XS_DIRECTORY:
  67.140  		send_directory(conn, onearg(in));
  67.141 @@ -1103,10 +1116,6 @@ static void process_message(struct conne
  67.142  		do_watch(conn, in);
  67.143  		break;
  67.144  
  67.145 -	case XS_WATCH_ACK:
  67.146 -		do_watch_ack(conn, onearg(in));
  67.147 -		break;
  67.148 -
  67.149  	case XS_UNWATCH:
  67.150  		do_unwatch(conn, in);
  67.151  		break;
  67.152 @@ -1131,11 +1140,13 @@ static void process_message(struct conne
  67.153  		do_get_domain_path(conn, onearg(in));
  67.154  		break;
  67.155  
  67.156 -	case XS_WATCH_EVENT:
  67.157  	default:
  67.158  		eprintf("Client unknown operation %i", in->hdr.msg.type);
  67.159  		send_error(conn, ENOSYS);
  67.160 +		break;
  67.161  	}
  67.162 +
  67.163 +	conn->transaction = NULL;
  67.164  }
  67.165  
  67.166  static int out_of_mem(void *data)
  67.167 @@ -1145,43 +1156,25 @@ static int out_of_mem(void *data)
  67.168  
  67.169  static void consider_message(struct connection *conn)
  67.170  {
  67.171 -	/*
  67.172 -	 * 'volatile' qualifier prevents register allocation which fixes:
  67.173 -	 *   warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork'
  67.174 -	 */
  67.175 -	struct buffered_data *volatile in = NULL;
  67.176 -	enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type;
  67.177  	jmp_buf talloc_fail;
  67.178  
  67.179 -	assert(conn->state == OK);
  67.180 +	if (verbose)
  67.181 +		xprintf("Got message %s len %i from %p\n",
  67.182 +			sockmsg_string(conn->in->hdr.msg.type),
  67.183 +			conn->in->hdr.msg.len, conn);
  67.184  
  67.185  	/* For simplicity, we kill the connection on OOM. */
  67.186  	talloc_set_fail_handler(out_of_mem, &talloc_fail);
  67.187  	if (setjmp(talloc_fail)) {
  67.188 -		/* Free in before conn, in case it needs something. */
  67.189 -		talloc_free(in);
  67.190  		talloc_free(conn);
  67.191  		goto end;
  67.192  	}
  67.193  
  67.194 -	if (verbose)
  67.195 -		xprintf("Got message %s len %i from %p\n",
  67.196 -			sockmsg_string(type), conn->in->hdr.msg.len, conn);
  67.197 -
  67.198 -	/* We might get a command while waiting for an ack: this means
  67.199 -	 * the other end discarded it: we will re-transmit. */
  67.200 -	if (type != XS_WATCH_ACK)
  67.201 -		conn->waiting_for_ack = NULL;
  67.202 +	process_message(conn, conn->in);
  67.203  
  67.204 -	/* Careful: process_message may free connection.  We detach
  67.205 -	 * "in" beforehand and allocate the new buffer to avoid
  67.206 -	 * touching conn after process_message.
  67.207 -	 */
  67.208 -	in = talloc_steal(talloc_autofree_context(), conn->in);
  67.209 +	talloc_free(conn->in);
  67.210  	conn->in = new_buffer(conn);
  67.211 -	process_message(conn, in);
  67.212  
  67.213 -	talloc_free(in);
  67.214  end:
  67.215  	talloc_set_fail_handler(NULL, NULL);
  67.216  	if (talloc_total_blocks(NULL)
  67.217 @@ -1196,10 +1189,7 @@ end:
  67.218  static void handle_input(struct connection *conn)
  67.219  {
  67.220  	int bytes;
  67.221 -	struct buffered_data *in;
  67.222 -
  67.223 -	assert(conn->state == OK);
  67.224 -	in = conn->in;
  67.225 +	struct buffered_data *in = conn->in;
  67.226  
  67.227  	/* Not finished header yet? */
  67.228  	if (in->inhdr) {
  67.229 @@ -1247,42 +1237,32 @@ bad_client:
  67.230  
  67.231  static void handle_output(struct connection *conn)
  67.232  {
  67.233 -	if (!write_message(conn))
  67.234 +	if (!write_messages(conn))
  67.235  		talloc_free(conn);
  67.236  }
  67.237  
  67.238  struct connection *new_connection(connwritefn_t *write, connreadfn_t *read)
  67.239  {
  67.240 -	/*
  67.241 -	 * 'volatile' qualifier prevents register allocation which fixes:
  67.242 -	 *   warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork'
  67.243 -	 */
  67.244 -	struct connection *volatile new;
  67.245 -	jmp_buf talloc_fail;
  67.246 +	struct connection *new;
  67.247  
  67.248  	new = talloc(talloc_autofree_context(), struct connection);
  67.249  	if (!new)
  67.250  		return NULL;
  67.251  
  67.252 -	new->state = OK;
  67.253 -	new->out = new->waiting_reply = NULL;
  67.254 -	new->waiting_for_ack = NULL;
  67.255 +	memset(new, 0, sizeof(*new));
  67.256  	new->fd = -1;
  67.257 -	new->id = 0;
  67.258 -	new->domain = NULL;
  67.259 -	new->transaction = NULL;
  67.260  	new->write = write;
  67.261  	new->read = read;
  67.262  	new->can_write = true;
  67.263 +	INIT_LIST_HEAD(&new->out_list);
  67.264  	INIT_LIST_HEAD(&new->watches);
  67.265 +	INIT_LIST_HEAD(&new->transaction_list);
  67.266  
  67.267 -	talloc_set_fail_handler(out_of_mem, &talloc_fail);
  67.268 -	if (setjmp(talloc_fail)) {
  67.269 +	new->in = new_buffer(new);
  67.270 +	if (new->in == NULL) {
  67.271  		talloc_free(new);
  67.272  		return NULL;
  67.273  	}
  67.274 -	new->in = new_buffer(new);
  67.275 -	talloc_set_fail_handler(NULL, NULL);
  67.276  
  67.277  	list_add_tail(&new->list, &connections);
  67.278  	talloc_set_destructor(new, destroy_conn);
  67.279 @@ -1328,23 +1308,17 @@ void dump_connection(void)
  67.280  	list_for_each_entry(i, &connections, list) {
  67.281  		printf("Connection %p:\n", i);
  67.282  		printf("    state = %s\n",
  67.283 -		       i->state == OK ? "OK"
  67.284 -		       : i->state == BUSY ? "BUSY"
  67.285 -		       : "INVALID");
  67.286 +		       list_empty(&i->out_list) ? "OK" : "BUSY");
  67.287  		if (i->id)
  67.288  			printf("    id = %i\n", i->id);
  67.289  		if (!i->in->inhdr || i->in->used)
  67.290  			printf("    got %i bytes of %s\n",
  67.291  			       i->in->used, i->in->inhdr ? "header" : "data");
  67.292 +#if 0
  67.293  		if (i->out)
  67.294  			printf("    sending message %s (%s) out\n",
  67.295  			       sockmsg_string(i->out->hdr.msg.type),
  67.296  			       i->out->buffer);
  67.297 -		if (i->waiting_reply)
  67.298 -			printf("    ... and behind is queued %s (%s)\n",
  67.299 -			       sockmsg_string(i->waiting_reply->hdr.msg.type),
  67.300 -			       i->waiting_reply->buffer);
  67.301 -#if 0
  67.302  		if (i->transaction)
  67.303  			dump_transaction(i);
  67.304  		if (i->domain)
  67.305 @@ -1443,6 +1417,7 @@ static void daemonize(void)
  67.306  
  67.307  
  67.308  static struct option options[] = {
  67.309 +	{ "no-domain-init", 0, NULL, 'D' },
  67.310  	{ "pid-file", 1, NULL, 'F' },
  67.311  	{ "no-fork", 0, NULL, 'N' },
  67.312  	{ "output-pid", 0, NULL, 'P' },
  67.313 @@ -1457,11 +1432,15 @@ int main(int argc, char *argv[])
  67.314  	fd_set inset, outset;
  67.315  	bool dofork = true;
  67.316  	bool outputpid = false;
  67.317 +	bool no_domain_init = false;
  67.318  	const char *pidfile = NULL;
  67.319  
  67.320 -	while ((opt = getopt_long(argc, argv, "F:NPT:V", options,
  67.321 +	while ((opt = getopt_long(argc, argv, "DF:NPT:V", options,
  67.322  				  NULL)) != -1) {
  67.323  		switch (opt) {
  67.324 +		case 'D':
  67.325 +			no_domain_init = true;
  67.326 +			break;
  67.327  		case 'F':
  67.328  			pidfile = optarg;
  67.329  			break;
  67.330 @@ -1534,7 +1513,8 @@ int main(int argc, char *argv[])
  67.331  	setup_structure();
  67.332  
  67.333  	/* Listen to hypervisor. */
  67.334 -	event_fd = domain_init();
  67.335 +	if (!no_domain_init)
  67.336 +		event_fd = domain_init();
  67.337  
  67.338  	/* Restore existing connections. */
  67.339  	restore_existing_connections();
  67.340 @@ -1615,3 +1595,13 @@ int main(int argc, char *argv[])
  67.341  		max = initialize_set(&inset, &outset, *sock, *ro_sock);
  67.342  	}
  67.343  }
  67.344 +
  67.345 +/*
  67.346 + * Local variables:
  67.347 + *  c-file-style: "linux"
  67.348 + *  indent-tabs-mode: t
  67.349 + *  c-indent-level: 8
  67.350 + *  c-basic-offset: 8
  67.351 + *  tab-width: 8
  67.352 + * End:
  67.353 + */
    68.1 --- a/tools/xenstore/xenstored_core.h	Tue Oct 11 15:50:21 2005 -0600
    68.2 +++ b/tools/xenstore/xenstored_core.h	Tue Oct 11 16:57:44 2005 -0600
    68.3 @@ -31,14 +31,19 @@
    68.4  
    68.5  struct buffered_data
    68.6  {
    68.7 +	struct list_head list;
    68.8 +
    68.9  	/* Are we still doing the header? */
   68.10  	bool inhdr;
   68.11 +
   68.12  	/* How far are we? */
   68.13  	unsigned int used;
   68.14 +
   68.15  	union {
   68.16  		struct xsd_sockmsg msg;
   68.17  		char raw[sizeof(struct xsd_sockmsg)];
   68.18  	} hdr;
   68.19 +
   68.20  	/* The actual data. */
   68.21  	char *buffer;
   68.22  };
   68.23 @@ -47,14 +52,6 @@ struct connection;
   68.24  typedef int connwritefn_t(struct connection *, const void *, unsigned int);
   68.25  typedef int connreadfn_t(struct connection *, void *, unsigned int);
   68.26  
   68.27 -enum state
   68.28 -{
   68.29 -	/* Doing action, not listening */
   68.30 -	BUSY,
   68.31 -	/* Completed */
   68.32 -	OK,
   68.33 -};
   68.34 -
   68.35  struct connection
   68.36  {
   68.37  	struct list_head list;
   68.38 @@ -62,29 +59,24 @@ struct connection
   68.39  	/* The file descriptor we came in on. */
   68.40  	int fd;
   68.41  
   68.42 -	/* Who am I?  0 for socket connections. */
   68.43 +	/* Who am I? 0 for socket connections. */
   68.44  	domid_t id;
   68.45  
   68.46 -	/* Blocked on transaction?  Busy? */
   68.47 -	enum state state;
   68.48 -
   68.49  	/* Is this a read-only connection? */
   68.50  	bool can_write;
   68.51  
   68.52 -	/* Are we waiting for a watch event ack? */
   68.53 -	struct watch *waiting_for_ack;
   68.54 -
   68.55  	/* Buffered incoming data. */
   68.56  	struct buffered_data *in;
   68.57  
   68.58  	/* Buffered output data */
   68.59 -	struct buffered_data *out;
   68.60 +	struct list_head out_list;
   68.61  
   68.62 -	/* If we had a watch fire outgoing when we needed to reply... */
   68.63 -	struct buffered_data *waiting_reply;
   68.64 +	/* Transaction context for current request (NULL if none). */
   68.65 +	struct transaction *transaction;
   68.66  
   68.67 -	/* My transaction, if any. */
   68.68 -	struct transaction *transaction;
   68.69 +	/* List of in-progress transactions. */
   68.70 +	struct list_head transaction_list;
   68.71 +	u32 next_transaction_id;
   68.72  
   68.73  	/* The domain I'm associated with, if any. */
   68.74  	struct domain *domain;
   68.75 @@ -175,3 +167,13 @@ void trace(const char *fmt, ...);
   68.76  extern int event_fd;
   68.77  
   68.78  #endif /* _XENSTORED_CORE_H */
   68.79 +
   68.80 +/*
   68.81 + * Local variables:
   68.82 + *  c-file-style: "linux"
   68.83 + *  indent-tabs-mode: t
   68.84 + *  c-indent-level: 8
   68.85 + *  c-basic-offset: 8
   68.86 + *  tab-width: 8
   68.87 + * End:
   68.88 + */
    69.1 --- a/tools/xenstore/xenstored_domain.c	Tue Oct 11 15:50:21 2005 -0600
    69.2 +++ b/tools/xenstore/xenstored_domain.c	Tue Oct 11 16:57:44 2005 -0600
    69.3 @@ -53,6 +53,14 @@ struct domain
    69.4  	/* Event channel port */
    69.5  	u16 port;
    69.6  
    69.7 +	/* The remote end of the event channel, used only to validate
    69.8 +	   repeated domain introductions. */
    69.9 +	u16 remote_port;
   69.10 +
   69.11 +	/* The mfn associated with the event channel, used only to validate
   69.12 +	   repeated domain introductions. */
   69.13 +	unsigned long mfn;
   69.14 +
   69.15  	/* Domain path in store. */
   69.16  	char *path;
   69.17  
   69.18 @@ -276,12 +284,13 @@ void handle_event(void)
   69.19  
   69.20  bool domain_can_read(struct connection *conn)
   69.21  {
   69.22 -	return conn->state == OK && buffer_has_input(conn->domain->input);
   69.23 +	return buffer_has_input(conn->domain->input);
   69.24  }
   69.25  
   69.26  bool domain_can_write(struct connection *conn)
   69.27  {
   69.28 -	return conn->out && buffer_has_output_room(conn->domain->output);
   69.29 +	return (!list_empty(&conn->out_list) &&
   69.30 +                buffer_has_output_room(conn->domain->output));
   69.31  }
   69.32  
   69.33  static struct domain *new_domain(void *context, domid_t domid,
   69.34 @@ -321,14 +330,35 @@ static struct domain *new_domain(void *c
   69.35  	domain->port = rc;
   69.36  	domain->conn = new_connection(writechn, readchn);
   69.37  	domain->conn->domain = domain;
   69.38 +
   69.39 +	domain->remote_port = port;
   69.40 +	domain->mfn = mfn;
   69.41 +
   69.42  	return domain;
   69.43  }
   69.44  
   69.45 +
   69.46 +static struct domain *find_domain_by_domid(domid_t domid)
   69.47 +{
   69.48 +	struct domain *i;
   69.49 +
   69.50 +	list_for_each_entry(i, &domains, list) {
   69.51 +		if (i->domid == domid)
   69.52 +			return i;
   69.53 +	}
   69.54 +	return NULL;
   69.55 +}
   69.56 +
   69.57 +
   69.58  /* domid, mfn, evtchn, path */
   69.59  void do_introduce(struct connection *conn, struct buffered_data *in)
   69.60  {
   69.61  	struct domain *domain;
   69.62  	char *vec[4];
   69.63 +	domid_t domid;
   69.64 +	unsigned long mfn;
   69.65 +	u16 port;
   69.66 +	const char *path;
   69.67  
   69.68  	if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) {
   69.69  		send_error(conn, EINVAL);
   69.70 @@ -340,38 +370,46 @@ void do_introduce(struct connection *con
   69.71  		return;
   69.72  	}
   69.73  
   69.74 +	domid = atoi(vec[0]);
   69.75 +	mfn = atol(vec[1]);
   69.76 +	port = atoi(vec[2]);
   69.77 +	path = vec[3];
   69.78 +
   69.79  	/* Sanity check args. */
   69.80 -	if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3])) {
   69.81 +	if ((port <= 0) || !is_valid_nodename(path)) {
   69.82  		send_error(conn, EINVAL);
   69.83  		return;
   69.84  	}
   69.85 -	/* Hang domain off "in" until we're finished. */
   69.86 -	domain = new_domain(in, atoi(vec[0]), atol(vec[1]), atol(vec[2]),
   69.87 -			    vec[3]);
   69.88 -	if (!domain) {
   69.89 -		send_error(conn, errno);
   69.90 -		return;
   69.91 -	}
   69.92  
   69.93 -	/* Now domain belongs to its connection. */
   69.94 -	talloc_steal(domain->conn, domain);
   69.95 +	domain = find_domain_by_domid(domid);
   69.96  
   69.97 -	fire_watches(conn, "@introduceDomain", false);
   69.98 +	if (domain == NULL) {
   69.99 +		/* Hang domain off "in" until we're finished. */
  69.100 +		domain = new_domain(in, domid, mfn, port, path);
  69.101 +		if (!domain) {
  69.102 +			send_error(conn, errno);
  69.103 +			return;
  69.104 +		}
  69.105 +
  69.106 +		/* Now domain belongs to its connection. */
  69.107 +		talloc_steal(domain->conn, domain);
  69.108 +
  69.109 +		fire_watches(conn, "@introduceDomain", false);
  69.110 +	}
  69.111 +	else {
  69.112 +		/* Check that the given details match the ones we have
  69.113 +		   previously recorded. */
  69.114 +		if (port != domain->remote_port ||
  69.115 +		    mfn != domain->mfn ||
  69.116 +		    strcmp(path, domain->path) != 0) {
  69.117 +			send_error(conn, EINVAL);
  69.118 +			return;
  69.119 +		}
  69.120 +	}
  69.121  
  69.122  	send_ack(conn, XS_INTRODUCE);
  69.123  }
  69.124  
  69.125 -static struct domain *find_domain_by_domid(domid_t domid)
  69.126 -{
  69.127 -	struct domain *i;
  69.128 -
  69.129 -	list_for_each_entry(i, &domains, list) {
  69.130 -		if (i->domid == domid)
  69.131 -			return i;
  69.132 -	}
  69.133 -	return NULL;
  69.134 -}
  69.135 -
  69.136  /* domid */
  69.137  void do_release(struct connection *conn, const char *domid_str)
  69.138  {
    70.1 --- a/tools/xenstore/xenstored_transaction.c	Tue Oct 11 15:50:21 2005 -0600
    70.2 +++ b/tools/xenstore/xenstored_transaction.c	Tue Oct 11 16:57:44 2005 -0600
    70.3 @@ -37,7 +37,7 @@
    70.4  
    70.5  struct changed_node
    70.6  {
    70.7 -	/* The list within this transaction. */
    70.8 +	/* List of all changed nodes in the context of this transaction. */
    70.9  	struct list_head list;
   70.10  
   70.11  	/* The name of the node. */
   70.12 @@ -49,15 +49,15 @@ struct changed_node
   70.13  
   70.14  struct transaction
   70.15  {
   70.16 -	/* Global list of transactions. */
   70.17 +	/* List of all transactions active on this connection. */
   70.18  	struct list_head list;
   70.19  
   70.20 +	/* Connection-local identifier for this transaction. */
   70.21 +	u32 id;
   70.22 +
   70.23  	/* Generation when transaction started. */
   70.24  	unsigned int generation;
   70.25  
   70.26 -	/* My owner (conn->transaction == me). */
   70.27 -	struct connection *conn;
   70.28 -
   70.29  	/* TDB to work on, and filename */
   70.30  	TDB_CONTEXT *tdb;
   70.31  	char *tdb_name;
   70.32 @@ -65,7 +65,7 @@ struct transaction
   70.33  	/* List of changed nodes. */
   70.34  	struct list_head changes;
   70.35  };
   70.36 -static LIST_HEAD(transactions);
   70.37 +
   70.38  static unsigned int generation;
   70.39  
   70.40  /* Return tdb context to use for this connection. */
   70.41 @@ -100,7 +100,6 @@ static int destroy_transaction(void *_tr
   70.42  {
   70.43  	struct transaction *trans = _transaction;
   70.44  
   70.45 -	list_del(&trans->list);
   70.46  	trace_destroy(trans, "transaction");
   70.47  	if (trans->tdb)
   70.48  		tdb_close(trans->tdb);
   70.49 @@ -108,10 +107,26 @@ static int destroy_transaction(void *_tr
   70.50  	return 0;
   70.51  }
   70.52  
   70.53 -void do_transaction_start(struct connection *conn, struct buffered_data *in)
   70.54 +struct transaction *transaction_lookup(struct connection *conn, u32 id)
   70.55  {
   70.56  	struct transaction *trans;
   70.57  
   70.58 +	if (id == 0)
   70.59 +		return NULL;
   70.60 +
   70.61 +	list_for_each_entry(trans, &conn->transaction_list, list)
   70.62 +		if (trans->id == id)
   70.63 +			return trans;
   70.64 +
   70.65 +	return ERR_PTR(-ENOENT);
   70.66 +}
   70.67 +
   70.68 +void do_transaction_start(struct connection *conn, struct buffered_data *in)
   70.69 +{
   70.70 +	struct transaction *trans, *exists;
   70.71 +	char id_str[20];
   70.72 +
   70.73 +	/* We don't support nested transactions. */
   70.74  	if (conn->transaction) {
   70.75  		send_error(conn, EBUSY);
   70.76  		return;
   70.77 @@ -120,7 +135,6 @@ void do_transaction_start(struct connect
   70.78  	/* Attach transaction to input for autofree until it's complete */
   70.79  	trans = talloc(in, struct transaction);
   70.80  	INIT_LIST_HEAD(&trans->changes);
   70.81 -	trans->conn = conn;
   70.82  	trans->generation = generation;
   70.83  	trans->tdb_name = talloc_asprintf(trans, "%s.%p",
   70.84  					  xs_daemon_tdb(), trans);
   70.85 @@ -132,11 +146,19 @@ void do_transaction_start(struct connect
   70.86  	/* Make it close if we go away. */
   70.87  	talloc_steal(trans, trans->tdb);
   70.88  
   70.89 +	/* Pick an unused transaction identifier. */
   70.90 +	do {
   70.91 +		trans->id = conn->next_transaction_id;
   70.92 +		exists = transaction_lookup(conn, conn->next_transaction_id++);
   70.93 +	} while (!IS_ERR(exists));
   70.94 +
   70.95  	/* Now we own it. */
   70.96 -	conn->transaction = talloc_steal(conn, trans);
   70.97 -	list_add_tail(&trans->list, &transactions);
   70.98 +	list_add_tail(&trans->list, &conn->transaction_list);
   70.99 +	talloc_steal(conn, trans);
  70.100  	talloc_set_destructor(trans, destroy_transaction);
  70.101 -	send_ack(conn, XS_TRANSACTION_START);
  70.102 +
  70.103 +	sprintf(id_str, "%u", trans->id);
  70.104 +	send_reply(conn, XS_TRANSACTION_START, id_str, strlen(id_str)+1);
  70.105  }
  70.106  
  70.107  void do_transaction_end(struct connection *conn, const char *arg)
  70.108 @@ -149,14 +171,14 @@ void do_transaction_end(struct connectio
  70.109  		return;
  70.110  	}
  70.111  
  70.112 -	if (!conn->transaction) {
  70.113 +	if ((trans = conn->transaction) == NULL) {
  70.114  		send_error(conn, ENOENT);
  70.115  		return;
  70.116  	}
  70.117  
  70.118 -	/* Set to NULL so fire_watches sends events, tdb_context works. */
  70.119 -	trans = conn->transaction;
  70.120  	conn->transaction = NULL;
  70.121 +	list_del(&trans->list);
  70.122 +
  70.123  	/* Attach transaction to arg for auto-cleanup */
  70.124  	talloc_steal(arg, trans);
  70.125  
  70.126 @@ -181,3 +203,12 @@ void do_transaction_end(struct connectio
  70.127  	send_ack(conn, XS_TRANSACTION_END);
  70.128  }
  70.129  
  70.130 +/*
  70.131 + * Local variables:
  70.132 + *  c-file-style: "linux"
  70.133 + *  indent-tabs-mode: t
  70.134 + *  c-indent-level: 8
  70.135 + *  c-basic-offset: 8
  70.136 + *  tab-width: 8
  70.137 + * End:
  70.138 + */
    71.1 --- a/tools/xenstore/xenstored_transaction.h	Tue Oct 11 15:50:21 2005 -0600
    71.2 +++ b/tools/xenstore/xenstored_transaction.h	Tue Oct 11 16:57:44 2005 -0600
    71.3 @@ -25,10 +25,11 @@ struct transaction;
    71.4  void do_transaction_start(struct connection *conn, struct buffered_data *node);
    71.5  void do_transaction_end(struct connection *conn, const char *arg);
    71.6  
    71.7 -bool transaction_block(struct connection *conn);
    71.8 +struct transaction *transaction_lookup(struct connection *conn, u32 id);
    71.9  
   71.10  /* This node was changed: can fail and longjmp. */
   71.11 -void add_change_node(struct transaction *trans, const char *node, bool recurse);
   71.12 +void add_change_node(struct transaction *trans, const char *node,
   71.13 +                     bool recurse);
   71.14  
   71.15  /* Return tdb context to use for this connection. */
   71.16  TDB_CONTEXT *tdb_transaction_context(struct transaction *trans);
    72.1 --- a/tools/xenstore/xenstored_watch.c	Tue Oct 11 15:50:21 2005 -0600
    72.2 +++ b/tools/xenstore/xenstored_watch.c	Tue Oct 11 16:57:44 2005 -0600
    72.3 @@ -32,17 +32,6 @@
    72.4  #include "xenstored_test.h"
    72.5  #include "xenstored_domain.h"
    72.6  
    72.7 -/* FIXME: time out unacked watches. */
    72.8 -struct watch_event
    72.9 -{
   72.10 -	/* The events on this watch. */
   72.11 -	struct list_head list;
   72.12 -
   72.13 -	/* Data to send (node\0token\0). */
   72.14 -	unsigned int len;
   72.15 -	char *data;
   72.16 -};
   72.17 -
   72.18  struct watch
   72.19  {
   72.20  	/* Watches on this connection */
   72.21 @@ -58,54 +47,17 @@ struct watch
   72.22  	char *node;
   72.23  };
   72.24  
   72.25 -/* Look through our watches: if any of them have an event, queue it. */
   72.26 -void queue_next_event(struct connection *conn)
   72.27 -{
   72.28 -	struct watch_event *event;
   72.29 -	struct watch *watch;
   72.30 -
   72.31 -	/* We had a reply queued already?  Send it: other end will
   72.32 -	 * discard watch. */
   72.33 -	if (conn->waiting_reply) {
   72.34 -		conn->out = conn->waiting_reply;
   72.35 -		conn->waiting_reply = NULL;
   72.36 -		conn->waiting_for_ack = NULL;
   72.37 -		return;
   72.38 -	}
   72.39 -
   72.40 -	/* If we're already waiting for ack, don't queue more. */
   72.41 -	if (conn->waiting_for_ack)
   72.42 -		return;
   72.43 -
   72.44 -	list_for_each_entry(watch, &conn->watches, list) {
   72.45 -		event = list_top(&watch->events, struct watch_event, list);
   72.46 -		if (event) {
   72.47 -			conn->waiting_for_ack = watch;
   72.48 -			send_reply(conn,XS_WATCH_EVENT,event->data,event->len);
   72.49 -			break;
   72.50 -		}
   72.51 -	}
   72.52 -}
   72.53 -
   72.54 -static int destroy_watch_event(void *_event)
   72.55 -{
   72.56 -	struct watch_event *event = _event;
   72.57 -
   72.58 -	trace_destroy(event, "watch_event");
   72.59 -	return 0;
   72.60 -}
   72.61 -
   72.62  static void add_event(struct connection *conn,
   72.63  		      struct watch *watch,
   72.64  		      const char *name)
   72.65  {
   72.66 -	struct watch_event *event;
   72.67 +	/* Data to send (node\0token\0). */
   72.68 +	unsigned int len;
   72.69 +	char *data;
   72.70  
   72.71  	if (!check_event_node(name)) {
   72.72  		/* Can this conn load node, or see that it doesn't exist? */
   72.73 -		struct node *node;
   72.74 -
   72.75 -		node = get_node(conn, name, XS_PERM_READ);
   72.76 +		struct node *node = get_node(conn, name, XS_PERM_READ);
   72.77  		if (!node && errno != ENOENT)
   72.78  			return;
   72.79  	}
   72.80 @@ -116,14 +68,12 @@ static void add_event(struct connection 
   72.81  			name++;
   72.82  	}
   72.83  
   72.84 -	event = talloc(watch, struct watch_event);
   72.85 -	event->len = strlen(name) + 1 + strlen(watch->token) + 1;
   72.86 -	event->data = talloc_array(event, char, event->len);
   72.87 -	strcpy(event->data, name);
   72.88 -	strcpy(event->data + strlen(name) + 1, watch->token);
   72.89 -	talloc_set_destructor(event, destroy_watch_event);
   72.90 -	list_add_tail(&event->list, &watch->events);
   72.91 -	trace_create(event, "watch_event");
   72.92 +	len = strlen(name) + 1 + strlen(watch->token) + 1;
   72.93 +	data = talloc_array(watch, char, len);
   72.94 +	strcpy(data, name);
   72.95 +	strcpy(data + strlen(name) + 1, watch->token);
   72.96 +        send_reply(conn, XS_WATCH_EVENT, data, len);
   72.97 +	talloc_free(data);
   72.98  }
   72.99  
  72.100  /* FIXME: we fail to fire on out of memory.  Should drop connections. */
  72.101 @@ -143,11 +93,6 @@ void fire_watches(struct connection *con
  72.102  				add_event(i, watch, name);
  72.103  			else if (recurse && is_child(watch->node, name))
  72.104  				add_event(i, watch, watch->node);
  72.105 -			else
  72.106 -				continue;
  72.107 -			/* If connection not doing anything, queue this. */
  72.108 -			if (i->state == OK)
  72.109 -				queue_next_event(i);
  72.110  		}
  72.111  	}
  72.112  }
  72.113 @@ -181,6 +126,15 @@ void do_watch(struct connection *conn, s
  72.114  		}
  72.115  	}
  72.116  
  72.117 +	/* Check for duplicates. */
  72.118 +	list_for_each_entry(watch, &conn->watches, list) {
  72.119 +		if (streq(watch->node, vec[0]) &&
  72.120 +                    streq(watch->token, vec[1])) {
  72.121 +			send_error(conn, EEXIST);
  72.122 +			return;
  72.123 +		}
  72.124 +	}
  72.125 +
  72.126  	watch = talloc(conn, struct watch);
  72.127  	watch->node = talloc_strdup(watch, vec[0]);
  72.128  	watch->token = talloc_strdup(watch, vec[1]);
  72.129 @@ -200,37 +154,6 @@ void do_watch(struct connection *conn, s
  72.130  	add_event(conn, watch, watch->node);
  72.131  }
  72.132  
  72.133 -void do_watch_ack(struct connection *conn, const char *token)
  72.134 -{
  72.135 -	struct watch_event *event;
  72.136 -
  72.137 -	if (!token) {
  72.138 -		send_error(conn, EINVAL);
  72.139 -		return;
  72.140 -	}
  72.141 -
  72.142 -	if (!conn->waiting_for_ack) {
  72.143 -		send_error(conn, ENOENT);
  72.144 -		return;
  72.145 -	}
  72.146 -
  72.147 -	if (!streq(conn->waiting_for_ack->token, token)) {
  72.148 -		/* They're confused: this will cause us to send event again */
  72.149 -		conn->waiting_for_ack = NULL;
  72.150 -		send_error(conn, EINVAL);
  72.151 -		return;
  72.152 -	}
  72.153 -
  72.154 -	/* Remove event: after ack sent, core will call queue_next_event */
  72.155 -	event = list_top(&conn->waiting_for_ack->events, struct watch_event,
  72.156 -			 list);
  72.157 -	list_del(&event->list);
  72.158 -	talloc_free(event);
  72.159 -
  72.160 -	conn->waiting_for_ack = NULL;
  72.161 -	send_ack(conn, XS_WATCH_ACK);
  72.162 -}
  72.163 -
  72.164  void do_unwatch(struct connection *conn, struct buffered_data *in)
  72.165  {
  72.166  	struct watch *watch;
  72.167 @@ -241,9 +164,6 @@ void do_unwatch(struct connection *conn,
  72.168  		return;
  72.169  	}
  72.170  
  72.171 -	/* We don't need to worry if we're waiting for an ack for the
  72.172 -	 * watch we're deleting: conn->waiting_for_ack was reset by
  72.173 -	 * this command in consider_message anyway. */
  72.174  	node = canonicalize(conn, vec[0]);
  72.175  	list_for_each_entry(watch, &conn->watches, list) {
  72.176  		if (streq(watch->node, node) && streq(watch->token, vec[1])) {
  72.177 @@ -260,18 +180,19 @@ void do_unwatch(struct connection *conn,
  72.178  void dump_watches(struct connection *conn)
  72.179  {
  72.180  	struct watch *watch;
  72.181 -	struct watch_event *event;
  72.182  
  72.183 -	if (conn->waiting_for_ack)
  72.184 -		printf("    waiting_for_ack for watch on %s token %s\n",
  72.185 -		       conn->waiting_for_ack->node,
  72.186 -		       conn->waiting_for_ack->token);
  72.187 -
  72.188 -	list_for_each_entry(watch, &conn->watches, list) {
  72.189 +	list_for_each_entry(watch, &conn->watches, list)
  72.190  		printf("    watch on %s token %s\n",
  72.191  		       watch->node, watch->token);
  72.192 -		list_for_each_entry(event, &watch->events, list)
  72.193 -			printf("        event: %s\n", event->data);
  72.194 -	}
  72.195  }
  72.196  #endif
  72.197 +
  72.198 +/*
  72.199 + * Local variables:
  72.200 + *  c-file-style: "linux"
  72.201 + *  indent-tabs-mode: t
  72.202 + *  c-indent-level: 8
  72.203 + *  c-basic-offset: 8
  72.204 + *  tab-width: 8
  72.205 + * End:
  72.206 + */
    73.1 --- a/tools/xenstore/xenstored_watch.h	Tue Oct 11 15:50:21 2005 -0600
    73.2 +++ b/tools/xenstore/xenstored_watch.h	Tue Oct 11 16:57:44 2005 -0600
    73.3 @@ -23,17 +23,9 @@
    73.4  #include "xenstored_core.h"
    73.5  
    73.6  void do_watch(struct connection *conn, struct buffered_data *in);
    73.7 -void do_watch_ack(struct connection *conn, const char *token);
    73.8  void do_unwatch(struct connection *conn, struct buffered_data *in);
    73.9  
   73.10 -/* Is this a watch event message for this connection? */
   73.11 -bool is_watch_event(struct connection *conn, struct buffered_data *out);
   73.12 -
   73.13 -/* Look through our watches: if any of them have an event, queue it. */
   73.14 -void queue_next_event(struct connection *conn);
   73.15 -
   73.16 -/* Fire all watches: recurse means all the children are affected (ie. rm).
   73.17 - */
   73.18 +/* Fire all watches: recurse means all the children are affected (ie. rm). */
   73.19  void fire_watches(struct connection *conn, const char *name, bool recurse);
   73.20  
   73.21  void dump_watches(struct connection *conn);
    74.1 --- a/tools/xenstore/xs.c	Tue Oct 11 15:50:21 2005 -0600
    74.2 +++ b/tools/xenstore/xs.c	Tue Oct 11 16:57:44 2005 -0600
    74.3 @@ -52,6 +52,7 @@ struct xs_handle {
    74.4           * signals waiters.
    74.5           */
    74.6  	pthread_t read_thr;
    74.7 +	int read_thr_exists;
    74.8  
    74.9  	/*
   74.10           * A list of fired watch messages, protected by a mutex. Users can
   74.11 @@ -75,11 +76,9 @@ struct xs_handle {
   74.12  
   74.13  	/* One request at a time. */
   74.14  	pthread_mutex_t request_mutex;
   74.15 -
   74.16 -	/* One transaction at a time. */
   74.17 -	pthread_mutex_t transaction_mutex;
   74.18  };
   74.19  
   74.20 +static int read_message(struct xs_handle *h);
   74.21  static void *read_thread(void *arg);
   74.22  
   74.23  int xs_fileno(struct xs_handle *h)
   74.24 @@ -134,7 +133,7 @@ static struct xs_handle *get_handle(cons
   74.25  	int fd = -1, saved_errno;
   74.26  
   74.27  	if (stat(connect_to, &buf) != 0)
   74.28 -		goto error;
   74.29 +		return NULL;
   74.30  
   74.31  	if (S_ISSOCK(buf.st_mode))
   74.32  		fd = get_socket(connect_to);
   74.33 @@ -142,11 +141,17 @@ static struct xs_handle *get_handle(cons
   74.34  		fd = get_dev(connect_to);
   74.35  
   74.36  	if (fd == -1)
   74.37 -		goto error;
   74.38 +		return NULL;
   74.39  
   74.40  	h = malloc(sizeof(*h));
   74.41 -	if (h == NULL)
   74.42 -		goto error;
   74.43 +	if (h == NULL) {
   74.44 +		saved_errno = errno;
   74.45 +		close(fd);
   74.46 +		errno = saved_errno;
   74.47 +		return NULL;
   74.48 +	}
   74.49 +
   74.50 +	memset(h, 0, sizeof(*h));
   74.51  
   74.52  	h->fd = fd;
   74.53  
   74.54 @@ -162,21 +167,8 @@ static struct xs_handle *get_handle(cons
   74.55  	pthread_cond_init(&h->reply_condvar, NULL);
   74.56  
   74.57  	pthread_mutex_init(&h->request_mutex, NULL);
   74.58 -	pthread_mutex_init(&h->transaction_mutex, NULL);
   74.59 -
   74.60 -	if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0)
   74.61 -		goto error;
   74.62  
   74.63  	return h;
   74.64 -
   74.65 - error:
   74.66 -	saved_errno = errno;
   74.67 -	if (h != NULL)
   74.68 -		free(h);
   74.69 -	if (fd != -1)
   74.70 -		close(fd);
   74.71 -	errno = saved_errno;
   74.72 -	return NULL;
   74.73  }
   74.74  
   74.75  struct xs_handle *xs_daemon_open(void)
   74.76 @@ -198,14 +190,15 @@ void xs_daemon_close(struct xs_handle *h
   74.77  {
   74.78  	struct xs_stored_msg *msg, *tmsg;
   74.79  
   74.80 -	pthread_mutex_lock(&h->transaction_mutex);
   74.81  	pthread_mutex_lock(&h->request_mutex);
   74.82  	pthread_mutex_lock(&h->reply_mutex);
   74.83  	pthread_mutex_lock(&h->watch_mutex);
   74.84  
   74.85 -	/* XXX FIXME: May leak an unpublished message buffer. */
   74.86 -	pthread_cancel(h->read_thr);
   74.87 -	pthread_join(h->read_thr, NULL);
   74.88 +	if (h->read_thr_exists) {
   74.89 +		/* XXX FIXME: May leak an unpublished message buffer. */
   74.90 +		pthread_cancel(h->read_thr);
   74.91 +		pthread_join(h->read_thr, NULL);
   74.92 +	}
   74.93  
   74.94  	list_for_each_entry_safe(msg, tmsg, &h->reply_list, list) {
   74.95  		free(msg->body);
   74.96 @@ -217,7 +210,6 @@ void xs_daemon_close(struct xs_handle *h
   74.97  		free(msg);
   74.98  	}
   74.99  
  74.100 -	pthread_mutex_unlock(&h->transaction_mutex);
  74.101  	pthread_mutex_unlock(&h->request_mutex);
  74.102  	pthread_mutex_unlock(&h->reply_mutex);
  74.103  	pthread_mutex_unlock(&h->watch_mutex);
  74.104 @@ -277,6 +269,10 @@ static void *read_reply(
  74.105  	struct xs_stored_msg *msg;
  74.106  	char *body;
  74.107  
  74.108 +	/* Read from comms channel ourselves if there is no reader thread. */
  74.109 +	if (!h->read_thr_exists && (read_message(h) == -1))
  74.110 +		return NULL;
  74.111 +
  74.112  	pthread_mutex_lock(&h->reply_mutex);
  74.113  	while (list_empty(&h->reply_list))
  74.114  		pthread_cond_wait(&h->reply_condvar, &h->reply_mutex);
  74.115 @@ -296,8 +292,10 @@ static void *read_reply(
  74.116  }
  74.117  
  74.118  /* Send message to xs, get malloc'ed reply.  NULL and set errno on error. */
  74.119 -static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type,
  74.120 -		      const struct iovec *iovec, unsigned int num_vecs,
  74.121 +static void *xs_talkv(struct xs_handle *h, struct xs_transaction_handle *t,
  74.122 +		      enum xsd_sockmsg_type type,
  74.123 +		      const struct iovec *iovec,
  74.124 +		      unsigned int num_vecs,
  74.125  		      unsigned int *len)
  74.126  {
  74.127  	struct xsd_sockmsg msg;
  74.128 @@ -306,6 +304,7 @@ static void *xs_talkv(struct xs_handle *
  74.129  	unsigned int i;
  74.130  	struct sigaction ignorepipe, oldact;
  74.131  
  74.132 +	msg.tx_id = (u32)(unsigned long)t;
  74.133  	msg.type = type;
  74.134  	msg.len = 0;
  74.135  	for (i = 0; i < num_vecs; i++)
  74.136 @@ -368,14 +367,16 @@ static void free_no_errno(void *p)
  74.137  }
  74.138  
  74.139  /* Simplified version of xs_talkv: single message. */
  74.140 -static void *xs_single(struct xs_handle *h, enum xsd_sockmsg_type type,
  74.141 -		       const char *string, unsigned int *len)
  74.142 +static void *xs_single(struct xs_handle *h, struct xs_transaction_handle *t,
  74.143 +		       enum xsd_sockmsg_type type,
  74.144 +		       const char *string,
  74.145 +		       unsigned int *len)
  74.146  {
  74.147  	struct iovec iovec;
  74.148  
  74.149  	iovec.iov_base = (void *)string;
  74.150  	iovec.iov_len = strlen(string) + 1;
  74.151 -	return xs_talkv(h, type, &iovec, 1, len);
  74.152 +	return xs_talkv(h, t, type, &iovec, 1, len);
  74.153  }
  74.154  
  74.155  static bool xs_bool(char *reply)
  74.156 @@ -386,12 +387,13 @@ static bool xs_bool(char *reply)
  74.157  	return true;
  74.158  }
  74.159  
  74.160 -char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num)
  74.161 +char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t,
  74.162 +		    const char *path, unsigned int *num)
  74.163  {
  74.164  	char *strings, *p, **ret;
  74.165  	unsigned int len;
  74.166  
  74.167 -	strings = xs_single(h, XS_DIRECTORY, path, &len);
  74.168 +	strings = xs_single(h, t, XS_DIRECTORY, path, &len);
  74.169  	if (!strings)
  74.170  		return NULL;
  74.171  
  74.172 @@ -417,16 +419,17 @@ char **xs_directory(struct xs_handle *h,
  74.173   * Returns a malloced value: call free() on it after use.
  74.174   * len indicates length in bytes, not including the nul.
  74.175   */
  74.176 -void *xs_read(struct xs_handle *h, const char *path, unsigned int *len)
  74.177 +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
  74.178 +	      const char *path, unsigned int *len)
  74.179  {
  74.180 -	return xs_single(h, XS_READ, path, len);
  74.181 +	return xs_single(h, t, XS_READ, path, len);
  74.182  }
  74.183  
  74.184  /* Write the value of a single file.
  74.185   * Returns false on failure.
  74.186   */
  74.187 -bool xs_write(struct xs_handle *h, const char *path,
  74.188 -	      const void *data, unsigned int len)
  74.189 +bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t,
  74.190 +	      const char *path, const void *data, unsigned int len)
  74.191  {
  74.192  	struct iovec iovec[2];
  74.193  
  74.194 @@ -435,36 +438,40 @@ bool xs_write(struct xs_handle *h, const
  74.195  	iovec[1].iov_base = (void *)data;
  74.196  	iovec[1].iov_len = len;
  74.197  
  74.198 -	return xs_bool(xs_talkv(h, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
  74.199 +	return xs_bool(xs_talkv(h, t, XS_WRITE, iovec,
  74.200 +				ARRAY_SIZE(iovec), NULL));
  74.201  }
  74.202  
  74.203  /* Create a new directory.
  74.204   * Returns false on failure, or success if it already exists.
  74.205   */
  74.206 -bool xs_mkdir(struct xs_handle *h, const char *path)
  74.207 +bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
  74.208 +	      const char *path)
  74.209  {
  74.210 -	return xs_bool(xs_single(h, XS_MKDIR, path, NULL));
  74.211 +	return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL));
  74.212  }
  74.213  
  74.214  /* Destroy a file or directory (directories must be empty).
  74.215   * Returns false on failure, or success if it doesn't exist.
  74.216   */
  74.217 -bool xs_rm(struct xs_handle *h, const char *path)
  74.218 +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
  74.219 +	   const char *path)
  74.220  {
  74.221 -	return xs_bool(xs_single(h, XS_RM, path, NULL));
  74.222 +	return xs_bool(xs_single(h, t, XS_RM, path, NULL));
  74.223  }
  74.224  
  74.225  /* Get permissions of node (first element is owner).
  74.226   * Returns malloced array, or NULL: call free() after use.
  74.227   */
  74.228  struct xs_permissions *xs_get_permissions(struct xs_handle *h,
  74.229 +					  struct xs_transaction_handle *t,
  74.230  					  const char *path, unsigned int *num)
  74.231  {
  74.232  	char *strings;
  74.233  	unsigned int len;
  74.234  	struct xs_permissions *ret;
  74.235  
  74.236 -	strings = xs_single(h, XS_GET_PERMS, path, &len);
  74.237 +	strings = xs_single(h, t, XS_GET_PERMS, path, &len);
  74.238  	if (!strings)
  74.239  		return NULL;
  74.240  
  74.241 @@ -490,7 +497,9 @@ struct xs_permissions *xs_get_permission
  74.242  /* Set permissions of node (must be owner).
  74.243   * Returns false on failure.
  74.244   */
  74.245 -bool xs_set_permissions(struct xs_handle *h, const char *path,
  74.246 +bool xs_set_permissions(struct xs_handle *h,
  74.247 +			struct xs_transaction_handle *t,
  74.248 +			const char *path,
  74.249  			struct xs_permissions *perms,
  74.250  			unsigned int num_perms)
  74.251  {
  74.252 @@ -512,7 +521,7 @@ bool xs_set_permissions(struct xs_handle
  74.253  			goto unwind;
  74.254  	}
  74.255  
  74.256 -	if (!xs_bool(xs_talkv(h, XS_SET_PERMS, iov, 1+num_perms, NULL)))
  74.257 +	if (!xs_bool(xs_talkv(h, t, XS_SET_PERMS, iov, 1+num_perms, NULL)))
  74.258  		goto unwind;
  74.259  	for (i = 0; i < num_perms; i++)
  74.260  		free(iov[i+1].iov_base);
  74.261 @@ -534,12 +543,24 @@ bool xs_watch(struct xs_handle *h, const
  74.262  {
  74.263  	struct iovec iov[2];
  74.264  
  74.265 +	/* We dynamically create a reader thread on demand. */
  74.266 +	pthread_mutex_lock(&h->request_mutex);
  74.267 +	if (!h->read_thr_exists) {
  74.268 +		if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0) {
  74.269 +			pthread_mutex_unlock(&h->request_mutex);
  74.270 +			return false;
  74.271 +		}
  74.272 +		h->read_thr_exists = 1;
  74.273 +	}
  74.274 +	pthread_mutex_unlock(&h->request_mutex);
  74.275 +
  74.276  	iov[0].iov_base = (void *)path;
  74.277  	iov[0].iov_len = strlen(path) + 1;
  74.278  	iov[1].iov_base = (void *)token;
  74.279  	iov[1].iov_len = strlen(token) + 1;
  74.280  
  74.281 -	return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
  74.282 +	return xs_bool(xs_talkv(h, NULL, XS_WATCH, iov,
  74.283 +				ARRAY_SIZE(iov), NULL));
  74.284  }
  74.285  
  74.286  /* Find out what node change was on (will block if nothing pending).
  74.287 @@ -593,15 +614,6 @@ char **xs_read_watch(struct xs_handle *h
  74.288  	return ret;
  74.289  }
  74.290  
  74.291 -/* Acknowledge watch on node.  Watches must be acknowledged before
  74.292 - * any other watches can be read.
  74.293 - * Returns false on failure.
  74.294 - */
  74.295 -bool xs_acknowledge_watch(struct xs_handle *h, const char *token)
  74.296 -{
  74.297 -	return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL));
  74.298 -}
  74.299 -
  74.300  /* Remove a watch on a node.
  74.301   * Returns false on failure (no watch on that node).
  74.302   */
  74.303 @@ -614,18 +626,28 @@ bool xs_unwatch(struct xs_handle *h, con
  74.304  	iov[1].iov_base = (char *)token;
  74.305  	iov[1].iov_len = strlen(token) + 1;
  74.306  
  74.307 -	return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
  74.308 +	return xs_bool(xs_talkv(h, NULL, XS_UNWATCH, iov,
  74.309 +				ARRAY_SIZE(iov), NULL));
  74.310  }
  74.311  
  74.312  /* Start a transaction: changes by others will not be seen during this
  74.313   * transaction, and changes will not be visible to others until end.
  74.314   * You can only have one transaction at any time.
  74.315 - * Returns false on failure.
  74.316 + * Returns NULL on failure.
  74.317   */
  74.318 -bool xs_transaction_start(struct xs_handle *h)
  74.319 +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h)
  74.320  {
  74.321 -	pthread_mutex_lock(&h->transaction_mutex);
  74.322 -	return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL));
  74.323 +	char *id_str;
  74.324 +	unsigned long id;
  74.325 +
  74.326 +	id_str = xs_single(h, NULL, XS_TRANSACTION_START, "", NULL);
  74.327 +	if (id_str == NULL)
  74.328 +		return NULL;
  74.329 +
  74.330 +	id = strtoul(id_str, NULL, 0);
  74.331 +	free(id_str);
  74.332 +
  74.333 +	return (struct xs_transaction_handle *)id;
  74.334  }
  74.335  
  74.336  /* End a transaction.
  74.337 @@ -633,21 +655,17 @@ bool xs_transaction_start(struct xs_hand
  74.338   * Returns false on failure, which indicates an error: transactions will
  74.339   * not fail spuriously.
  74.340   */
  74.341 -bool xs_transaction_end(struct xs_handle *h, bool abort)
  74.342 +bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
  74.343 +			bool abort)
  74.344  {
  74.345  	char abortstr[2];
  74.346 -	bool rc;
  74.347  
  74.348  	if (abort)
  74.349  		strcpy(abortstr, "F");
  74.350  	else
  74.351  		strcpy(abortstr, "T");
  74.352  	
  74.353 -	rc = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL));
  74.354 -
  74.355 -	pthread_mutex_unlock(&h->transaction_mutex);
  74.356 -
  74.357 -	return rc;
  74.358 +	return xs_bool(xs_single(h, t, XS_TRANSACTION_END, abortstr, NULL));
  74.359  }
  74.360  
  74.361  /* Introduce a new domain.
  74.362 @@ -675,7 +693,8 @@ bool xs_introduce_domain(struct xs_handl
  74.363  	iov[3].iov_base = (char *)path;
  74.364  	iov[3].iov_len = strlen(path) + 1;
  74.365  
  74.366 -	return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL));
  74.367 +	return xs_bool(xs_talkv(h, NULL, XS_INTRODUCE, iov,
  74.368 +				ARRAY_SIZE(iov), NULL));
  74.369  }
  74.370  
  74.371  bool xs_release_domain(struct xs_handle *h, domid_t domid)
  74.372 @@ -684,7 +703,7 @@ bool xs_release_domain(struct xs_handle 
  74.373  
  74.374  	sprintf(domid_str, "%u", domid);
  74.375  
  74.376 -	return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL));
  74.377 +	return xs_bool(xs_single(h, NULL, XS_RELEASE, domid_str, NULL));
  74.378  }
  74.379  
  74.380  char *xs_get_domain_path(struct xs_handle *h, domid_t domid)
  74.381 @@ -693,7 +712,7 @@ char *xs_get_domain_path(struct xs_handl
  74.382  
  74.383  	sprintf(domid_str, "%u", domid);
  74.384  
  74.385 -	return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL);
  74.386 +	return xs_single(h, NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
  74.387  }
  74.388  
  74.389  /* Only useful for DEBUG versions */
  74.390 @@ -707,68 +726,76 @@ char *xs_debug_command(struct xs_handle 
  74.391  	iov[1].iov_base = data;
  74.392  	iov[1].iov_len = len;
  74.393  
  74.394 -	return xs_talkv(h, XS_DEBUG, iov, ARRAY_SIZE(iov), NULL);
  74.395 +	return xs_talkv(h, NULL, XS_DEBUG, iov,
  74.396 +			ARRAY_SIZE(iov), NULL);
  74.397 +}
  74.398 +
  74.399 +static int read_message(struct xs_handle *h)
  74.400 +{
  74.401 +	struct xs_stored_msg *msg = NULL;
  74.402 +	char *body = NULL;
  74.403 +	int saved_errno;
  74.404 +
  74.405 +	/* Allocate message structure and read the message header. */
  74.406 +	msg = malloc(sizeof(*msg));
  74.407 +	if (msg == NULL)
  74.408 +		goto error;
  74.409 +	if (!read_all(h->fd, &msg->hdr, sizeof(msg->hdr)))
  74.410 +		goto error;
  74.411 +
  74.412 +	/* Allocate and read the message body. */
  74.413 +	body = msg->body = malloc(msg->hdr.len + 1);
  74.414 +	if (body == NULL)
  74.415 +		goto error;
  74.416 +	if (!read_all(h->fd, body, msg->hdr.len))
  74.417 +		goto error;
  74.418 +	body[msg->hdr.len] = '\0';
  74.419 +
  74.420 +	if (msg->hdr.type == XS_WATCH_EVENT) {
  74.421 +		pthread_mutex_lock(&h->watch_mutex);
  74.422 +
  74.423 +		/* Kick users out of their select() loop. */
  74.424 +		if (list_empty(&h->watch_list) &&
  74.425 +		    (h->watch_pipe[1] != -1))
  74.426 +			while (write(h->watch_pipe[1], body, 1) != 1)
  74.427 +				continue;
  74.428 +
  74.429 +		list_add_tail(&msg->list, &h->watch_list);
  74.430 +		pthread_cond_signal(&h->watch_condvar);
  74.431 +
  74.432 +		pthread_mutex_unlock(&h->watch_mutex);
  74.433 +	} else {
  74.434 +		pthread_mutex_lock(&h->reply_mutex);
  74.435 +
  74.436 +		/* There should only ever be one response pending! */
  74.437 +		if (!list_empty(&h->reply_list)) {
  74.438 +			pthread_mutex_unlock(&h->reply_mutex);
  74.439 +			goto error;
  74.440 +		}
  74.441 +
  74.442 +		list_add_tail(&msg->list, &h->reply_list);
  74.443 +		pthread_cond_signal(&h->reply_condvar);
  74.444 +
  74.445 +		pthread_mutex_unlock(&h->reply_mutex);
  74.446 +	}
  74.447 +
  74.448 +	return 0;
  74.449 +
  74.450 + error:
  74.451 +	saved_errno = errno;
  74.452 +	free(msg);
  74.453 +	free(body);
  74.454 +	errno = saved_errno;
  74.455 +	return -1;
  74.456  }
  74.457  
  74.458  static void *read_thread(void *arg)
  74.459  {
  74.460  	struct xs_handle *h = arg;
  74.461 -	struct xs_stored_msg *msg = NULL;
  74.462 -	char *body = NULL;
  74.463 -
  74.464 -	for (;;) {
  74.465 -		msg = NULL;
  74.466 -		body = NULL;
  74.467 -
  74.468 -		/* Allocate message structure and read the message header. */
  74.469 -		msg = malloc(sizeof(*msg));
  74.470 -		if (msg == NULL)
  74.471 -			goto error;
  74.472 -		if (!read_all(h->fd, &msg->hdr, sizeof(msg->hdr)))
  74.473 -			goto error;
  74.474 -
  74.475 -		/* Allocate and read the message body. */
  74.476 -		body = msg->body = malloc(msg->hdr.len + 1);
  74.477 -		if (body == NULL)
  74.478 -			goto error;
  74.479 -		if (!read_all(h->fd, body, msg->hdr.len))
  74.480 -			goto error;
  74.481 -		body[msg->hdr.len] = '\0';
  74.482 -
  74.483 -		if (msg->hdr.type == XS_WATCH_EVENT) {
  74.484 -			pthread_mutex_lock(&h->watch_mutex);
  74.485  
  74.486 -			/* Kick users out of their select() loop. */
  74.487 -			if (list_empty(&h->watch_list) &&
  74.488 -			    (h->watch_pipe[1] != -1))
  74.489 -				while (write(h->watch_pipe[1], body, 1) != 1)
  74.490 -					continue;
  74.491 -
  74.492 -			list_add_tail(&msg->list, &h->watch_list);
  74.493 -			pthread_cond_signal(&h->watch_condvar);
  74.494 -
  74.495 -			pthread_mutex_unlock(&h->watch_mutex);
  74.496 -		} else {
  74.497 -			pthread_mutex_lock(&h->reply_mutex);
  74.498 +	while (read_message(h) != -1)
  74.499 +		continue;
  74.500  
  74.501 -			/* There should only ever be one response pending! */
  74.502 -			if (!list_empty(&h->reply_list)) {
  74.503 -				pthread_mutex_unlock(&h->reply_mutex);
  74.504 -				goto error;
  74.505 -			}
  74.506 -
  74.507 -			list_add_tail(&msg->list, &h->reply_list);
  74.508 -			pthread_cond_signal(&h->reply_condvar);
  74.509 -
  74.510 -			pthread_mutex_unlock(&h->reply_mutex);
  74.511 -		}
  74.512 -	}
  74.513 -
  74.514 - error:
  74.515 -	if (body != NULL)
  74.516 -		free(body);
  74.517 -	if (msg != NULL)
  74.518 -		free(msg);
  74.519  	return NULL;
  74.520  }
  74.521  
    75.1 --- a/tools/xenstore/xs.h	Tue Oct 11 15:50:21 2005 -0600
    75.2 +++ b/tools/xenstore/xs.h	Tue Oct 11 16:57:44 2005 -0600
    75.3 @@ -23,6 +23,7 @@
    75.4  #include <xs_lib.h>
    75.5  
    75.6  struct xs_handle;
    75.7 +struct xs_transaction_handle;
    75.8  
    75.9  /* On failure, these routines set errno. */
   75.10  
   75.11 @@ -44,41 +45,47 @@ void xs_daemon_close(struct xs_handle *)
   75.12   * Returns a malloced array: call free() on it after use.
   75.13   * Num indicates size.
   75.14   */
   75.15 -char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num);
   75.16 +char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t,
   75.17 +		    const char *path, unsigned int *num);
   75.18  
   75.19  /* Get the value of a single file, nul terminated.
   75.20   * Returns a malloced value: call free() on it after use.
   75.21   * len indicates length in bytes, not including terminator.
   75.22   */
   75.23 -void *xs_read(struct xs_handle *h, const char *path, unsigned int *len);
   75.24 +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t,
   75.25 +	      const char *path, unsigned int *len);
   75.26  
   75.27  /* Write the value of a single file.
   75.28   * Returns false on failure.
   75.29   */
   75.30 -bool xs_write(struct xs_handle *h, const char *path, const void *data,
   75.31 -	      unsigned int len);
   75.32 +bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t,
   75.33 +	      const char *path, const void *data, unsigned int len);
   75.34  
   75.35  /* Create a new directory.
   75.36   * Returns false on failure, or success if it already exists.
   75.37   */
   75.38 -bool xs_mkdir(struct xs_handle *h, const char *path);
   75.39 +bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t,
   75.40 +	      const char *path);
   75.41  
   75.42  /* Destroy a file or directory (and children).
   75.43   * Returns false on failure, or success if it doesn't exist.
   75.44   */
   75.45 -bool xs_rm(struct xs_handle *h, const char *path);
   75.46 +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t,
   75.47 +	   const char *path);
   75.48  
   75.49  /* Get permissions of node (first element is owner, first perms is "other").
   75.50   * Returns malloced array, or NULL: call free() after use.
   75.51   */
   75.52  struct xs_permissions *xs_get_permissions(struct xs_handle *h,
   75.53 +					  struct xs_transaction_handle *t,
   75.54  					  const char *path, unsigned int *num);
   75.55  
   75.56  /* Set permissions of node (must be owner).
   75.57   * Returns false on failure.
   75.58   */
   75.59 -bool xs_set_permissions(struct xs_handle *h, const char *path,
   75.60 -			struct xs_permissions *perms, unsigned int num_perms);
   75.61 +bool xs_set_permissions(struct xs_handle *h, struct xs_transaction_handle *t,
   75.62 +			const char *path, struct xs_permissions *perms,
   75.63 +			unsigned int num_perms);
   75.64  
   75.65  /* Watch a node for changes (poll on fd to detect, or call read_watch()).
   75.66   * When the node (or any child) changes, fd will become readable.
   75.67 @@ -96,12 +103,6 @@ int xs_fileno(struct xs_handle *h);
   75.68   */
   75.69  char **xs_read_watch(struct xs_handle *h, unsigned int *num);
   75.70  
   75.71 -/* Acknowledge watch on node.  Watches must be acknowledged before
   75.72 - * any other watches can be read.
   75.73 - * Returns false on failure.
   75.74 - */
   75.75 -bool xs_acknowledge_watch(struct xs_handle *h, const char *token);
   75.76 -
   75.77  /* Remove a watch on a node: implicitly acks any outstanding watch.
   75.78   * Returns false on failure (no watch on that node).
   75.79   */
   75.80 @@ -110,16 +111,17 @@ bool xs_unwatch(struct xs_handle *h, con
   75.81  /* Start a transaction: changes by others will not be seen during this
   75.82   * transaction, and changes will not be visible to others until end.
   75.83   * You can only have one transaction at any time.
   75.84 - * Returns false on failure.
   75.85 + * Returns NULL on failure.
   75.86   */
   75.87 -bool xs_transaction_start(struct xs_handle *h);
   75.88 +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h);
   75.89  
   75.90  /* End a transaction.
   75.91   * If abandon is true, transaction is discarded instead of committed.
   75.92   * Returns false on failure: if errno == EAGAIN, you have to restart
   75.93   * transaction.
   75.94   */
   75.95 -bool xs_transaction_end(struct xs_handle *h, bool abort);
   75.96 +bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t,
   75.97 +			bool abort);
   75.98  
   75.99  /* Introduce a new domain.
  75.100   * This tells the store daemon about a shared memory page, event channel
  75.101 @@ -142,3 +144,13 @@ char *xs_debug_command(struct xs_handle 
  75.102  		       void *data, unsigned int len);
  75.103  
  75.104  #endif /* _XS_H */
  75.105 +
  75.106 +/*
  75.107 + * Local variables:
  75.108 + *  c-file-style: "linux"
  75.109 + *  indent-tabs-mode: t
  75.110 + *  c-indent-level: 8
  75.111 + *  c-basic-offset: 8
  75.112 + *  tab-width: 8
  75.113 + * End:
  75.114 + */
    76.1 --- a/tools/xenstore/xs_test.c	Tue Oct 11 15:50:21 2005 -0600
    76.2 +++ b/tools/xenstore/xs_test.c	Tue Oct 11 16:57:44 2005 -0600
    76.3 @@ -42,6 +42,7 @@
    76.4  #define XSTEST
    76.5  
    76.6  static struct xs_handle *handles[10] = { NULL };
    76.7 +static struct xs_transaction_handle *txh[10] = { NULL };
    76.8  
    76.9  static unsigned int timeout_ms = 500;
   76.10  static bool timeout_suppressed = true;
   76.11 @@ -201,7 +202,6 @@ static void __attribute__((noreturn)) us
   76.12  	     "  watch <path> <token>\n"
   76.13  	     "  watchnoack <path> <token>\n"
   76.14  	     "  waitwatch\n"
   76.15 -	     "  ackwatch <token>\n"
   76.16  	     "  unwatch <path> <token>\n"
   76.17  	     "  close\n"
   76.18  	     "  start <node>\n"
   76.19 @@ -313,7 +313,7 @@ static void do_dir(unsigned int handle, 
   76.20  	char **entries;
   76.21  	unsigned int i, num;
   76.22  
   76.23 -	entries = xs_directory(handles[handle], path, &num);
   76.24 +	entries = xs_directory(handles[handle], txh[handle], path, &num);
   76.25  	if (!entries) {
   76.26  		failed(handle);
   76.27  		return;
   76.28 @@ -332,7 +332,7 @@ static void do_read(unsigned int handle,
   76.29  	char *value;
   76.30  	unsigned int len;
   76.31  
   76.32 -	value = xs_read(handles[handle], path, &len);
   76.33 +	value = xs_read(handles[handle], txh[handle], path, &len);
   76.34  	if (!value) {
   76.35  		failed(handle);
   76.36  		return;
   76.37 @@ -348,7 +348,7 @@ static void do_read(unsigned int handle,
   76.38  
   76.39  static void do_write(unsigned int handle, char *path, char *data)
   76.40  {
   76.41 -	if (!xs_write(handles[handle], path, data, strlen(data)))
   76.42 +	if (!xs_write(handles[handle], txh[handle], path, data, strlen(data)))
   76.43  		failed(handle);
   76.44  }
   76.45  
   76.46 @@ -361,13 +361,13 @@ static void do_setid(unsigned int handle
   76.47  
   76.48  static void do_mkdir(unsigned int handle, char *path)
   76.49  {
   76.50 -	if (!xs_mkdir(handles[handle], path))
   76.51 +	if (!xs_mkdir(handles[handle], txh[handle], path))
   76.52  		failed(handle);
   76.53  }
   76.54  
   76.55  static void do_rm(unsigned int handle, char *path)
   76.56  {
   76.57 -	if (!xs_rm(handles[handle], path))
   76.58 +	if (!xs_rm(handles[handle], txh[handle], path))
   76.59  		failed(handle);
   76.60  }
   76.61  
   76.62 @@ -376,7 +376,7 @@ static void do_getperm(unsigned int hand
   76.63  	unsigned int i, num;
   76.64  	struct xs_permissions *perms;
   76.65  
   76.66 -	perms = xs_get_permissions(handles[handle], path, &num);
   76.67 +	perms = xs_get_permissions(handles[handle], txh[handle], path, &num);
   76.68  	if (!perms) {
   76.69  		failed(handle);
   76.70  		return;
   76.71 @@ -437,7 +437,7 @@ static void do_setperm(unsigned int hand
   76.72  			barf("bad flags %s\n", arg);
   76.73  	}
   76.74  
   76.75 -	if (!xs_set_permissions(handles[handle], path, perms, i))
   76.76 +	if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i))
   76.77  		failed(handle);
   76.78  }
   76.79  
   76.80 @@ -455,8 +455,6 @@ static void do_watch(unsigned int handle
   76.81  		    !streq(vec[XS_WATCH_PATH], node) ||
   76.82  		    !streq(vec[XS_WATCH_TOKEN], token))
   76.83  			failed(handle);
   76.84 -		if (!xs_acknowledge_watch(handles[handle], token))
   76.85 -			failed(handle);
   76.86  	}
   76.87  }
   76.88  
   76.89 @@ -515,12 +513,6 @@ static void do_waitwatch(unsigned int ha
   76.90  	free(vec);
   76.91  }
   76.92  
   76.93 -static void do_ackwatch(unsigned int handle, const char *token)
   76.94 -{
   76.95 -	if (!xs_acknowledge_watch(handles[handle], token))
   76.96 -		failed(handle);
   76.97 -}
   76.98 -
   76.99  static void do_unwatch(unsigned int handle, const char *node, const char *token)
  76.100  {
  76.101  	if (!xs_unwatch(handles[handle], node, token))
  76.102 @@ -529,14 +521,16 @@ static void do_unwatch(unsigned int hand
  76.103  
  76.104  static void do_start(unsigned int handle)
  76.105  {
  76.106 -	if (!xs_transaction_start(handles[handle]))
  76.107 +	txh[handle] = xs_transaction_start(handles[handle]);
  76.108 +	if (txh[handle] == NULL)
  76.109  		failed(handle);
  76.110  }
  76.111  
  76.112  static void do_end(unsigned int handle, bool abort)
  76.113  {
  76.114 -	if (!xs_transaction_end(handles[handle], abort))
  76.115 +	if (!xs_transaction_end(handles[handle], txh[handle], abort))
  76.116  		failed(handle);
  76.117 +	txh[handle] = NULL;
  76.118  }
  76.119  
  76.120  static void do_introduce(unsigned int handle,
  76.121 @@ -626,7 +620,8 @@ static void dump_dir(unsigned int handle
  76.122  
  76.123  		sprintf(subnode, "%s/%s", node, dir[i]);
  76.124  
  76.125 -		perms = xs_get_permissions(handles[handle], subnode,&numperms);
  76.126 +		perms = xs_get_permissions(handles[handle], txh[handle],
  76.127 +					   subnode,&numperms);
  76.128  		if (!perms) {
  76.129  			failed(handle);
  76.130  			return;
  76.131 @@ -643,7 +638,8 @@ static void dump_dir(unsigned int handle
  76.132  		output("\n");
  76.133  
  76.134  		/* Even directories can have contents. */
  76.135 -		contents = xs_read(handles[handle], subnode, &len);
  76.136 +		contents = xs_read(handles[handle], txh[handle], 
  76.137 +				   subnode, &len);
  76.138  		if (!contents) {
  76.139  			if (errno != EISDIR)
  76.140  				failed(handle);
  76.141 @@ -653,7 +649,8 @@ static void dump_dir(unsigned int handle
  76.142  		}			
  76.143  
  76.144  		/* Every node is a directory. */
  76.145 -		subdirs = xs_directory(handles[handle], subnode, &subnum);
  76.146 +		subdirs = xs_directory(handles[handle], txh[handle], 
  76.147 +				       subnode, &subnum);
  76.148  		if (!subdirs) {
  76.149  			failed(handle);
  76.150  			return;
  76.151 @@ -668,7 +665,7 @@ static void dump(int handle)
  76.152  	char **subdirs;
  76.153  	unsigned int subnum;
  76.154  
  76.155 -	subdirs = xs_directory(handles[handle], "/", &subnum);
  76.156 +	subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum);
  76.157  	if (!subdirs) {
  76.158  		failed(handle);
  76.159  		return;
  76.160 @@ -746,13 +743,12 @@ static void do_command(unsigned int defa
  76.161  		do_watch(handle, arg(line, 1), arg(line, 2), false);
  76.162  	else if (streq(command, "waitwatch"))
  76.163  		do_waitwatch(handle);
  76.164 -	else if (streq(command, "ackwatch"))
  76.165 -		do_ackwatch(handle, arg(line, 1));
  76.166  	else if (streq(command, "unwatch"))
  76.167  		do_unwatch(handle, arg(line, 1), arg(line, 2));
  76.168  	else if (streq(command, "close")) {
  76.169  		xs_daemon_close(handles[handle]);
  76.170  		handles[handle] = NULL;
  76.171 +		txh[handle] = NULL;
  76.172  	} else if (streq(command, "start"))
  76.173  		do_start(handle);
  76.174  	else if (streq(command, "commit"))
  76.175 @@ -836,3 +832,13 @@ int main(int argc, char *argv[])
  76.176  
  76.177  	return 0;
  76.178  }
  76.179 +
  76.180 +/*
  76.181 + * Local variables:
  76.182 + *  c-file-style: "linux"
  76.183 + *  indent-tabs-mode: t
  76.184 + *  c-indent-level: 8
  76.185 + *  c-basic-offset: 8
  76.186 + *  tab-width: 8
  76.187 + * End:
  76.188 + */
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/tools/xenstore/xsls.c	Tue Oct 11 16:57:44 2005 -0600
    77.3 @@ -0,0 +1,47 @@
    77.4 +#include <stdio.h>
    77.5 +#include <stdlib.h>
    77.6 +#include <string.h>
    77.7 +#include <err.h>
    77.8 +#include <xs.h>
    77.9 +
   77.10 +void print_dir(struct xs_handle *h, char *path, int cur_depth)
   77.11 +{
   77.12 +    char **e;
   77.13 +    char newpath[512], *val;
   77.14 +    int num, i, len;
   77.15 +
   77.16 +    e = xs_directory(h, NULL, path, &num);
   77.17 +    if (e == NULL)
   77.18 +        err(1, "xs_directory (%s)", path);
   77.19 +
   77.20 +    for (i = 0; i<num; i++) {
   77.21 +        int j;
   77.22 +        for (j=0; j<cur_depth; j++) printf(" ");
   77.23 +        printf("%s", e[i]);
   77.24 +        sprintf(newpath, "%s%s%s", path, 
   77.25 +                path[strlen(path)-1] == '/' ? "" : "/", 
   77.26 +                e[i]);
   77.27 +        val = xs_read(h, NULL, newpath, &len);
   77.28 +        if (val == NULL)
   77.29 +            printf(":\n");
   77.30 +        else if ((unsigned)len > (151 - strlen(e[i])))
   77.31 +            printf(" = \"%.*s...\"\n", 148 - strlen(e[i]), val);
   77.32 +        else
   77.33 +            printf(" = \"%s\"\n", val);
   77.34 +        free(val);
   77.35 +        print_dir(h, newpath, cur_depth+1); 
   77.36 +    }
   77.37 +    free(e);
   77.38 +}
   77.39 +
   77.40 +int main(int argc, char *argv[])
   77.41 +{
   77.42 +    struct xs_handle *xsh = xs_daemon_open();
   77.43 +
   77.44 +    if (xsh == NULL)
   77.45 +        err(1, "xs_daemon_open");
   77.46 +
   77.47 +    print_dir(xsh, argc == 1 ? "/" : argv[1], 0);
   77.48 +
   77.49 +    return 0;
   77.50 +}
    78.1 --- a/xen/Makefile	Tue Oct 11 15:50:21 2005 -0600
    78.2 +++ b/xen/Makefile	Tue Oct 11 16:57:44 2005 -0600
    78.3 @@ -95,7 +95,7 @@ include/xen/compile.h: include/xen/compi
    78.4  	    -e 's/@@version@@/$(XEN_VERSION)/g' \
    78.5  	    -e 's/@@subversion@@/$(XEN_SUBVERSION)/g' \
    78.6  	    -e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \
    78.7 -	    -e 's!@@changeset@@!$(shell (hg parents | awk -F: '/^changeset/{CS=$$3};{FS="date:[ ]+"}/^date/{D=$$2}; END {print D, CS}') 2>/dev/null || (head -n 6 ChangeLog | awk -F: '/^changeset/{CS=$$3};{FS="date:[ ]+"}/^date/{D=$$2}; END {print D, CS}') 2>/dev/null || echo information unavailable)!g' \
    78.8 +	    -e 's!@@changeset@@!$(shell ((hg parents || head -n 7 ../ChangeLog || echo date: unavailable) | awk '{FS="changeset:[ ]+"}/^changeset/{CS=$$2};{FS="date:[ ]+"}/^date/{D=$$2}; END {print D, CS}') 2>/dev/null)!g' \
    78.9  	    < include/xen/compile.h.in > $@.new
   78.10  	@cat include/xen/banner.h >> $@.new
   78.11  	@mv -f $@.new $@
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/xen/include/public/io/console.h	Tue Oct 11 16:57:44 2005 -0600
    79.3 @@ -0,0 +1,23 @@
    79.4 +/******************************************************************************
    79.5 + * console.h
    79.6 + * 
    79.7 + * Console I/O interface for Xen guest OSes.
    79.8 + * 
    79.9 + * Copyright (c) 2005, Keir Fraser
   79.10 + */
   79.11 +
   79.12 +#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
   79.13 +#define __XEN_PUBLIC_IO_CONSOLE_H__
   79.14 +
   79.15 +typedef u32 XENCONS_RING_IDX;
   79.16 +
   79.17 +#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
   79.18 +
   79.19 +struct xencons_interface {
   79.20 +    char in[1024];
   79.21 +    char out[2048];
   79.22 +    XENCONS_RING_IDX in_cons, in_prod;
   79.23 +    XENCONS_RING_IDX out_cons, out_prod;
   79.24 +};
   79.25 +
   79.26 +#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
    80.1 --- a/xen/include/public/io/xs_wire.h	Tue Oct 11 15:50:21 2005 -0600
    80.2 +++ b/xen/include/public/io/xs_wire.h	Tue Oct 11 16:57:44 2005 -0600
    80.3 @@ -30,25 +30,23 @@
    80.4  
    80.5  enum xsd_sockmsg_type
    80.6  {
    80.7 -	XS_DEBUG,
    80.8 -	XS_DIRECTORY,
    80.9 -	XS_READ,
   80.10 -	XS_GET_PERMS,
   80.11 -	XS_WATCH,
   80.12 -	XS_WATCH_ACK,
   80.13 -	XS_UNWATCH,
   80.14 -	XS_TRANSACTION_START,
   80.15 -	XS_TRANSACTION_END,
   80.16 -	XS_OP_READ_ONLY = XS_TRANSACTION_END,
   80.17 -	XS_INTRODUCE,
   80.18 -	XS_RELEASE,
   80.19 -	XS_GET_DOMAIN_PATH,
   80.20 -	XS_WRITE,
   80.21 -	XS_MKDIR,
   80.22 -	XS_RM,
   80.23 -	XS_SET_PERMS,
   80.24 -	XS_WATCH_EVENT,
   80.25 -	XS_ERROR,
   80.26 +    XS_DEBUG,
   80.27 +    XS_DIRECTORY,
   80.28 +    XS_READ,
   80.29 +    XS_GET_PERMS,
   80.30 +    XS_WATCH,
   80.31 +    XS_UNWATCH,
   80.32 +    XS_TRANSACTION_START,
   80.33 +    XS_TRANSACTION_END,
   80.34 +    XS_INTRODUCE,
   80.35 +    XS_RELEASE,
   80.36 +    XS_GET_DOMAIN_PATH,
   80.37 +    XS_WRITE,
   80.38 +    XS_MKDIR,
   80.39 +    XS_RM,
   80.40 +    XS_SET_PERMS,
   80.41 +    XS_WATCH_EVENT,
   80.42 +    XS_ERROR,
   80.43  };
   80.44  
   80.45  #define XS_WRITE_NONE "NONE"
   80.46 @@ -58,38 +56,40 @@ enum xsd_sockmsg_type
   80.47  /* We hand errors as strings, for portability. */
   80.48  struct xsd_errors
   80.49  {
   80.50 -	int errnum;
   80.51 -	const char *errstring;
   80.52 +    int errnum;
   80.53 +    const char *errstring;
   80.54  };
   80.55  #define XSD_ERROR(x) { x, #x }
   80.56  static struct xsd_errors xsd_errors[] __attribute__((unused)) = {
   80.57 -	XSD_ERROR(EINVAL),
   80.58 -	XSD_ERROR(EACCES),
   80.59 -	XSD_ERROR(EEXIST),
   80.60 -	XSD_ERROR(EISDIR),
   80.61 -	XSD_ERROR(ENOENT),
   80.62 -	XSD_ERROR(ENOMEM),
   80.63 -	XSD_ERROR(ENOSPC),
   80.64 -	XSD_ERROR(EIO),
   80.65 -	XSD_ERROR(ENOTEMPTY),
   80.66 -	XSD_ERROR(ENOSYS),
   80.67 -	XSD_ERROR(EROFS),
   80.68 -	XSD_ERROR(EBUSY),
   80.69 -	XSD_ERROR(EAGAIN),
   80.70 -	XSD_ERROR(EISCONN),
   80.71 +    XSD_ERROR(EINVAL),
   80.72 +    XSD_ERROR(EACCES),
   80.73 +    XSD_ERROR(EEXIST),
   80.74 +    XSD_ERROR(EISDIR),
   80.75 +    XSD_ERROR(ENOENT),
   80.76 +    XSD_ERROR(ENOMEM),
   80.77 +    XSD_ERROR(ENOSPC),
   80.78 +    XSD_ERROR(EIO),
   80.79 +    XSD_ERROR(ENOTEMPTY),
   80.80 +    XSD_ERROR(ENOSYS),
   80.81 +    XSD_ERROR(EROFS),
   80.82 +    XSD_ERROR(EBUSY),
   80.83 +    XSD_ERROR(EAGAIN),
   80.84 +    XSD_ERROR(EISCONN),
   80.85  };
   80.86  struct xsd_sockmsg
   80.87  {
   80.88 -	u32 type;
   80.89 -	u32 len; 		/* Length of data following this. */
   80.90 +    u32 type;  /* XS_??? */
   80.91 +    u32 req_id;/* Request identifier, echoed in daemon's response.  */
   80.92 +    u32 tx_id; /* Transaction id (0 if not related to a transaction). */
   80.93 +    u32 len;   /* Length of data following this. */
   80.94  
   80.95 -	/* Generally followed by nul-terminated string(s). */
   80.96 +    /* Generally followed by nul-terminated string(s). */
   80.97  };
   80.98  
   80.99  enum xs_watch_type
  80.100  {
  80.101 -	XS_WATCH_PATH = 0,
  80.102 -	XS_WATCH_TOKEN,
  80.103 +    XS_WATCH_PATH = 0,
  80.104 +    XS_WATCH_TOKEN,
  80.105  };
  80.106  
  80.107  #endif /* _XS_WIRE_H */