[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merged
# HG changeset patch # User djm@xxxxxxxxxxxxxxx # Node ID 74d56b7ff46cb07fbf7dbb72cad4e14e9d22324f # Parent 333f722ed6d05d80e341a72f19bad4143c94cd87 # Parent 4e335372ace84b605cebc36a42610caadb09a4d8 Merged diff -r 333f722ed6d0 -r 74d56b7ff46c .hgignore --- a/.hgignore Tue Oct 11 21:50:21 2005 +++ b/.hgignore Tue Oct 11 22:57:44 2005 @@ -161,6 +161,7 @@ ^tools/xenstore/xs_tdb_dump$ ^tools/xenstore/xs_test$ ^tools/xenstore/xs_watch_stress$ +^tools/xenstore/xsls$ ^tools/xentrace/xenctx$ ^tools/xentrace/xentrace$ ^xen/BLOG$ diff -r 333f722ed6d0 -r 74d56b7ff46c Makefile --- a/Makefile Tue Oct 11 21:50:21 2005 +++ b/Makefile Tue Oct 11 22:57:44 2005 @@ -66,7 +66,7 @@ $(MAKE) -C tools install install-kernels: - for i in $(XKERNELS) ; do $(MAKE) $$i-build || exit 1; done + for i in $(XKERNELS) ; do $(MAKE) $$i-install || exit 1; done install-docs: sh ./docs/check_pkgs && $(MAKE) -C docs install || true @@ -179,7 +179,7 @@ rm -rf $(D)/usr/$(LIBDIR)/libxenctrl* $(D)/usr/$(LIBDIR)/libxenguest* rm -rf $(D)/usr/$(LIBDIR)/libxenstore* rm -rf $(D)/usr/$(LIBDIR)/python/xen $(D)/usr/$(LIBDIR)/xen - rm -rf $(D)/usr/libexec/xen + rm -rf $(D)/usr/$(LIBDIR)/xen/bin rm -rf $(D)/usr/sbin/xen* $(D)/usr/sbin/netfix $(D)/usr/sbin/xm rm -rf $(D)/usr/share/doc/xen rm -rf $(D)/usr/share/xen diff -r 333f722ed6d0 -r 74d56b7ff46c buildconfigs/Rules.mk --- a/buildconfigs/Rules.mk Tue Oct 11 21:50:21 2005 +++ b/buildconfigs/Rules.mk Tue Oct 11 22:57:44 2005 @@ -87,8 +87,16 @@ touch $@ # update timestamp to avoid rebuild endif -%-build: +%-install: $(MAKE) -f buildconfigs/mk.$* build + +%-dist: DESTDIR=$(DISTDIR)/install +%-dist: %-install + @: # do nothing + +# Legacy dist target +%-build: %-dist + @: # do nothing %-delete: $(MAKE) -f buildconfigs/mk.$* delete diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/arch/xen/boot/Makefile --- a/linux-2.6-xen-sparse/arch/xen/boot/Makefile Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/arch/xen/boot/Makefile Tue Oct 11 22:57:44 2005 @@ -8,4 +8,4 @@ $(call if_changed,objcopy) bzImage: vmlinuz - $(Q)$(LN) -sf ../../../vmlinuz $(srctree)/arch/xen/boot/bzImage + $(Q)ln -sf ../../../vmlinuz $(srctree)/arch/xen/boot/bzImage diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Tue Oct 11 22:57:44 2005 @@ -1327,18 +1327,14 @@ .callback = handle_vcpu_hotplug_event }; -/* NB: Assumes xenbus_lock is held! */ static int setup_cpu_watcher(struct notifier_block *notifier, unsigned long event, void *data) { - int err = 0; - - BUG_ON(down_trylock(&xenbus_lock) == 0); + int err; + err = register_xenbus_watch(&cpu_watch); - - if (err) { + if (err) printk("Failed to register watch on /cpu\n"); - } return NOTIFY_DONE; } @@ -1368,7 +1364,7 @@ return; /* get the state value */ - err = xenbus_scanf(dir, "availability", "%s", state); + err = xenbus_scanf(NULL, dir, "availability", "%s", state); if (err != 1) { printk(KERN_ERR @@ -1578,7 +1574,7 @@ void smp_resume(void) { smp_intr_init(); - local_setup_timer_irq(); + local_setup_timer(); } void vcpu_prepare(int vcpu) diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Tue Oct 11 22:57:44 2005 @@ -122,7 +122,7 @@ static u64 processed_system_time; /* System time (ns) at last processing. */ static DEFINE_PER_CPU(u64, processed_system_time); -#define NS_PER_TICK (1000000000L/HZ) +#define NS_PER_TICK (1000000000ULL/HZ) static inline void __normalize_time(time_t *sec, s64 *nsec) { @@ -800,9 +800,9 @@ delta = j - jiffies; /* NB. The next check can trigger in some wrap-around cases, * but that's ok: we'll just end up with a shorter timeout. */ - if (delta < 1) + if (delta < 1) delta = 1; - st = processed_system_time + (delta * NS_PER_TICK); + st = processed_system_time + ((u64)delta * NS_PER_TICK); } while (read_seqretry(&xtime_lock, seq)); return st; @@ -816,7 +816,7 @@ { unsigned int cpu = smp_processor_id(); unsigned long j; - + /* s390 does this /before/ checking rcu_pending(). We copy them. */ cpu_set(cpu, nohz_cpu_mask); diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Tue Oct 11 22:57:44 2005 @@ -270,26 +270,28 @@ } } -static void shutdown_handler(struct xenbus_watch *watch, const char *node) +static void shutdown_handler(struct xenbus_watch *watch, + const char **vec, unsigned int len) { static DECLARE_WORK(shutdown_work, __shutdown_handler, NULL); char *str; + struct xenbus_transaction *xbt; int err; again: - err = xenbus_transaction_start(); - if (err) + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) return; - str = (char *)xenbus_read("control", "shutdown", NULL); + str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ if (XENBUS_IS_ERR_READ(str)) { - xenbus_transaction_end(1); + xenbus_transaction_end(xbt, 1); return; } - xenbus_write("control", "shutdown", ""); - - err = xenbus_transaction_end(0); + xenbus_write(xbt, "control", "shutdown", ""); + + err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { kfree(str); goto again; @@ -315,26 +317,28 @@ } #ifdef CONFIG_MAGIC_SYSRQ -static void sysrq_handler(struct xenbus_watch *watch, const char *node) +static void sysrq_handler(struct xenbus_watch *watch, const char **vec, + unsigned int len) { char sysrq_key = '\0'; + struct xenbus_transaction *xbt; int err; again: - err = xenbus_transaction_start(); - if (err) + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) return; - if (!xenbus_scanf("control", "sysrq", "%c", &sysrq_key)) { + if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) { printk(KERN_ERR "Unable to read sysrq code in " "control/sysrq\n"); - xenbus_transaction_end(1); + xenbus_transaction_end(xbt, 1); return; } if (sysrq_key != '\0') - xenbus_printf("control", "sysrq", "%c", '\0'); - - err = xenbus_transaction_end(0); + xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); + + err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; @@ -358,9 +362,6 @@ static struct notifier_block xenstore_notifier; -/* Setup our watcher - NB: Assumes xenbus_lock is held! -*/ static int setup_shutdown_watcher(struct notifier_block *notifier, unsigned long event, void *data) @@ -369,8 +370,6 @@ #ifdef CONFIG_MAGIC_SYSRQ int err2 = 0; #endif - - BUG_ON(down_trylock(&xenbus_lock) == 0); err1 = register_xenbus_watch(&shutdown_watch); #ifdef CONFIG_MAGIC_SYSRQ @@ -411,4 +410,3 @@ * tab-width: 8 * End: */ -# diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Tue Oct 11 22:57:44 2005 @@ -357,7 +357,7 @@ unsigned long long new_target; int err; - err = xenbus_scanf("memory", "target", "%llu", &new_target); + err = xenbus_scanf(NULL, "memory", "target", "%llu", &new_target); if (err != 1) { printk(KERN_ERR "Unable to read memory/target\n"); return; @@ -370,16 +370,11 @@ } -/* Setup our watcher - NB: Assumes xenbus_lock is held! -*/ int balloon_init_watcher(struct notifier_block *notifier, unsigned long event, void *data) { int err; - - BUG_ON(down_trylock(&xenbus_lock) == 0); err = register_xenbus_watch(&target_watch); if (err) diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Tue Oct 11 22:57:44 2005 @@ -61,18 +61,19 @@ unsigned long ring_ref; unsigned int evtchn; int err; + struct xenbus_transaction *xbt; struct backend_info *be = container_of(watch, struct backend_info, watch); /* If other end is gone, delete ourself. */ - if (vec && !xenbus_exists(be->frontpath, "")) { + if (vec && !xenbus_exists(NULL, be->frontpath, "")) { device_unregister(&be->dev->dev); return; } if (be->blkif == NULL || be->blkif->status == CONNECTED) return; - err = xenbus_gather(be->frontpath, "ring-ref", "%lu", &ring_ref, + err = xenbus_gather(NULL, be->frontpath, "ring-ref", "%lu", &ring_ref, "event-channel", "%u", &evtchn, NULL); if (err) { xenbus_dev_error(be->dev, err, @@ -84,7 +85,8 @@ /* Map the shared frame, irq etc. */ err = blkif_map(be->blkif, ring_ref, evtchn); if (err) { - xenbus_dev_error(be->dev, err, "mapping ring-ref %lu port %u", + xenbus_dev_error(be->dev, err, + "mapping ring-ref %lu port %u", ring_ref, evtchn); return; } @@ -92,13 +94,13 @@ again: /* Supply the information about the device the frontend needs */ - err = xenbus_transaction_start(); - if (err) { + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) { xenbus_dev_error(be->dev, err, "starting transaction"); return; } - err = xenbus_printf(be->dev->nodename, "sectors", "%lu", + err = xenbus_printf(xbt, be->dev->nodename, "sectors", "%lu", vbd_size(&be->blkif->vbd)); if (err) { xenbus_dev_error(be->dev, err, "writing %s/sectors", @@ -107,14 +109,14 @@ } /* FIXME: use a typename instead */ - err = xenbus_printf(be->dev->nodename, "info", "%u", + err = xenbus_printf(xbt, be->dev->nodename, "info", "%u", vbd_info(&be->blkif->vbd)); if (err) { xenbus_dev_error(be->dev, err, "writing %s/info", be->dev->nodename); goto abort; } - err = xenbus_printf(be->dev->nodename, "sector-size", "%lu", + err = xenbus_printf(xbt, be->dev->nodename, "sector-size", "%lu", vbd_secsize(&be->blkif->vbd)); if (err) { xenbus_dev_error(be->dev, err, "writing %s/sector-size", @@ -122,7 +124,7 @@ goto abort; } - err = xenbus_transaction_end(0); + err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) { @@ -136,7 +138,7 @@ return; abort: - xenbus_transaction_end(1); + xenbus_transaction_end(xbt, 1); } /* @@ -154,7 +156,8 @@ = container_of(watch, struct backend_info, backend_watch); struct xenbus_device *dev = be->dev; - err = xenbus_scanf(dev->nodename, "physical-device", "%li", &pdev); + err = xenbus_scanf(NULL, dev->nodename, + "physical-device", "%li", &pdev); if (XENBUS_EXIST_ERR(err)) return; if (err < 0) { @@ -169,7 +172,7 @@ be->pdev = pdev; /* If there's a read-only node, we're read only. */ - p = xenbus_read(dev->nodename, "read-only", NULL); + p = xenbus_read(NULL, dev->nodename, "read-only", NULL); if (!IS_ERR(p)) { be->readonly = 1; kfree(p); @@ -184,7 +187,8 @@ if (IS_ERR(be->blkif)) { err = PTR_ERR(be->blkif); be->blkif = NULL; - xenbus_dev_error(dev, err, "creating block interface"); + xenbus_dev_error(dev, err, + "creating block interface"); return; } @@ -192,7 +196,8 @@ if (err) { blkif_put(be->blkif); be->blkif = NULL; - xenbus_dev_error(dev, err, "creating vbd structure"); + xenbus_dev_error(dev, err, + "creating vbd structure"); return; } @@ -210,13 +215,14 @@ be = kmalloc(sizeof(*be), GFP_KERNEL); if (!be) { - xenbus_dev_error(dev, -ENOMEM, "allocating backend structure"); + xenbus_dev_error(dev, -ENOMEM, + "allocating backend structure"); return -ENOMEM; } memset(be, 0, sizeof(*be)); frontend = NULL; - err = xenbus_gather(dev->nodename, + err = xenbus_gather(NULL, dev->nodename, "frontend-id", "%li", &be->frontend_id, "frontend", NULL, &frontend, NULL); @@ -228,7 +234,7 @@ dev->nodename); goto free_be; } - if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) { + if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) { /* If we can't get a frontend path and a frontend-id, * then our bus-id is no longer valid and we need to * destroy the backend device. @@ -244,7 +250,8 @@ err = register_xenbus_watch(&be->backend_watch); if (err) { be->backend_watch.node = NULL; - xenbus_dev_error(dev, err, "adding backend watch on %s", + xenbus_dev_error(dev, err, + "adding backend watch on %s", dev->nodename); goto free_be; } diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Tue Oct 11 22:57:44 2005 @@ -460,7 +460,7 @@ if (info->connected == BLKIF_STATE_CONNECTED) return; - err = xenbus_gather(watch->node, + err = xenbus_gather(NULL, watch->node, "sectors", "%lu", §ors, "info", "%u", &binfo, "sector-size", "%lu", §or_size, @@ -532,10 +532,11 @@ { char *backend; const char *message; + struct xenbus_transaction *xbt; int err; backend = NULL; - err = xenbus_gather(dev->nodename, + err = xenbus_gather(NULL, dev->nodename, "backend-id", "%i", &info->backend_id, "backend", NULL, &backend, NULL); @@ -559,25 +560,26 @@ } again: - err = xenbus_transaction_start(); - if (err) { + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) { xenbus_dev_error(dev, err, "starting transaction"); goto destroy_blkring; } - err = xenbus_printf(dev->nodename, "ring-ref","%u", info->ring_ref); + err = xenbus_printf(xbt, dev->nodename, + "ring-ref","%u", info->ring_ref); if (err) { message = "writing ring-ref"; goto abort_transaction; } - err = xenbus_printf(dev->nodename, + err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", info->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } - err = xenbus_transaction_end(0); + err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) goto again; @@ -598,8 +600,7 @@ return 0; abort_transaction: - xenbus_transaction_end(1); - /* Have to do this *outside* transaction. */ + xenbus_transaction_end(xbt, 1); xenbus_dev_error(dev, err, "%s", message); destroy_blkring: blkif_free(info); @@ -620,7 +621,8 @@ struct blkfront_info *info; /* FIXME: Use dynamic device id if this is not set. */ - err = xenbus_scanf(dev->nodename, "virtual-device", "%i", &vdevice); + err = xenbus_scanf(NULL, dev->nodename, + "virtual-device", "%i", &vdevice); if (XENBUS_EXIST_ERR(err)) return err; if (err < 0) { diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Tue Oct 11 22:57:44 2005 @@ -160,7 +160,8 @@ mi = ((major_info[index] != NULL) ? major_info[index] : xlbd_alloc_major_info(major, minor, index)); - mi->usage++; + if (mi) + mi->usage++; return mi; } diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c --- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Tue Oct 11 22:57:44 2005 @@ -20,69 +20,48 @@ #include <linux/sched.h> #include <linux/err.h> #include "xencons_ring.h" - -struct ring_head -{ - u32 cons; - u32 prod; - char buf[0]; -} __attribute__((packed)); +#include <asm-xen/xen-public/io/console.h> static int xencons_irq; +static xencons_receiver_func *xencons_receiver; -#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head)) -#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE) -#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE) - -static inline struct ring_head *outring(void) +static inline struct xencons_interface *xencons_interface(void) { return mfn_to_virt(xen_start_info->console_mfn); } -static inline struct ring_head *inring(void) -{ - return mfn_to_virt(xen_start_info->console_mfn) + PAGE_SIZE/2; -} - - -/* don't block - write as much as possible and return */ -static int __xencons_ring_send( - struct ring_head *ring, const char *data, unsigned len) -{ - int copied = 0; - - mb(); - while (copied < len && !XENCONS_FULL(ring)) { - ring->buf[XENCONS_IDX(ring->prod)] = data[copied]; - ring->prod++; - copied++; - } - mb(); - - return copied; -} - int xencons_ring_send(const char *data, unsigned len) { - int sent = __xencons_ring_send(outring(), data, len); + int sent = 0; + struct xencons_interface *intf = xencons_interface(); + + while ((sent < len) && + (intf->out_prod - intf->out_cons) < sizeof(intf->out)) { + intf->out[MASK_XENCONS_IDX(intf->out_prod, intf->out)] = + data[sent]; + intf->out_prod++; + sent++; + } + /* Use evtchn: this is called early, before irq is set up. */ notify_remote_via_evtchn(xen_start_info->console_evtchn); + return sent; } - -static xencons_receiver_func *xencons_receiver; - static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs) { - struct ring_head *ring = inring(); - while (ring->cons < ring->prod) { - if (xencons_receiver != NULL) { - xencons_receiver(ring->buf + XENCONS_IDX(ring->cons), - 1, regs); - } - ring->cons++; + struct xencons_interface *intf = xencons_interface(); + + while (intf->in_cons != intf->in_prod) { + if (xencons_receiver != NULL) + xencons_receiver( + intf->in + MASK_XENCONS_IDX(intf->in_cons, + intf->in), + 1, regs); + intf->in_cons++; } + return IRQ_HANDLED; } @@ -96,7 +75,7 @@ int err; if (xencons_irq) - unbind_evtchn_from_irqhandler(xencons_irq, inring()); + unbind_evtchn_from_irqhandler(xencons_irq, NULL); xencons_irq = 0; if (!xen_start_info->console_evtchn) @@ -104,7 +83,7 @@ err = bind_evtchn_to_irqhandler( xen_start_info->console_evtchn, - handle_input, 0, "xencons", inring()); + handle_input, 0, "xencons", NULL); if (err <= 0) { xprintk("XEN console request irq failed %i\n", err); return err; diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Tue Oct 11 22:57:44 2005 @@ -69,15 +69,15 @@ int i; /* If other end is gone, delete ourself. */ - if (vec && !xenbus_exists(be->frontpath, "")) { - xenbus_rm(be->dev->nodename, ""); + if (vec && !xenbus_exists(NULL, be->frontpath, "")) { + xenbus_rm(NULL, be->dev->nodename, ""); device_unregister(&be->dev->dev); return; } if (be->netif == NULL || be->netif->status == CONNECTED) return; - mac = xenbus_read(be->frontpath, "mac", NULL); + mac = xenbus_read(NULL, be->frontpath, "mac", NULL); if (IS_ERR(mac)) { err = PTR_ERR(mac); xenbus_dev_error(be->dev, err, "reading %s/mac", @@ -98,7 +98,8 @@ } kfree(mac); - err = xenbus_gather(be->frontpath, "tx-ring-ref", "%lu", &tx_ring_ref, + err = xenbus_gather(NULL, be->frontpath, + "tx-ring-ref", "%lu", &tx_ring_ref, "rx-ring-ref", "%lu", &rx_ring_ref, "event-channel", "%u", &evtchn, NULL); if (err) { @@ -137,7 +138,7 @@ struct xenbus_device *dev = be->dev; u8 be_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; - err = xenbus_scanf(dev->nodename, "handle", "%li", &handle); + err = xenbus_scanf(NULL, dev->nodename, "handle", "%li", &handle); if (XENBUS_EXIST_ERR(err)) return; if (err < 0) { @@ -188,7 +189,7 @@ key = env_vars; while (*key != NULL) { - val = xenbus_read(xdev->nodename, *key, NULL); + val = xenbus_read(NULL, xdev->nodename, *key, NULL); if (!IS_ERR(val)) { char buf[strlen(*key) + 4]; sprintf(buf, "%s=%%s", *key); @@ -220,7 +221,7 @@ memset(be, 0, sizeof(*be)); frontend = NULL; - err = xenbus_gather(dev->nodename, + err = xenbus_gather(NULL, dev->nodename, "frontend-id", "%li", &be->frontend_id, "frontend", NULL, &frontend, NULL); @@ -232,7 +233,7 @@ dev->nodename); goto free_be; } - if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) { + if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) { /* If we can't get a frontend path and a frontend-id, * then our bus-id is no longer valid and we need to * destroy the backend device. diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Tue Oct 11 22:57:44 2005 @@ -1083,10 +1083,11 @@ { char *backend, *mac, *e, *s; const char *message; + struct xenbus_transaction *xbt; int err, i; backend = NULL; - err = xenbus_gather(dev->nodename, + err = xenbus_gather(NULL, dev->nodename, "backend-id", "%i", &info->backend_id, "backend", NULL, &backend, NULL); @@ -1102,7 +1103,7 @@ goto out; } - mac = xenbus_read(dev->nodename, "mac", NULL); + mac = xenbus_read(NULL, dev->nodename, "mac", NULL); if (IS_ERR(mac)) { err = PTR_ERR(mac); xenbus_dev_error(dev, err, "reading %s/mac", @@ -1131,32 +1132,32 @@ } again: - err = xenbus_transaction_start(); - if (err) { + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) { xenbus_dev_error(dev, err, "starting transaction"); goto destroy_ring; } - err = xenbus_printf(dev->nodename, "tx-ring-ref","%u", + err = xenbus_printf(xbt, dev->nodename, "tx-ring-ref","%u", info->tx_ring_ref); if (err) { message = "writing tx ring-ref"; goto abort_transaction; } - err = xenbus_printf(dev->nodename, "rx-ring-ref","%u", + err = xenbus_printf(xbt, dev->nodename, "rx-ring-ref","%u", info->rx_ring_ref); if (err) { message = "writing rx ring-ref"; goto abort_transaction; } - err = xenbus_printf(dev->nodename, + err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", info->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } - err = xenbus_transaction_end(0); + err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) goto again; @@ -1177,8 +1178,7 @@ return 0; abort_transaction: - xenbus_transaction_end(1); - /* Have to do this *outside* transaction. */ + xenbus_transaction_end(xbt, 1); xenbus_dev_error(dev, err, "%s", message); destroy_ring: shutdown_device(info); @@ -1201,7 +1201,7 @@ struct netfront_info *info; unsigned int handle; - err = xenbus_scanf(dev->nodename, "handle", "%u", &handle); + err = xenbus_scanf(NULL, dev->nodename, "handle", "%u", &handle); if (XENBUS_EXIST_ERR(err)) return err; if (err < 0) { diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Tue Oct 11 22:57:44 2005 @@ -246,7 +246,10 @@ PAGE_SHIFT); ret = xen_start_info->store_mfn; - /* We'll return then this will wait for daemon to answer */ + /* + ** Complete initialization of xenbus (viz. set up the + ** connection to xenstored now that it has started). + */ kthread_run(do_xenbus_probe, NULL, "xenbus_probe"); } break; diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Tue Oct 11 22:57:44 2005 @@ -66,12 +66,13 @@ unsigned int evtchn; unsigned long ready = 1; int err; + struct xenbus_transaction *xbt; struct backend_info *be = container_of(watch, struct backend_info, watch); /* If other end is gone, delete ourself. */ - if (vec && !xenbus_exists(be->frontpath, "")) { - xenbus_rm(be->dev->nodename, ""); + if (vec && !xenbus_exists(NULL, be->frontpath, "")) { + xenbus_rm(NULL, be->dev->nodename, ""); device_unregister(&be->dev->dev); return; } @@ -79,7 +80,7 @@ if (be->tpmif == NULL || be->tpmif->status == CONNECTED) return; - err = xenbus_gather(be->frontpath, + err = xenbus_gather(NULL, be->frontpath, "ring-ref", "%lu", &ringref, "event-channel", "%u", &evtchn, NULL); if (err) { @@ -115,20 +116,20 @@ * unless something bad happens */ again: - err = xenbus_transaction_start(); - if (err) { + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) { xenbus_dev_error(be->dev, err, "starting transaction"); return; } - err = xenbus_printf(be->dev->nodename, + err = xenbus_printf(xbt, be->dev->nodename, "ready", "%lu", ready); if (err) { xenbus_dev_error(be->dev, err, "writing 'ready'"); goto abort; } - err = xenbus_transaction_end(0); + err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) { @@ -139,7 +140,7 @@ xenbus_dev_ok(be->dev); return; abort: - xenbus_transaction_end(1); + xenbus_transaction_end(xbt, 1); } @@ -152,7 +153,7 @@ = container_of(watch, struct backend_info, backend_watch); struct xenbus_device *dev = be->dev; - err = xenbus_scanf(dev->nodename, "instance", "%li", &instance); + err = xenbus_scanf(NULL, dev->nodename, "instance", "%li", &instance); if (XENBUS_EXIST_ERR(err)) return; if (err < 0) { @@ -205,7 +206,7 @@ memset(be, 0, sizeof(*be)); frontend = NULL; - err = xenbus_gather(dev->nodename, + err = xenbus_gather(NULL, dev->nodename, "frontend-id", "%li", &be->frontend_id, "frontend", NULL, &frontend, NULL); @@ -217,7 +218,7 @@ dev->nodename); goto free_be; } - if (strlen(frontend) == 0 || !xenbus_exists(frontend, "")) { + if (strlen(frontend) == 0 || !xenbus_exists(NULL, frontend, "")) { /* If we can't get a frontend path and a frontend-id, * then our bus-id is no longer valid and we need to * destroy the backend device. diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Tue Oct 11 22:57:44 2005 @@ -226,7 +226,7 @@ if (tp->connected) return; - err = xenbus_gather(watch->node, + err = xenbus_gather(NULL, watch->node, "ready", "%lu", &ready, NULL); if (err) { @@ -311,9 +311,10 @@ const char *message; int err; int backend_id; + struct xenbus_transaction *xbt; backend = NULL; - err = xenbus_gather(dev->nodename, + err = xenbus_gather(NULL, dev->nodename, "backend-id", "%i", &backend_id, "backend", NULL, &backend, NULL); @@ -339,27 +340,27 @@ } again: - err = xenbus_transaction_start(); - if (err) { + xbt = xenbus_transaction_start(); + if (IS_ERR(xbt)) { xenbus_dev_error(dev, err, "starting transaction"); goto destroy_tpmring; } - err = xenbus_printf(dev->nodename, + err = xenbus_printf(xbt, dev->nodename, "ring-ref","%u", info->ring_ref); if (err) { message = "writing ring-ref"; goto abort_transaction; } - err = xenbus_printf(dev->nodename, + err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", my_private.evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } - err = xenbus_transaction_end(0); + err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) { @@ -380,8 +381,7 @@ return 0; abort_transaction: - xenbus_transaction_end(1); - /* Have to do this *outside* transaction. */ + xenbus_transaction_end(xbt, 1); xenbus_dev_error(dev, err, "%s", message); destroy_tpmring: destroy_tpmring(info, &my_private); @@ -399,7 +399,7 @@ struct tpmfront_info *info; int handle; - err = xenbus_scanf(dev->nodename, + err = xenbus_scanf(NULL, dev->nodename, "handle", "%i", &handle); if (XENBUS_EXIST_ERR(err)) return err; diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Tue Oct 11 22:57:44 2005 @@ -128,19 +128,16 @@ void *dst; unsigned int avail; - wait_event(xb_waitq, output_avail(out)); - - /* Read, then check: not that we don't trust store. - * Hell, some of my best friends are daemons. But, - * in this post-911 world... */ + wait_event_interruptible(xb_waitq, output_avail(out)); + + mb(); h = *out; - mb(); - if (!check_buffer(&h)) { - set_current_state(TASK_RUNNING); - return -EIO; /* ETERRORIST! */ - } + if (!check_buffer(&h)) + return -EIO; dst = get_output_chunk(&h, out->buf, &avail); + if (avail == 0) + continue; if (avail > len) avail = len; memcpy(dst, data, avail); @@ -172,15 +169,16 @@ unsigned int avail; const char *src; - wait_event(xb_waitq, xs_input_avail()); + wait_event_interruptible(xb_waitq, xs_input_avail()); + + mb(); h = *in; - mb(); - if (!check_buffer(&h)) { - set_current_state(TASK_RUNNING); + if (!check_buffer(&h)) return -EIO; - } src = get_input_chunk(&h, in->buf, &avail); + if (avail == 0) + continue; if (avail > len) avail = len; was_full = !output_avail(&h); @@ -195,10 +193,6 @@ notify_remote_via_evtchn(xen_start_info->store_evtchn); } - /* If we left something, wake watch thread to deal with it. */ - if (xs_input_avail()) - wake_up(&xb_waitq); - return 0; } diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Tue Oct 11 22:57:44 2005 @@ -45,86 +45,132 @@ #include <asm-xen/xen_proc.h> #include <asm/hypervisor.h> +struct xenbus_dev_transaction { + struct list_head list; + struct xenbus_transaction *handle; +}; + struct xenbus_dev_data { - /* Are there bytes left to be read in this message? */ - int bytes_left; - /* Are we still waiting for the reply to a message we wrote? */ - int awaiting_reply; - /* Buffer for outgoing messages. */ + /* In-progress transaction. */ + struct list_head transactions; + + /* Partial request. */ unsigned int len; union { struct xsd_sockmsg msg; char buffer[PAGE_SIZE]; } u; + + /* Response queue. */ +#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1)) + char read_buffer[PAGE_SIZE]; + unsigned int read_cons, read_prod; + wait_queue_head_t read_waitq; }; static struct proc_dir_entry *xenbus_dev_intf; -/* Reply can be long (dir, getperm): don't buffer, just examine - * headers so we can discard rest if they die. */ static ssize_t xenbus_dev_read(struct file *filp, char __user *ubuf, size_t len, loff_t *ppos) { - struct xenbus_dev_data *data = filp->private_data; - struct xsd_sockmsg msg; - int err; - - /* Refill empty buffer? */ - if (data->bytes_left == 0) { - if (len < sizeof(msg)) - return -EINVAL; - - err = xb_read(&msg, sizeof(msg)); - if (err) - return err; - data->bytes_left = msg.len; - if (ubuf && copy_to_user(ubuf, &msg, sizeof(msg)) != 0) - return -EFAULT; - /* We can receive spurious XS_WATCH_EVENT messages. */ - if (msg.type != XS_WATCH_EVENT) - data->awaiting_reply = 0; - return sizeof(msg); - } - - /* Don't read over next header, or over temporary buffer. */ - if (len > sizeof(data->u.buffer)) - len = sizeof(data->u.buffer); - if (len > data->bytes_left) - len = data->bytes_left; - - err = xb_read(data->u.buffer, len); - if (err) - return err; - - data->bytes_left -= len; - if (ubuf && copy_to_user(ubuf, data->u.buffer, len) != 0) - return -EFAULT; - return len; -} - -/* We do v. basic sanity checking so they don't screw up kernel later. */ + struct xenbus_dev_data *u = filp->private_data; + int i; + + if (wait_event_interruptible(u->read_waitq, + u->read_prod != u->read_cons)) + return -EINTR; + + for (i = 0; i < len; i++) { + if (u->read_cons == u->read_prod) + break; + put_user(u->read_buffer[MASK_READ_IDX(u->read_cons)], ubuf+i); + u->read_cons++; + } + + return i; +} + +static void queue_reply(struct xenbus_dev_data *u, + char *data, unsigned int len) +{ + int i; + + for (i = 0; i < len; i++, u->read_prod++) + u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i]; + + BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer)); + + wake_up(&u->read_waitq); +} + static ssize_t xenbus_dev_write(struct file *filp, const char __user *ubuf, size_t len, loff_t *ppos) { - struct xenbus_dev_data *data = filp->private_data; - int err; - - /* We gather data in buffer until we're ready to send it. */ - if (len > data->len + sizeof(data->u)) + struct xenbus_dev_data *u = filp->private_data; + struct xenbus_dev_transaction *trans; + void *reply; + int err = 0; + + if ((len + u->len) > sizeof(u->u.buffer)) return -EINVAL; - if (copy_from_user(data->u.buffer + data->len, ubuf, len) != 0) + + if (copy_from_user(u->u.buffer + u->len, ubuf, len) != 0) return -EFAULT; - data->len += len; - if (data->len >= sizeof(data->u.msg) + data->u.msg.len) { - err = xb_write(data->u.buffer, data->len); - if (err) - return err; - data->len = 0; - data->awaiting_reply = 1; - } - return len; + + u->len += len; + if (u->len < (sizeof(u->u.msg) + u->u.msg.len)) + return len; + + switch (u->u.msg.type) { + case XS_TRANSACTION_START: + case XS_TRANSACTION_END: + case XS_DIRECTORY: + case XS_READ: + case XS_GET_PERMS: + case XS_RELEASE: + case XS_GET_DOMAIN_PATH: + case XS_WRITE: + case XS_MKDIR: + case XS_RM: + case XS_SET_PERMS: + reply = xenbus_dev_request_and_reply(&u->u.msg); + if (IS_ERR(reply)) { + err = PTR_ERR(reply); + } else { + if (u->u.msg.type == XS_TRANSACTION_START) { + trans = kmalloc(sizeof(*trans), GFP_KERNEL); + trans->handle = (struct xenbus_transaction *) + simple_strtoul(reply, NULL, 0); + list_add(&trans->list, &u->transactions); + } else if (u->u.msg.type == XS_TRANSACTION_END) { + list_for_each_entry(trans, &u->transactions, + list) + if ((unsigned long)trans->handle == + (unsigned long)u->u.msg.tx_id) + break; + BUG_ON(&trans->list == &u->transactions); + list_del(&trans->list); + kfree(trans); + } + queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg)); + queue_reply(u, (char *)reply, u->u.msg.len); + kfree(reply); + } + break; + + default: + err = -EINVAL; + break; + } + + if (err == 0) { + u->len = 0; + err = len; + } + + return err; } static int xenbus_dev_open(struct inode *inode, struct file *filp) @@ -134,7 +180,6 @@ if (xen_start_info->store_evtchn == 0) return -ENOENT; - /* Don't try seeking. */ nonseekable_open(inode, filp); u = kmalloc(sizeof(*u), GFP_KERNEL); @@ -142,28 +187,26 @@ return -ENOMEM; memset(u, 0, sizeof(*u)); + INIT_LIST_HEAD(&u->transactions); + init_waitqueue_head(&u->read_waitq); filp->private_data = u; - down(&xenbus_lock); - return 0; } static int xenbus_dev_release(struct inode *inode, struct file *filp) { - struct xenbus_dev_data *data = filp->private_data; - - /* Discard any unread replies. */ - while (data->bytes_left || data->awaiting_reply) - xenbus_dev_read(filp, NULL, sizeof(data->u.buffer), NULL); - - /* Harmless if no transaction in progress. */ - xenbus_transaction_end(1); - - up(&xenbus_lock); - - kfree(data); + struct xenbus_dev_data *u = filp->private_data; + struct xenbus_dev_transaction *trans, *tmp; + + list_for_each_entry_safe(trans, tmp, &u->transactions, list) { + xenbus_transaction_end(trans->handle, 1); + list_del(&trans->list); + kfree(trans); + } + + kfree(u); return 0; } diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Tue Oct 11 22:57:44 2005 @@ -125,7 +125,7 @@ devid = strrchr(nodename, '/') + 1; - err = xenbus_gather(nodename, "frontend-id", "%i", &domid, + err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid, "frontend", NULL, &frontend, NULL); if (err) @@ -133,7 +133,7 @@ if (strlen(frontend) == 0) err = -ERANGE; - if (!err && !xenbus_exists(frontend, "")) + if (!err && !xenbus_exists(NULL, frontend, "")) err = -ENOENT; if (err) { @@ -229,18 +229,13 @@ static int xenbus_register_driver_common(struct xenbus_driver *drv, struct xen_bus_type *bus) { - int err; - drv->driver.name = drv->name; drv->driver.bus = &bus->bus; drv->driver.owner = drv->owner; drv->driver.probe = xenbus_dev_probe; drv->driver.remove = xenbus_dev_remove; - down(&xenbus_lock); - err = driver_register(&drv->driver); - up(&xenbus_lock); - return err; + return driver_register(&drv->driver); } int xenbus_register_driver(struct xenbus_driver *drv) @@ -256,9 +251,7 @@ void xenbus_unregister_driver(struct xenbus_driver *drv) { - down(&xenbus_lock); driver_unregister(&drv->driver); - up(&xenbus_lock); } EXPORT_SYMBOL(xenbus_unregister_driver); @@ -447,7 +440,7 @@ if (!nodename) return -ENOMEM; - dir = xenbus_directory(nodename, "", &dir_n); + dir = xenbus_directory(NULL, nodename, "", &dir_n); if (IS_ERR(dir)) { kfree(nodename); return PTR_ERR(dir); @@ -470,7 +463,7 @@ unsigned int dir_n = 0; int i; - dir = xenbus_directory(bus->root, type, &dir_n); + dir = xenbus_directory(NULL, bus->root, type, &dir_n); if (IS_ERR(dir)) return PTR_ERR(dir); @@ -489,7 +482,7 @@ char **dir; unsigned int i, dir_n; - dir = xenbus_directory(bus->root, "", &dir_n); + dir = xenbus_directory(NULL, bus->root, "", &dir_n); if (IS_ERR(dir)) return PTR_ERR(dir); @@ -535,7 +528,7 @@ if (char_count(node, '/') < 2) return; - exists = xenbus_exists(node, ""); + exists = xenbus_exists(NULL, node, ""); if (!exists) { xenbus_cleanup_devices(node, &bus->bus); return; @@ -621,26 +614,22 @@ void xenbus_suspend(void) { - /* We keep lock, so no comms can happen as page moves. */ - down(&xenbus_lock); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev); + xs_suspend(); } void xenbus_resume(void) { xb_init_comms(); - reregister_xenbus_watches(); + xs_resume(); bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev); - up(&xenbus_lock); } int register_xenstore_notifier(struct notifier_block *nb) { int ret = 0; - - down(&xenbus_lock); if (xen_start_info->store_evtchn) { ret = nb->notifier_call(nb, 0, NULL); @@ -648,26 +637,26 @@ notifier_chain_register(&xenstore_chain, nb); } - up(&xenbus_lock); - return ret; } EXPORT_SYMBOL(register_xenstore_notifier); void unregister_xenstore_notifier(struct notifier_block *nb) { - down(&xenbus_lock); notifier_chain_unregister(&xenstore_chain, nb); - up(&xenbus_lock); } EXPORT_SYMBOL(unregister_xenstore_notifier); -/* called from a thread in privcmd/privcmd.c */ +/* +** Called either from below xenbus_probe_init() initcall (for domUs) +** or, for dom0, from a thread created in privcmd/privcmd.c (after +** the user-space tools have invoked initDomainStore()) +*/ int do_xenbus_probe(void *unused) { int err = 0; - /* Initialize xenstore comms unless already done. */ + /* Initialize the interface to xenstore. */ err = xs_init(); if (err) { printk("XENBUS: Error initializing xenstore comms:" @@ -675,16 +664,17 @@ return err; } - down(&xenbus_lock); /* Enumerate devices in xenstore. */ xenbus_probe_devices(&xenbus_frontend); xenbus_probe_devices(&xenbus_backend); + /* Watch for changes. */ register_xenbus_watch(&fe_watch); register_xenbus_watch(&be_watch); + /* Notify others that xenstore is up */ notifier_call_chain(&xenstore_chain, 0, 0); - up(&xenbus_lock); + return 0; } @@ -698,6 +688,10 @@ device_register(&xenbus_frontend.dev); device_register(&xenbus_backend.dev); + /* + ** Domain0 doesn't have a store_evtchn yet - this will + ** be set up later by xend invoking initDomainStore() + */ if (!xen_start_info->store_evtchn) return 0; diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Tue Oct 11 22:57:44 2005 @@ -42,11 +42,58 @@ #define streq(a, b) (strcmp((a), (b)) == 0) -static char printf_buffer[4096]; +struct xs_stored_msg { + struct list_head list; + + struct xsd_sockmsg hdr; + + union { + /* Queued replies. */ + struct { + char *body; + } reply; + + /* Queued watch events. */ + struct { + struct xenbus_watch *handle; + char **vec; + unsigned int vec_size; + } watch; + } u; +}; + +struct xs_handle { + /* A list of replies. Currently only one will ever be outstanding. */ + struct list_head reply_list; + spinlock_t reply_lock; + wait_queue_head_t reply_waitq; + + /* One request at a time. */ + struct semaphore request_mutex; + + /* Protect transactions against save/restore. */ + struct rw_semaphore suspend_mutex; +}; + +static struct xs_handle xs_state; + +/* List of registered watches, and a lock to protect it. */ static LIST_HEAD(watches); - -DECLARE_MUTEX(xenbus_lock); -EXPORT_SYMBOL(xenbus_lock); +static DEFINE_SPINLOCK(watches_lock); + +/* List of pending watch calbback events, and a lock to protect it. */ +static LIST_HEAD(watch_events); +static DEFINE_SPINLOCK(watch_events_lock); + +/* + * Details of the xenwatch callback kernel thread. The thread waits on the + * watch_events_waitq for work to do (queued on watch_events list). When it + * wakes up it acquires the xenwatch_mutex before reading the list and + * carrying out work. + */ +static pid_t xenwatch_pid; +static DECLARE_MUTEX(xenwatch_mutex); +static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq); static int get_error(const char *errorstring) { @@ -65,47 +112,82 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) { - struct xsd_sockmsg msg; - void *ret; - int err; - - err = xb_read(&msg, sizeof(msg)); - if (err) - return ERR_PTR(err); - - ret = kmalloc(msg.len + 1, GFP_KERNEL); - if (!ret) - return ERR_PTR(-ENOMEM); - - err = xb_read(ret, msg.len); - if (err) { - kfree(ret); - return ERR_PTR(err); - } - ((char*)ret)[msg.len] = '\0'; - - *type = msg.type; + struct xs_stored_msg *msg; + char *body; + + spin_lock(&xs_state.reply_lock); + + while (list_empty(&xs_state.reply_list)) { + spin_unlock(&xs_state.reply_lock); + wait_event_interruptible(xs_state.reply_waitq, + !list_empty(&xs_state.reply_list)); + spin_lock(&xs_state.reply_lock); + } + + msg = list_entry(xs_state.reply_list.next, + struct xs_stored_msg, list); + list_del(&msg->list); + + spin_unlock(&xs_state.reply_lock); + + *type = msg->hdr.type; if (len) - *len = msg.len; - return ret; + *len = msg->hdr.len; + body = msg->u.reply.body; + + kfree(msg); + + return body; } /* Emergency write. */ void xenbus_debug_write(const char *str, unsigned int count) { - struct xsd_sockmsg msg; + struct xsd_sockmsg msg = { 0 }; msg.type = XS_DEBUG; msg.len = sizeof("print") + count + 1; + down(&xs_state.request_mutex); xb_write(&msg, sizeof(msg)); xb_write("print", sizeof("print")); xb_write(str, count); xb_write("", 1); + up(&xs_state.request_mutex); +} + +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) +{ + void *ret; + struct xsd_sockmsg req_msg = *msg; + int err; + + if (req_msg.type == XS_TRANSACTION_START) + down_read(&xs_state.suspend_mutex); + + down(&xs_state.request_mutex); + + err = xb_write(msg, sizeof(*msg) + msg->len); + if (err) { + msg->type = XS_ERROR; + ret = ERR_PTR(err); + } else { + ret = read_reply(&msg->type, &msg->len); + } + + up(&xs_state.request_mutex); + + if ((msg->type == XS_TRANSACTION_END) || + ((req_msg.type == XS_TRANSACTION_START) && + (msg->type == XS_ERROR))) + up_read(&xs_state.suspend_mutex); + + return ret; } /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ -static void *xs_talkv(enum xsd_sockmsg_type type, +static void *xs_talkv(struct xenbus_transaction *t, + enum xsd_sockmsg_type type, const struct kvec *iovec, unsigned int num_vecs, unsigned int *len) @@ -115,31 +197,34 @@ unsigned int i; int err; - WARN_ON(down_trylock(&xenbus_lock) == 0); - + msg.tx_id = (u32)(unsigned long)t; msg.type = type; msg.len = 0; for (i = 0; i < num_vecs; i++) msg.len += iovec[i].iov_len; + down(&xs_state.request_mutex); + err = xb_write(&msg, sizeof(msg)); - if (err) + if (err) { + up(&xs_state.request_mutex); return ERR_PTR(err); + } for (i = 0; i < num_vecs; i++) { err = xb_write(iovec[i].iov_base, iovec[i].iov_len);; - if (err) + if (err) { + up(&xs_state.request_mutex); return ERR_PTR(err); - } - - /* Watches can have fired before reply comes: daemon detects - * and re-transmits, so we can ignore this. */ - do { - kfree(ret); - ret = read_reply(&msg.type, len); - if (IS_ERR(ret)) - return ret; - } while (msg.type == XS_WATCH_EVENT); + } + } + + ret = read_reply(&msg.type, len); + + up(&xs_state.request_mutex); + + if (IS_ERR(ret)) + return ret; if (msg.type == XS_ERROR) { err = get_error(ret); @@ -152,14 +237,16 @@ } /* Simplified version of xs_talkv: single message. */ -static void *xs_single(enum xsd_sockmsg_type type, - const char *string, unsigned int *len) +static void *xs_single(struct xenbus_transaction *t, + enum xsd_sockmsg_type type, + const char *string, + unsigned int *len) { struct kvec iovec; iovec.iov_base = (void *)string; iovec.iov_len = strlen(string) + 1; - return xs_talkv(type, &iovec, 1, len); + return xs_talkv(t, type, &iovec, 1, len); } /* Many commands only need an ack, don't care what it says. */ @@ -182,20 +269,22 @@ return num; } -/* Return the path to dir with /name appended. */ +/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */ static char *join(const char *dir, const char *name) { - static char buffer[4096]; - - BUG_ON(down_trylock(&xenbus_lock) == 0); - /* XXX FIXME: might not be correct if name == "" */ - BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer)); + char *buffer; + + buffer = kmalloc(strlen(dir) + strlen("/") + strlen(name) + 1, + GFP_KERNEL); + if (buffer == NULL) + return ERR_PTR(-ENOMEM); strcpy(buffer, dir); if (!streq(name, "")) { strcat(buffer, "/"); strcat(buffer, name); } + return buffer; } @@ -207,7 +296,7 @@ *num = count_strings(strings, len); /* Transfer to one big alloc for easy freeing. */ - ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC); + ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL); if (!ret) { kfree(strings); return ERR_PTR(-ENOMEM); @@ -222,12 +311,18 @@ return ret; } -char **xenbus_directory(const char *dir, const char *node, unsigned int *num) -{ - char *strings; +char **xenbus_directory(struct xenbus_transaction *t, + const char *dir, const char *node, unsigned int *num) +{ + char *strings, *path; unsigned int len; - strings = xs_single(XS_DIRECTORY, join(dir, node), &len); + path = join(dir, node); + if (IS_ERR(path)) + return (char **)path; + + strings = xs_single(t, XS_DIRECTORY, path, &len); + kfree(path); if (IS_ERR(strings)) return (char **)strings; @@ -236,12 +331,13 @@ EXPORT_SYMBOL(xenbus_directory); /* Check if a path exists. Return 1 if it does. */ -int xenbus_exists(const char *dir, const char *node) +int xenbus_exists(struct xenbus_transaction *t, + const char *dir, const char *node) { char **d; int dir_n; - d = xenbus_directory(dir, node, &dir_n); + d = xenbus_directory(t, dir, node, &dir_n); if (IS_ERR(d)) return 0; kfree(d); @@ -253,78 +349,133 @@ * Returns a kmalloced value: call free() on it after use. * len indicates length in bytes. */ -void *xenbus_read(const char *dir, const char *node, unsigned int *len) -{ - return xs_single(XS_READ, join(dir, node), len); +void *xenbus_read(struct xenbus_transaction *t, + const char *dir, const char *node, unsigned int *len) +{ + char *path; + void *ret; + + path = join(dir, node); + if (IS_ERR(path)) + return (void *)path; + + ret = xs_single(t, XS_READ, path, len); + kfree(path); + return ret; } EXPORT_SYMBOL(xenbus_read); /* Write the value of a single file. * Returns -err on failure. */ -int xenbus_write(const char *dir, const char *node, const char *string) +int xenbus_write(struct xenbus_transaction *t, + const char *dir, const char *node, const char *string) { const char *path; struct kvec iovec[2]; + int ret; path = join(dir, node); + if (IS_ERR(path)) + return PTR_ERR(path); iovec[0].iov_base = (void *)path; iovec[0].iov_len = strlen(path) + 1; iovec[1].iov_base = (void *)string; iovec[1].iov_len = strlen(string); - return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); + ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); + kfree(path); + return ret; } EXPORT_SYMBOL(xenbus_write); /* Create a new directory. */ -int xenbus_mkdir(const char *dir, const char *node) -{ - return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL)); +int xenbus_mkdir(struct xenbus_transaction *t, + const char *dir, const char *node) +{ + char *path; + int ret; + + path = join(dir, node); + if (IS_ERR(path)) + return PTR_ERR(path); + + ret = xs_error(xs_single(t, XS_MKDIR, path, NULL)); + kfree(path); + return ret; } EXPORT_SYMBOL(xenbus_mkdir); /* Destroy a file or directory (directories must be empty). */ -int xenbus_rm(const char *dir, const char *node) -{ - return xs_error(xs_single(XS_RM, join(dir, node), NULL)); +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node) +{ + char *path; + int ret; + + path = join(dir, node); + if (IS_ERR(path)) + return PTR_ERR(path); + + ret = xs_error(xs_single(t, XS_RM, path, NULL)); + kfree(path); + return ret; } EXPORT_SYMBOL(xenbus_rm); /* Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. - * You can only have one transaction at any time. */ -int xenbus_transaction_start(void) -{ - return xs_error(xs_single(XS_TRANSACTION_START, "", NULL)); +struct xenbus_transaction *xenbus_transaction_start(void) +{ + char *id_str; + unsigned long id; + + down_read(&xs_state.suspend_mutex); + + id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL); + if (IS_ERR(id_str)) { + up_read(&xs_state.suspend_mutex); + return (struct xenbus_transaction *)id_str; + } + + id = simple_strtoul(id_str, NULL, 0); + kfree(id_str); + + return (struct xenbus_transaction *)id; } EXPORT_SYMBOL(xenbus_transaction_start); /* End a transaction. * If abandon is true, transaction is discarded instead of committed. */ -int xenbus_transaction_end(int abort) +int xenbus_transaction_end(struct xenbus_transaction *t, int abort) { char abortstr[2]; + int err; if (abort) strcpy(abortstr, "F"); else strcpy(abortstr, "T"); - return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL)); + + err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL)); + + up_read(&xs_state.suspend_mutex); + + return err; } EXPORT_SYMBOL(xenbus_transaction_end); /* Single read and scanf: returns -errno or num scanned. */ -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) +int xenbus_scanf(struct xenbus_transaction *t, + const char *dir, const char *node, const char *fmt, ...) { va_list ap; int ret; char *val; - val = xenbus_read(dir, node, NULL); + val = xenbus_read(t, dir, node, NULL); if (IS_ERR(val)) return PTR_ERR(val); @@ -340,18 +491,28 @@ EXPORT_SYMBOL(xenbus_scanf); /* Single printf and write: returns -errno or 0. */ -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...) +int xenbus_printf(struct xenbus_transaction *t, + const char *dir, const char *node, const char *fmt, ...) { va_list ap; int ret; - - BUG_ON(down_trylock(&xenbus_lock) == 0); +#define PRINTF_BUFFER_SIZE 4096 + char *printf_buffer; + + printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); + if (printf_buffer == NULL) + return -ENOMEM; + va_start(ap, fmt); - ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap); + ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap); va_end(ap); - BUG_ON(ret > sizeof(printf_buffer)-1); - return xenbus_write(dir, node, printf_buffer); + BUG_ON(ret > PRINTF_BUFFER_SIZE-1); + ret = xenbus_write(t, dir, node, printf_buffer); + + kfree(printf_buffer); + + return ret; } EXPORT_SYMBOL(xenbus_printf); @@ -361,19 +522,28 @@ va_list ap; int ret; unsigned int len; - - BUG_ON(down_trylock(&xenbus_lock) == 0); + char *printf_buffer; + + printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL); + if (printf_buffer == NULL) + goto fail; len = sprintf(printf_buffer, "%i ", -err); va_start(ap, fmt); - ret = vsnprintf(printf_buffer+len, sizeof(printf_buffer)-len, fmt, ap); + ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); va_end(ap); - BUG_ON(len + ret > sizeof(printf_buffer)-1); + BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1); dev->has_error = 1; - if (xenbus_write(dev->nodename, "error", printf_buffer) != 0) - printk("xenbus: failed to write error node for %s (%s)\n", - dev->nodename, printf_buffer); + if (xenbus_write(NULL, dev->nodename, "error", printf_buffer) != 0) + goto fail; + + kfree(printf_buffer); + return; + + fail: + printk("xenbus: failed to write error node for %s (%s)\n", + dev->nodename, printf_buffer); } EXPORT_SYMBOL(xenbus_dev_error); @@ -381,7 +551,7 @@ void xenbus_dev_ok(struct xenbus_device *dev) { if (dev->has_error) { - if (xenbus_rm(dev->nodename, "error") != 0) + if (xenbus_rm(NULL, dev->nodename, "error") != 0) printk("xenbus: failed to clear error node for %s\n", dev->nodename); else @@ -391,7 +561,7 @@ EXPORT_SYMBOL(xenbus_dev_ok); /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */ -int xenbus_gather(const char *dir, ...) +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...) { va_list ap; const char *name; @@ -403,7 +573,7 @@ void *result = va_arg(ap, void *); char *p; - p = xenbus_read(dir, name, NULL); + p = xenbus_read(t, dir, name, NULL); if (IS_ERR(p)) { ret = PTR_ERR(p); break; @@ -429,27 +599,8 @@ iov[1].iov_base = (void *)token; iov[1].iov_len = strlen(token) + 1; - return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL)); -} - -static char **xs_read_watch(unsigned int *num) -{ - enum xsd_sockmsg_type type; - char *strings; - unsigned int len; - - strings = read_reply(&type, &len); - if (IS_ERR(strings)) - return (char **)strings; - - BUG_ON(type != XS_WATCH_EVENT); - - return split(strings, len, num); -} - -static int xs_acknowledge_watch(const char *token) -{ - return xs_error(xs_single(XS_WATCH_ACK, token, NULL)); + return xs_error(xs_talkv(NULL, XS_WATCH, iov, + ARRAY_SIZE(iov), NULL)); } static int xs_unwatch(const char *path, const char *token) @@ -461,10 +612,10 @@ iov[1].iov_base = (char *)token; iov[1].iov_len = strlen(token) + 1; - return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL)); -} - -/* A little paranoia: we don't just trust token. */ + return xs_error(xs_talkv(NULL, XS_UNWATCH, iov, + ARRAY_SIZE(iov), NULL)); +} + static struct xenbus_watch *find_watch(const char *token) { struct xenbus_watch *i, *cmp; @@ -474,6 +625,7 @@ list_for_each_entry(i, &watches, list) if (i == cmp) return i; + return NULL; } @@ -485,92 +637,223 @@ int err; sprintf(token, "%lX", (long)watch); + + down_read(&xs_state.suspend_mutex); + + spin_lock(&watches_lock); BUG_ON(find_watch(token)); + spin_unlock(&watches_lock); err = xs_watch(watch->node, token); - if (!err) + + /* Ignore errors due to multiple registration. */ + if ((err == 0) || (err == -EEXIST)) { + spin_lock(&watches_lock); list_add(&watch->list, &watches); + spin_unlock(&watches_lock); + } + + up_read(&xs_state.suspend_mutex); + return err; } EXPORT_SYMBOL(register_xenbus_watch); void unregister_xenbus_watch(struct xenbus_watch *watch) { + struct xs_stored_msg *msg, *tmp; char token[sizeof(watch) * 2 + 1]; int err; sprintf(token, "%lX", (long)watch); + + down_read(&xs_state.suspend_mutex); + + spin_lock(&watches_lock); BUG_ON(!find_watch(token)); + list_del(&watch->list); + spin_unlock(&watches_lock); err = xs_unwatch(watch->node, token); - list_del(&watch->list); - if (err) printk(KERN_WARNING "XENBUS Failed to release watch %s: %i\n", watch->node, err); + + up_read(&xs_state.suspend_mutex); + + /* Cancel pending watch events. */ + spin_lock(&watch_events_lock); + list_for_each_entry_safe(msg, tmp, &watch_events, list) { + if (msg->u.watch.handle != watch) + continue; + list_del(&msg->list); + kfree(msg->u.watch.vec); + kfree(msg); + } + spin_unlock(&watch_events_lock); + + /* Flush any currently-executing callback, unless we are it. :-) */ + if (current->pid != xenwatch_pid) { + down(&xenwatch_mutex); + up(&xenwatch_mutex); + } } EXPORT_SYMBOL(unregister_xenbus_watch); -/* Re-register callbacks to all watches. */ -void reregister_xenbus_watches(void) +void xs_suspend(void) +{ + down_write(&xs_state.suspend_mutex); + down(&xs_state.request_mutex); +} + +void xs_resume(void) { struct xenbus_watch *watch; char token[sizeof(watch) * 2 + 1]; + up(&xs_state.request_mutex); + + /* No need for watches_lock: the suspend_mutex is sufficient. */ list_for_each_entry(watch, &watches, list) { sprintf(token, "%lX", (long)watch); xs_watch(watch->node, token); } -} - -static int watch_thread(void *unused) -{ + + up_write(&xs_state.suspend_mutex); +} + +static int xenwatch_thread(void *unused) +{ + struct list_head *ent; + struct xs_stored_msg *msg; + for (;;) { - char **vec = NULL; - unsigned int num; - - wait_event(xb_waitq, xs_input_avail()); - - /* If this is a spurious wakeup caused by someone - * doing an op, they'll hold the lock and the buffer - * will be empty by the time we get there. - */ - down(&xenbus_lock); - if (xs_input_avail()) - vec = xs_read_watch(&num); - - if (vec && !IS_ERR(vec)) { - struct xenbus_watch *w; - int err; - - err = xs_acknowledge_watch(vec[XS_WATCH_TOKEN]); - if (err) - printk(KERN_WARNING "XENBUS ack %s fail %i\n", - vec[XS_WATCH_TOKEN], err); - w = find_watch(vec[XS_WATCH_TOKEN]); - BUG_ON(!w); - w->callback(w, (const char **)vec, num); - kfree(vec); - } else if (vec) - printk(KERN_WARNING "XENBUS xs_read_watch: %li\n", - PTR_ERR(vec)); - up(&xenbus_lock); + wait_event_interruptible(watch_events_waitq, + !list_empty(&watch_events)); + + down(&xenwatch_mutex); + + spin_lock(&watch_events_lock); + ent = watch_events.next; + if (ent != &watch_events) + list_del(ent); + spin_unlock(&watch_events_lock); + + if (ent != &watch_events) { + msg = list_entry(ent, struct xs_stored_msg, list); + msg->u.watch.handle->callback( + msg->u.watch.handle, + (const char **)msg->u.watch.vec, + msg->u.watch.vec_size); + kfree(msg->u.watch.vec); + kfree(msg); + } + + up(&xenwatch_mutex); + } +} + +static int process_msg(void) +{ + struct xs_stored_msg *msg; + char *body; + int err; + + msg = kmalloc(sizeof(*msg), GFP_KERNEL); + if (msg == NULL) + return -ENOMEM; + + err = xb_read(&msg->hdr, sizeof(msg->hdr)); + if (err) { + kfree(msg); + return err; + } + + body = kmalloc(msg->hdr.len + 1, GFP_KERNEL); + if (body == NULL) { + kfree(msg); + return -ENOMEM; + } + + err = xb_read(body, msg->hdr.len); + if (err) { + kfree(body); + kfree(msg); + return err; + } + body[msg->hdr.len] = '\0'; + + if (msg->hdr.type == XS_WATCH_EVENT) { + msg->u.watch.vec = split(body, msg->hdr.len, + &msg->u.watch.vec_size); + if (IS_ERR(msg->u.watch.vec)) { + kfree(msg); + return PTR_ERR(msg->u.watch.vec); + } + + spin_lock(&watches_lock); + msg->u.watch.handle = find_watch( + msg->u.watch.vec[XS_WATCH_TOKEN]); + if (msg->u.watch.handle != NULL) { + spin_lock(&watch_events_lock); + list_add_tail(&msg->list, &watch_events); + wake_up(&watch_events_waitq); + spin_unlock(&watch_events_lock); + } else { + kfree(msg->u.watch.vec); + kfree(msg); + } + spin_unlock(&watches_lock); + } else { + msg->u.reply.body = body; + spin_lock(&xs_state.reply_lock); + list_add_tail(&msg->list, &xs_state.reply_list); + spin_unlock(&xs_state.reply_lock); + wake_up(&xs_state.reply_waitq); + } + + return 0; +} + +static int xenbus_thread(void *unused) +{ + int err; + + for (;;) { + err = process_msg(); + if (err) + printk(KERN_WARNING "XENBUS error %d while reading " + "message\n", err); } } int xs_init(void) { int err; - struct task_struct *watcher; - + struct task_struct *task; + + INIT_LIST_HEAD(&xs_state.reply_list); + spin_lock_init(&xs_state.reply_lock); + init_waitqueue_head(&xs_state.reply_waitq); + + init_MUTEX(&xs_state.request_mutex); + init_rwsem(&xs_state.suspend_mutex); + + /* Initialize the shared memory rings to talk to xenstored */ err = xb_init_comms(); if (err) return err; - - watcher = kthread_run(watch_thread, NULL, "kxbwatch"); - if (IS_ERR(watcher)) - return PTR_ERR(watcher); + + task = kthread_run(xenwatch_thread, NULL, "xenwatch"); + if (IS_ERR(task)) + return PTR_ERR(task); + xenwatch_pid = task->pid; + + task = kthread_run(xenbus_thread, NULL, "xenbus"); + if (IS_ERR(task)) + return PTR_ERR(task); + return 0; } diff -r 333f722ed6d0 -r 74d56b7ff46c linux-2.6-xen-sparse/include/asm-xen/xenbus.h --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Tue Oct 11 21:50:21 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Tue Oct 11 22:57:44 2005 @@ -78,30 +78,35 @@ int xenbus_register_backend(struct xenbus_driver *drv); void xenbus_unregister_driver(struct xenbus_driver *drv); -/* Caller must hold this lock to call these functions: it's also held - * across watch callbacks. */ -extern struct semaphore xenbus_lock; +struct xenbus_transaction; -char **xenbus_directory(const char *dir, const char *node, unsigned int *num); -void *xenbus_read(const char *dir, const char *node, unsigned int *len); -int xenbus_write(const char *dir, const char *node, const char *string); -int xenbus_mkdir(const char *dir, const char *node); -int xenbus_exists(const char *dir, const char *node); -int xenbus_rm(const char *dir, const char *node); -int xenbus_transaction_start(void); -int xenbus_transaction_end(int abort); +char **xenbus_directory(struct xenbus_transaction *t, + const char *dir, const char *node, unsigned int *num); +void *xenbus_read(struct xenbus_transaction *t, + const char *dir, const char *node, unsigned int *len); +int xenbus_write(struct xenbus_transaction *t, + const char *dir, const char *node, const char *string); +int xenbus_mkdir(struct xenbus_transaction *t, + const char *dir, const char *node); +int xenbus_exists(struct xenbus_transaction *t, + const char *dir, const char *node); +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node); +struct xenbus_transaction *xenbus_transaction_start(void); +int xenbus_transaction_end(struct xenbus_transaction *t, int abort); /* Single read and scanf: returns -errno or num scanned if > 0. */ -int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...) - __attribute__((format(scanf, 3, 4))); +int xenbus_scanf(struct xenbus_transaction *t, + const char *dir, const char *node, const char *fmt, ...) + __attribute__((format(scanf, 4, 5))); /* Single printf and write: returns -errno or 0. */ -int xenbus_printf(const char *dir, const char *node, const char *fmt, ...) - __attribute__((format(printf, 3, 4))); +int xenbus_printf(struct xenbus_transaction *t, + const char *dir, const char *node, const char *fmt, ...) + __attribute__((format(printf, 4, 5))); /* Generic read function: NULL-terminated triples of name, * sprintf-style type string, and pointer. Returns 0 or errno.*/ -int xenbus_gather(const char *dir, ...); +int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...); /* Report a (negative) errno into the store, with explanation. */ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt,...); @@ -113,7 +118,11 @@ struct xenbus_watch { struct list_head list; + + /* Path being watched. */ char *node; + + /* Callback (executed in a process context with no locks held). */ void (*callback)(struct xenbus_watch *, const char **vec, unsigned int len); }; @@ -124,7 +133,11 @@ int register_xenbus_watch(struct xenbus_watch *watch); void unregister_xenbus_watch(struct xenbus_watch *watch); -void reregister_xenbus_watches(void); +void xs_suspend(void); +void xs_resume(void); + +/* Used by xenbus_dev to borrow kernel's store connection. */ +void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg); /* Called from xen core code. */ void xenbus_suspend(void); diff -r 333f722ed6d0 -r 74d56b7ff46c tools/blktap/xenbus.c --- a/tools/blktap/xenbus.c Tue Oct 11 21:50:21 2005 +++ b/tools/blktap/xenbus.c Tue Oct 11 22:57:44 2005 @@ -260,10 +260,6 @@ node = res[XS_WATCH_PATH]; token = res[XS_WATCH_TOKEN]; - er = xs_acknowledge_watch(h, token); - if (er == 0) - warn("Couldn't acknowledge watch (%s)", token); - w = find_watch(token); if (!w) { diff -r 333f722ed6d0 -r 74d56b7ff46c tools/console/Makefile --- a/tools/console/Makefile Tue Oct 11 21:50:21 2005 +++ b/tools/console/Makefile Tue Oct 11 22:57:44 2005 @@ -3,7 +3,7 @@ include $(XEN_ROOT)/tools/Rules.mk DAEMON_INSTALL_DIR = /usr/sbin -CLIENT_INSTALL_DIR = /usr/libexec/xen +CLIENT_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin INSTALL = install INSTALL_PROG = $(INSTALL) -m0755 diff -r 333f722ed6d0 -r 74d56b7ff46c tools/console/client/main.c --- a/tools/console/client/main.c Tue Oct 11 21:50:21 2005 +++ b/tools/console/client/main.c Tue Oct 11 22:57:44 2005 @@ -220,7 +220,7 @@ if (path == NULL) err(ENOMEM, "realloc"); strcat(path, "/console/tty"); - str_pty = xs_read(xs, path, &len); + str_pty = xs_read(xs, NULL, path, &len); /* FIXME consoled currently does not assume domain-0 doesn't have a console which is good when we break domain-0 up. To keep us @@ -245,7 +245,7 @@ struct timeval tv = { 0, 500 }; select(0, NULL, NULL, NULL, &tv); /* pause briefly */ - str_pty = xs_read(xs, path, &len); + str_pty = xs_read(xs, NULL, path, &len); } if (str_pty == NULL) { diff -r 333f722ed6d0 -r 74d56b7ff46c tools/console/daemon/io.c --- a/tools/console/daemon/io.c Tue Oct 11 21:50:21 2005 +++ b/tools/console/daemon/io.c Tue Oct 11 22:57:44 2005 @@ -25,6 +25,7 @@ #include <xenctrl.h> #include <xs.h> #include <xen/linux/evtchn.h> +#include <xen/io/console.h> #include <malloc.h> #include <stdlib.h> @@ -62,24 +63,11 @@ char *conspath; int ring_ref; int local_port; - char *page; int evtchn_fd; + struct xencons_interface *interface; }; static struct domain *dom_head; - -struct ring_head -{ - u32 cons; - u32 prod; - char buf[0]; -} __attribute__((packed)); - -#define PAGE_SIZE (getpagesize()) -#define XENCONS_RING_SIZE (PAGE_SIZE/2 - sizeof (struct ring_head)) -#define XENCONS_IDX(cnt) ((cnt) % XENCONS_RING_SIZE) -#define XENCONS_FULL(ring) (((ring)->prod - (ring)->cons) == XENCONS_RING_SIZE) -#define XENCONS_SPACE(ring) (XENCONS_RING_SIZE - ((ring)->prod - (ring)->cons)) static void evtchn_notify(struct domain *dom) { @@ -91,12 +79,12 @@ static void buffer_append(struct domain *dom) { struct buffer *buffer = &dom->buffer; - struct ring_head *ring = (struct ring_head *)dom->page; size_t size; - u32 oldcons; + XENCONS_RING_IDX oldcons; int notify = 0; - - while ((size = ring->prod - ring->cons) != 0) { + struct xencons_interface *intf = dom->interface; + + while ((size = (intf->out_prod - intf->out_cons)) != 0) { notify = 1; if ((buffer->capacity - buffer->size) < size) { @@ -108,12 +96,12 @@ } } - oldcons = ring->cons; - while (ring->cons < (oldcons + size)) { - buffer->data[buffer->size] = - ring->buf[XENCONS_IDX(ring->cons)]; + oldcons = intf->out_cons; + while ((intf->out_cons - oldcons) < size) { + buffer->data[buffer->size] = intf->out[ + MASK_XENCONS_IDX(intf->out_cons, intf->out)]; buffer->size++; - ring->cons++; + intf->out_cons++; } if (buffer->max_capacity && @@ -179,7 +167,7 @@ success = asprintf(&path, "%s/tty", dom->conspath) != -1; if (!success) goto out; - success = xs_write(xs, path, slave, strlen(slave)); + success = xs_write(xs, NULL, path, slave, strlen(slave)); free(path); if (!success) goto out; @@ -187,7 +175,7 @@ success = asprintf(&path, "%s/limit", dom->conspath) != -1; if (!success) goto out; - data = xs_read(xs, path, &len); + data = xs_read(xs, NULL, path, &len); if (data) { dom->buffer.max_capacity = strtoul(data, 0, 0); free(data); @@ -216,7 +204,7 @@ char *p; asprintf(&path, "%s/%s", dir, name); - p = xs_read(xs, path, NULL); + p = xs_read(xs, NULL, path, NULL); free(path); if (p == NULL) { ret = ENOENT; @@ -246,12 +234,13 @@ goto out; if (ring_ref != dom->ring_ref) { - if (dom->page) - munmap(dom->page, getpagesize()); - dom->page = xc_map_foreign_range(xc, dom->domid, getpagesize(), - PROT_READ|PROT_WRITE, - (unsigned long)ring_ref); - if (dom->page == NULL) { + if (dom->interface != NULL) + munmap(dom->interface, getpagesize()); + dom->interface = xc_map_foreign_range( + xc, dom->domid, getpagesize(), + PROT_READ|PROT_WRITE, + (unsigned long)ring_ref); + if (dom->interface == NULL) { err = EINVAL; goto out; } @@ -334,7 +323,7 @@ dom->ring_ref = -1; dom->local_port = -1; - dom->page = NULL; + dom->interface = NULL; dom->evtchn_fd = -1; if (!watch_domain(dom, true)) @@ -396,9 +385,9 @@ { d->is_dead = true; watch_domain(d, false); - if (d->page) - munmap(d->page, getpagesize()); - d->page = NULL; + if (d->interface != NULL) + munmap(d->interface, getpagesize()); + d->interface = NULL; if (d->evtchn_fd != -1) close(d->evtchn_fd); d->evtchn_fd = -1; @@ -426,13 +415,21 @@ static void handle_tty_read(struct domain *dom) { - ssize_t len; + ssize_t len = 0; char msg[80]; - struct ring_head *inring = - (struct ring_head *)(dom->page + PAGE_SIZE/2); int i; - - len = read(dom->tty_fd, msg, MIN(XENCONS_SPACE(inring), sizeof(msg))); + struct xencons_interface *intf = dom->interface; + XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons; + + if (sizeof(intf->in) > filled) + len = sizeof(intf->in) - filled; + if (len > sizeof(msg)) + len = sizeof(msg); + + if (len == 0) + return; + + len = read(dom->tty_fd, msg, len); if (len < 1) { close(dom->tty_fd); dom->tty_fd = -1; @@ -444,8 +441,9 @@ } } else if (domain_is_valid(dom->domid)) { for (i = 0; i < len; i++) { - inring->buf[XENCONS_IDX(inring->prod)] = msg[i]; - inring->prod++; + intf->in[MASK_XENCONS_IDX(intf->in_prod, intf->in)] = + msg[i]; + intf->in_prod++; } evtchn_notify(dom); } else { @@ -505,7 +503,6 @@ domain_create_ring(dom); } - xs_acknowledge_watch(xs, vec[1]); free(vec); } @@ -565,3 +562,13 @@ } } while (ret > -1); } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/examples/Makefile --- a/tools/examples/Makefile Tue Oct 11 21:50:21 2005 +++ b/tools/examples/Makefile Tue Oct 11 22:57:44 2005 @@ -24,6 +24,7 @@ XEN_SCRIPTS += network-nat vif-nat XEN_SCRIPTS += block XEN_SCRIPTS += block-enbd +XEN_SCRIPTS += xen-hotplug-common.sh XEN_HOTPLUG_DIR = /etc/hotplug XEN_HOTPLUG_SCRIPTS = xen-backend.agent diff -r 333f722ed6d0 -r 74d56b7ff46c tools/examples/block --- a/tools/examples/block Tue Oct 11 21:50:21 2005 +++ b/tools/examples/block Tue Oct 11 22:57:44 2005 @@ -1,8 +1,7 @@ #!/bin/sh -set -e - -export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH +dir=$(dirname "$0") +. "$dir/xen-hotplug-common.sh" expand_dev() { local dev @@ -25,15 +24,15 @@ major=$(stat -L -c %t "$1") minor=$(stat -L -c %T "$1") pdev=$(printf "0x%02x%02x" 0x$major 0x$minor) - xenstore-write "$XENBUS_PATH"/physical-device $pdev \ + xenstore_write "$XENBUS_PATH"/physical-device $pdev \ "$XENBUS_PATH"/node $1 } -t=$(xenstore-read "$XENBUS_PATH"/type) +t=$(xenstore_read "$XENBUS_PATH"/type || true) case $1 in bind) - p=$(xenstore-read "$XENBUS_PATH"/params) + p=$(xenstore_read "$XENBUS_PATH"/params) case $t in phy) dev=$(expand_dev $p) @@ -60,7 +59,7 @@ ;; unbind) - node=$(xenstore-read "$XENBUS_PATH"/node) + node=$(xenstore_read "$XENBUS_PATH"/node) case $t in phy) exit 0 diff -r 333f722ed6d0 -r 74d56b7ff46c tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Tue Oct 11 21:50:21 2005 +++ b/tools/libxc/xc_linux_save.c Tue Oct 11 22:57:44 2005 @@ -35,7 +35,7 @@ #define DEBUG 0 #if 1 -#define ERR(_f, _a...) do { fprintf(stderr, _f , ## _a); fflush(stderr); } while (0) +#define ERR(_f, _a...) do { fprintf(stderr, _f "\n" , ## _a); fflush(stderr); } while (0) #else #define ERR(_f, _a...) ((void)0) #endif diff -r 333f722ed6d0 -r 74d56b7ff46c tools/misc/xend --- a/tools/misc/xend Tue Oct 11 21:50:21 2005 +++ b/tools/misc/xend Tue Oct 11 22:57:44 2005 @@ -2,9 +2,10 @@ # -*- mode: python; -*- #============================================================================ # Copyright (C) 2004 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ -"""Xen management daemon. Lives in /usr/sbin. +"""Xen management daemon. Provides console server and HTTP management api. Run: @@ -67,14 +68,14 @@ def start_xenstored(): XENSTORED_TRACE = os.getenv("XENSTORED_TRACE") - cmd = "/usr/sbin/xenstored --pid-file=/var/run/xenstore.pid" + cmd = "xenstored --pid-file=/var/run/xenstore.pid" if XENSTORED_TRACE: cmd += " -T /var/log/xenstored-trace.log" s,o = commands.getstatusoutput(cmd) def start_consoled(): if os.fork() == 0: - os.execvp('/usr/sbin/xenconsoled', ['/usr/sbin/xenconsoled']) + os.execvp('xenconsoled', ['xenconsoled']) def main(): try: diff -r 333f722ed6d0 -r 74d56b7ff46c tools/pygrub/src/fsys/reiser/reisermodule.c --- a/tools/pygrub/src/fsys/reiser/reisermodule.c Tue Oct 11 21:50:21 2005 +++ b/tools/pygrub/src/fsys/reiser/reisermodule.c Tue Oct 11 22:57:44 2005 @@ -46,7 +46,7 @@ if (!dal) return; - close((int)dal->dev); + close((size_t)dal->dev); dal_free(dal); } diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/lowlevel/xs/xs.c --- a/tools/python/xen/lowlevel/xs/xs.c Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/lowlevel/xs/xs.c Tue Oct 11 22:57:44 2005 @@ -80,8 +80,8 @@ static PyObject *xspy_read(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", NULL }; - static char *arg_spec = "s|"; + static char *kwd_spec[] = { "transaction", "path", NULL }; + static char *arg_spec = "ss"; char *path = NULL; struct xs_handle *xh = xshandle(self); @@ -89,13 +89,19 @@ unsigned int xsval_n = 0; PyObject *val = NULL; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, - &path)) - goto exit; - Py_BEGIN_ALLOW_THREADS - xsval = xs_read(xh, path, &xsval_n); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + xsval = xs_read(xh, th, path, &xsval_n); Py_END_ALLOW_THREADS if (!xsval) { if (errno == ENOENT) { @@ -123,8 +129,8 @@ static PyObject *xspy_write(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", "data", NULL }; - static char *arg_spec = "ss#"; + static char *kwd_spec[] = { "transaction", "path", "data", NULL }; + static char *arg_spec = "sss#"; char *path = NULL; char *data = NULL; int data_n = 0; @@ -133,13 +139,19 @@ PyObject *val = NULL; int xsval = 0; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, - &path, &data, &data_n)) - goto exit; - Py_BEGIN_ALLOW_THREADS - xsval = xs_write(xh, path, data, data_n); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path, &data, &data_n)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + xsval = xs_write(xh, th, path, data, data_n); Py_END_ALLOW_THREADS if (!xsval) { PyErr_SetFromErrno(PyExc_RuntimeError); @@ -162,8 +174,8 @@ static PyObject *xspy_ls(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", NULL }; - static char *arg_spec = "s|"; + static char *kwd_spec[] = { "transaction", "path", NULL }; + static char *arg_spec = "ss"; char *path = NULL; struct xs_handle *xh = xshandle(self); @@ -172,12 +184,20 @@ unsigned int xsval_n = 0; int i; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path)) - goto exit; - Py_BEGIN_ALLOW_THREADS - xsval = xs_directory(xh, path, &xsval_n); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path)) + goto exit; + + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + xsval = xs_directory(xh, th, path, &xsval_n); Py_END_ALLOW_THREADS if (!xsval) { if (errno == ENOENT) { @@ -205,20 +225,27 @@ static PyObject *xspy_mkdir(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", NULL }; - static char *arg_spec = "s|"; + static char *kwd_spec[] = { "transaction", "path", NULL }; + static char *arg_spec = "ss"; char *path = NULL; struct xs_handle *xh = xshandle(self); PyObject *val = NULL; int xsval = 0; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path)) - goto exit; - Py_BEGIN_ALLOW_THREADS - xsval = xs_mkdir(xh, path); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + xsval = xs_mkdir(xh, th, path); Py_END_ALLOW_THREADS if (!xsval) { PyErr_SetFromErrno(PyExc_RuntimeError); @@ -240,20 +267,27 @@ static PyObject *xspy_rm(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", NULL }; - static char *arg_spec = "s|"; + static char *kwd_spec[] = { "transaction", "path", NULL }; + static char *arg_spec = "ss"; char *path = NULL; struct xs_handle *xh = xshandle(self); PyObject *val = NULL; int xsval = 0; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path)) - goto exit; - Py_BEGIN_ALLOW_THREADS - xsval = xs_rm(xh, path); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + xsval = xs_rm(xh, th, path); Py_END_ALLOW_THREADS if (!xsval && errno != ENOENT) { PyErr_SetFromErrno(PyExc_RuntimeError); @@ -276,8 +310,8 @@ static PyObject *xspy_get_permissions(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", NULL }; - static char *arg_spec = "s|"; + static char *kwd_spec[] = { "transaction", "path", NULL }; + static char *arg_spec = "ss"; char *path = NULL; struct xs_handle *xh = xshandle(self); @@ -286,12 +320,19 @@ unsigned int perms_n = 0; int i; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path)) - goto exit; - Py_BEGIN_ALLOW_THREADS - perms = xs_get_permissions(xh, path, &perms_n); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + perms = xs_get_permissions(xh, th, path, &perms_n); Py_END_ALLOW_THREADS if (!perms) { PyErr_SetFromErrno(PyExc_RuntimeError); @@ -321,8 +362,8 @@ static PyObject *xspy_set_permissions(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "path", "perms", NULL }; - static char *arg_spec = "sO"; + static char *kwd_spec[] = { "transaction", "path", "perms", NULL }; + static char *arg_spec = "ssO"; char *path = NULL; PyObject *perms = NULL; static char *perm_names[] = { "dom", "read", "write", NULL }; @@ -335,11 +376,17 @@ PyObject *tuple0 = NULL; PyObject *val = NULL; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, - &path, &perms)) - goto exit; + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &path, &perms)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + if (!PyList_Check(perms)) { PyErr_SetString(PyExc_RuntimeError, "perms must be a list"); goto exit; @@ -369,7 +416,7 @@ xsperms[i].perms |= XS_PERM_WRITE; } Py_BEGIN_ALLOW_THREADS - xsval = xs_set_permissions(xh, path, xsperms, xsperms_n); + xsval = xs_set_permissions(xh, th, path, xsperms, xsperms_n); Py_END_ALLOW_THREADS if (!xsval) { PyErr_SetFromErrno(PyExc_RuntimeError); @@ -442,9 +489,6 @@ #define xspy_read_watch_doc "\n" \ "Read a watch notification.\n" \ - "The notification must be acknowledged by passing\n" \ - "the token to acknowledge_watch().\n" \ - " path [string]: xenstore path.\n" \ "\n" \ "Returns: [tuple] (path, token).\n" \ "Raises RuntimeError on error.\n" \ @@ -492,44 +536,6 @@ exit: if (xsval) free(xsval); - return val; -} - -#define xspy_acknowledge_watch_doc "\n" \ - "Acknowledge a watch notification that has been read.\n" \ - " token [string] : from the watch notification\n" \ - "\n" \ - "Returns None on success.\n" \ - "Raises RuntimeError on error.\n" \ - "\n" - -static PyObject *xspy_acknowledge_watch(PyObject *self, PyObject *args, - PyObject *kwds) -{ - static char *kwd_spec[] = { "token", NULL }; - static char *arg_spec = "O"; - PyObject *token; - char token_str[MAX_STRLEN(unsigned long) + 1]; - - struct xs_handle *xh = xshandle(self); - PyObject *val = NULL; - int xsval = 0; - - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &token)) - goto exit; - sprintf(token_str, "%li", (unsigned long)token); - Py_BEGIN_ALLOW_THREADS - xsval = xs_acknowledge_watch(xh, token_str); - Py_END_ALLOW_THREADS - if (!xsval) { - PyErr_SetFromErrno(PyExc_RuntimeError); - goto exit; - } - Py_INCREF(Py_None); - val = Py_None; - exit: return val; } @@ -584,9 +590,8 @@ #define xspy_transaction_start_doc "\n" \ "Start a transaction.\n" \ - "Only one transaction can be active at a time.\n" \ "\n" \ - "Returns None on success.\n" \ + "Returns transaction handle on success.\n" \ "Raises RuntimeError on error.\n" \ "\n" @@ -599,21 +604,23 @@ struct xs_handle *xh = xshandle(self); PyObject *val = NULL; - int xsval = 0; + struct xs_transaction_handle *th; + char thstr[20]; if (!xh) goto exit; if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &path)) goto exit; Py_BEGIN_ALLOW_THREADS - xsval = xs_transaction_start(xh); - Py_END_ALLOW_THREADS - if (!xsval) { - PyErr_SetFromErrno(PyExc_RuntimeError); - goto exit; - } - Py_INCREF(Py_None); - val = Py_None; + th = xs_transaction_start(xh); + Py_END_ALLOW_THREADS + if (th == NULL) { + PyErr_SetFromErrno(PyExc_RuntimeError); + goto exit; + } + + sprintf(thstr, "%lX", (unsigned long)th); + val = PyString_FromString(thstr); exit: return val; } @@ -630,20 +637,27 @@ static PyObject *xspy_transaction_end(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwd_spec[] = { "abort", NULL }; - static char *arg_spec = "|i"; + static char *kwd_spec[] = { "transaction", "abort", NULL }; + static char *arg_spec = "s|i"; int abort = 0; struct xs_handle *xh = xshandle(self); PyObject *val = NULL; int xsval = 0; - if (!xh) - goto exit; - if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, &abort)) - goto exit; - Py_BEGIN_ALLOW_THREADS - xsval = xs_transaction_end(xh, abort); + struct xs_transaction_handle *th; + char *thstr; + + if (!xh) + goto exit; + if (!PyArg_ParseTupleAndKeywords(args, kwds, arg_spec, kwd_spec, + &thstr, &abort)) + goto exit; + + th = (struct xs_transaction_handle *)strtoul(thstr, NULL, 16); + + Py_BEGIN_ALLOW_THREADS + xsval = xs_transaction_end(xh, th, abort); Py_END_ALLOW_THREADS if (!xsval) { if (errno == EAGAIN) { @@ -833,7 +847,6 @@ XSPY_METH(set_permissions), XSPY_METH(watch), XSPY_METH(read_watch), - XSPY_METH(acknowledge_watch), XSPY_METH(unwatch), XSPY_METH(transaction_start), XSPY_METH(transaction_end), diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/util/Brctl.py --- a/tools/python/xen/util/Brctl.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/util/Brctl.py Tue Oct 11 22:57:44 2005 @@ -5,7 +5,6 @@ import re import sys -os.defpath = os.defpath + ':/sbin:/usr/sbin:/usr/local/sbin' CMD_IFCONFIG = 'ifconfig' CMD_ROUTE = 'route' CMD_BRCTL = 'brctl' diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/XendCheckpoint.py Tue Oct 11 22:57:44 2005 @@ -14,6 +14,8 @@ from xen.util.xpopen import xPopen3 +import xen.util.auxbin + import xen.lowlevel.xc from xen.xend.xenstore.xsutil import IntroduceDomain @@ -21,9 +23,11 @@ from XendError import XendError from XendLogging import log + SIGNATURE = "LinuxGuestRecord" -PATH_XC_SAVE = "/usr/libexec/xen/xc_save" -PATH_XC_RESTORE = "/usr/libexec/xen/xc_restore" +XC_SAVE = "xc_save" +XC_RESTORE = "xc_restore" + sizeof_int = calcsize("i") sizeof_unsigned_long = calcsize("L") @@ -64,7 +68,7 @@ # enabled. Passing "0" simply uses the defaults compiled into # libxenguest; see the comments and/or code in xc_linux_save() for # more information. - cmd = [PATH_XC_SAVE, str(xc.handle()), str(fd), + cmd = [xen.util.auxbin.pathTo(XC_SAVE), str(xc.handle()), str(fd), str(dominfo.getDomid()), "0", "0", str(int(live)) ] log.debug("[xc_save]: %s", string.join(cmd)) @@ -129,7 +133,7 @@ store_evtchn = dominfo.store_channel console_evtchn = dominfo.console_channel - cmd = [PATH_XC_RESTORE, str(xc.handle()), str(fd), + cmd = [xen.util.auxbin.pathTo(XC_RESTORE), str(xc.handle()), str(fd), str(dominfo.getDomid()), str(nr_pfns), str(store_evtchn), str(console_evtchn)] log.debug("[xc_restore]: %s", string.join(cmd)) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/XendClient.py --- a/tools/python/xen/xend/XendClient.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/XendClient.py Tue Oct 11 22:57:44 2005 @@ -195,6 +195,9 @@ def xend_domains(self): return self.xendGet(self.domainurl()) + + def xend_list_domains(self): + return self.xendGet(self.domainurl(), {'detail': '1'}) def xend_domain_create(self, conf): return self.xendPost(self.domainurl(), diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/XendDomain.py --- a/tools/python/xen/xend/XendDomain.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/XendDomain.py Tue Oct 11 22:57:44 2005 @@ -359,20 +359,6 @@ raise XendError(str(ex)) - def domain_shutdown(self, domid, reason = 'poweroff'): - """Shutdown domain (nicely). - - @param reason: shutdown reason: poweroff, reboot, suspend, halt - """ - self.callInfo(domid, XendDomainInfo.XendDomainInfo.shutdown, reason) - - - def domain_sysrq(self, domid, key): - """Send a SysRq to the specified domain.""" - return self.callInfo(domid, XendDomainInfo.XendDomainInfo.send_sysrq, - key) - - def domain_destroy(self, domid): """Terminate domain immediately.""" @@ -475,37 +461,6 @@ raise XendError(str(ex)) - def domain_device_create(self, domid, devconfig): - """Create a new device for the specified domain. - """ - return self.callInfo(domid, - XendDomainInfo.XendDomainInfo.device_create, - devconfig) - - - def domain_device_configure(self, domid, devconfig, devid): - """Configure an existing device in the specified domain. - @return: updated device configuration - """ - return self.callInfo(domid, - XendDomainInfo.XendDomainInfo.device_configure, - devconfig, devid) - - - def domain_device_destroy(self, domid, devtype, devid): - """Destroy a device.""" - return self.callInfo(domid, - XendDomainInfo.XendDomainInfo.destroyDevice, - devtype, devid) - - - def domain_devtype_ls(self, domid, devtype): - """Get list of device sxprs for the specified domain.""" - return self.callInfo(domid, - XendDomainInfo.XendDomainInfo.getDeviceSxprs, - devtype) - - def domain_vif_limit_set(self, domid, vif, credit, period): """Limit the vif's transmission rate """ @@ -536,44 +491,6 @@ maxmem_kb = maxmem) except Exception, ex: raise XendError(str(ex)) - - def domain_mem_target_set(self, domid, mem): - """Set the memory target for a domain. - - @param mem: memory target (in MiB) - """ - self.callInfo(domid, XendDomainInfo.XendDomainInfo.setMemoryTarget, - mem << 10) - - - def domain_vcpu_hotplug(self, domid, vcpu, state): - """Enable or disable specified VCPU in specified domain - - @param vcpu: target VCPU in domain - @param state: which state VCPU will become - """ - self.callInfo(domid, XendDomainInfo.XendDomainInfo.vcpu_hotplug, vcpu, - state) - - - def domain_dumpcore(self, domid): - """Save a core dump for a crashed domain.""" - self.callInfo(domid, XendDomainInfo.XendDomainInfo.dumpCore) - - - ## private: - - def callInfo(self, domid, fn, *args, **kwargs): - try: - self.refresh() - dominfo = self.domains.get(domid) - if dominfo: - return fn(dominfo, *args, **kwargs) - except XendError: - raise - except Exception, exn: - log.exception("") - raise XendError(str(exn)) def instance(): diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Oct 11 22:57:44 2005 @@ -30,6 +30,7 @@ import errno import xen.lowlevel.xc +from xen.util import asserts from xen.util.blkif import blkdev_uname_to_file from xen.xend import image @@ -41,7 +42,8 @@ from xen.xend.XendError import XendError, VmError from xen.xend.XendRoot import get_component -from xen.xend.uuid import getUuid +from uuid import getUuid + from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xsutil import GetDomainPath, IntroduceDomain @@ -217,17 +219,12 @@ def restore(config): """Create a domain and a VM object to do a restore. - @param config: domain configuration + @param config: domain configuration """ log.debug("XendDomainInfo.restore(%s)", config) - try: - uuid = sxp.child_value(config, 'uuid') - ssidref = int(sxp.child_value(config, 'ssidref')) - except TypeError, exn: - raise VmError('Invalid ssidref in config: %s' % exn) - + uuid = sxp.child_value(config, 'uuid') vm = XendDomainInfo(uuid, parseConfig(config)) try: vm.construct() @@ -257,7 +254,7 @@ return val - log.debug("parseConfig: config is %s" % str(config)) + log.debug("parseConfig: config is %s", config) result = {} @@ -315,7 +312,7 @@ log.warn("Ignoring malformed and deprecated config option " "restart = %s", restart) - log.debug("parseConfig: result is %s" % str(result)) + log.debug("parseConfig: result is %s", result) return result @@ -529,7 +526,7 @@ except KeyError, exn: log.exception(exn) - raise VmError('Unspecified domain detail: %s' % str(exn)) + raise VmError('Unspecified domain detail: %s' % exn) def readVm(self, *args): @@ -579,7 +576,7 @@ if self.infoIsSet(k): to_store[k] = str(self.info[k]) - log.debug("Storing VM details: %s" % str(to_store)) + log.debug("Storing VM details: %s", to_store) self.writeVm(to_store) @@ -605,7 +602,7 @@ for v in range(0, self.info['vcpus']): to_store["cpu/%d/availability" % v] = availability(v) - log.debug("Storing domain details: %s" % str(to_store)) + log.debug("Storing domain details: %s", to_store) self.writeDom(to_store) @@ -746,7 +743,7 @@ def shutdown(self, reason): if not reason in shutdown_reasons.values(): - raise XendError('invalid reason:' + reason) + raise XendError('Invalid reason: %s' % reason) self.storeDom("control/shutdown", reason) if reason != 'suspend': self.storeDom('xend/shutdown_start_time', time.time()) @@ -793,10 +790,12 @@ def setMemoryTarget(self, target): """Set the memory target of this domain. - @param target In KiB. - """ - self.info['memory_KiB'] = target - self.storeDom("memory/target", target) + @param target In MiB. + """ + # Internally we use KiB, but the command interface uses MiB. + t = target << 10 + self.info['memory_KiB'] = t + self.storeDom("memory/target", t) def update(self, info = None): @@ -986,8 +985,8 @@ """ log.debug('XendDomainInfo.construct: %s %s', - str(self.domid), - str(self.info['ssidref'])) + self.domid, + self.info['ssidref']) self.domid = xc.domain_create(dom = 0, ssidref = self.info['ssidref']) @@ -1004,9 +1003,9 @@ def initDomain(self): log.debug('XendDomainInfo.initDomain: %s %s %s', - str(self.domid), - str(self.info['memory_KiB']), - str(self.info['cpu_weight'])) + self.domid, + self.info['memory_KiB'], + self.info['cpu_weight']) if not self.infoIsSet('image'): raise VmError('Missing image in configuration') @@ -1085,14 +1084,15 @@ def destroy(self): """Cleanup VM and destroy domain. Nothrow guarantee.""" - log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + log.debug("XendDomainInfo.destroy: domid=%s", self.domid) self.cleanupVm() - self.destroyDomain() + if self.dompath is not None: + self.destroyDomain() def destroyDomain(self): - log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid)) + log.debug("XendDomainInfo.destroyDomain(%s)", self.domid) try: if self.domid is not None: @@ -1366,7 +1366,10 @@ self.storeVm('vcpu_avail', self.info['vcpu_avail']) self.storeDom("cpu/%d/availability" % vcpu, availability) - def send_sysrq(self, key=0): + + def send_sysrq(self, key): + asserts.isCharConvertible(key) + self.storeDom("control/sysrq", '%c' % key) @@ -1388,18 +1391,18 @@ dom = 0 # get max number of vcpus to use for dom0 from config target = int(xroot.get_dom0_vcpus()) - log.debug("number of vcpus to use is %d" % (target)) + log.debug("number of vcpus to use is %d", target) # target = 0 means use all processors if target > 0: # count the number of online vcpus (cpu values in v2c map >= 0) vcpu_to_cpu = dom_get(dom)['vcpu_to_cpu'] vcpus_online = len(filter(lambda x: x >= 0, vcpu_to_cpu)) - log.debug("found %d vcpus online" % (vcpus_online)) + log.debug("found %d vcpus online", vcpus_online) # disable any extra vcpus that are online over the requested target for vcpu in range(target, vcpus_online): - log.info("enforcement is disabling DOM%d VCPU%d" % (dom, vcpu)) + log.info("enforcement is disabling DOM%d VCPU%d", dom, vcpu) self.vcpu_hotplug(vcpu, 0) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/XendLogging.py --- a/tools/python/xen/xend/XendLogging.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/XendLogging.py Tue Oct 11 22:57:44 2005 @@ -13,79 +13,84 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ + +import tempfile import types import logging -from logging import Formatter, StreamHandler -from logging.handlers import RotatingFileHandler +import logging.handlers -class XendLogging: - KB = 1024 - MB = 1024 * KB - - maxBytes = 1 * MB - backupCount = 5 +__all__ = [ 'log', 'init', 'getLogFilename', 'addLogStderr', + 'removeLogStderr' ] - logStderrFormat = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" - logFileFormat = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" - dateFormat = "%Y-%m-%d %H:%M:%S" - - def __init__(self, filename, level=logging.INFO, maxBytes=None, backupCount=None): - """Initialise logging. Logs to 'filename' by default, but does not log to - stderr unless addLogStderr() is called. - """ - self.setLevel(level) - if maxBytes: - self.maxBytes = maxBytes - if backupCount: - self.backupCount = backupCount - self.initLogFile(filename) - self.initLogStderr() - - def setLevel(self, level): - if isinstance(level, types.StringType): - level = logging._levelNames[level] - self.getLogger().setLevel(level) - self.level = level - - def getLogger(self): - return logging.getLogger("xend") - - def initLogFile(self, filename): - """Create the file logger and add it. - """ - self.logfile = RotatingFileHandler(filename, - mode='a', - maxBytes=self.maxBytes, - backupCount=self.backupCount) - self.logfilename = filename - self.logfile.setFormatter(Formatter(self.logFileFormat, self.dateFormat)) - self.getLogger().addHandler(self.logfile) - - def getLogFile(self): - return self.logfile - - def getLogFilename(self): - return self.logfilename - - def initLogStderr(self): - """Create the stderr logger, but don't add it. - """ - self.logstderr = StreamHandler() - self.logstderr.setFormatter(Formatter(self.logStderrFormat, self.dateFormat)) - - def addLogStderr(self): - """Add logging to stderr.""" - self.getLogger().addHandler(self.logstderr) - - def removeLogStderr(self): - """Remove logging to stderr.""" - self.getLogger().removeHandler(self.logstderr) - - def getLogStderr(self): - return self.logstderr log = logging.getLogger("xend") - + + +DEFAULT_MAX_BYTES = 1 << 20 # 1MB +DEFAULT_BACKUP_COUNT = 5 + +STDERR_FORMAT = "[%(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" +LOGFILE_FORMAT = "[%(asctime)s %(name)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s" +DATE_FORMAT = "%Y-%m-%d %H:%M:%S" + + +stderrHandler = logging.StreamHandler() +stderrHandler.setFormatter(logging.Formatter(STDERR_FORMAT, DATE_FORMAT)) + +logfilename = None + + +def init(filename, level=logging.INFO, maxBytes=None, backupCount=None): + """Initialise logging. Logs to 'filename' by default, but does not log to + stderr unless addLogStderr() is called. + """ + + global logfilename + + def openFileHandler(fname): + return logging.handlers.RotatingFileHandler(fname, + mode='a', + maxBytes=maxBytes, + backupCount=backupCount) + + if not maxBytes: + maxBytes = DEFAULT_MAX_BYTES + if not backupCount: + backupCount = DEFAULT_BACKUP_COUNT + + # Rather unintuitively, getLevelName will get the number corresponding to + # a level name, as well as getting the name corresponding to a level + # number. setLevel seems to take the number only though, so convert if we + # are given a string. + if isinstance(level, types.StringType): + level = logging.getLevelName(level) + + log.setLevel(level) + + try: + fileHandler = openFileHandler(filename) + logfilename = filename + except IOError: + logfilename = tempfile.mkstemp("-xend.log")[1] + fileHandler = openFileHandler(logfilename) + + fileHandler.setFormatter(logging.Formatter(LOGFILE_FORMAT, DATE_FORMAT)) + log.addHandler(fileHandler) + + +def getLogFilename(): + return logfilename + + +def addLogStderr(): + """Add logging to stderr.""" + log.addHandler(stderrHandler) + + +def removeLogStderr(): + """Remove logging to stderr.""" + log.removeHandler(stderrHandler) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/XendRoot.py --- a/tools/python/xen/xend/XendRoot.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/XendRoot.py Tue Oct 11 22:57:44 2005 @@ -13,6 +13,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ """Xend root class. @@ -29,7 +30,7 @@ import string import sys -from XendLogging import XendLogging +import XendLogging from XendError import XendError import sxp @@ -92,7 +93,6 @@ def __init__(self): self.config_path = None self.config = None - self.logging = None self.configure() @@ -114,84 +114,22 @@ """ return self.components.get(name) - def _format(self, msg, args): - if args: - return str(msg) % args - else: - return str(msg) - - def _log(self, mode, fmt, args): - """Logging function that uses the logger if it exists, otherwise - logs to stderr. We use this for XendRoot log messages because - they may be logged before the logger has been configured. - Other components can safely use the logger. - """ - log = self.get_logger() - if mode not in ['warning', 'info', 'debug', 'error']: - mode = 'info' - level = mode.upper() - if log: - getattr(log, mode)(fmt, *args) - else: - print >>sys.stderr, "xend", "[%s]" % level, self._format(fmt, args) - - def logDebug(self, fmt, *args): - """Log a debug message. - - @param fmt: message format - @param args: arguments - """ - self._log('debug', fmt, args) - - def logInfo(self, fmt, *args): - """Log an info message. - - @param fmt: message format - @param args: arguments - """ - self._log('info', fmt, args) - - def logWarning(self, fmt, *args): - """Log a warning message. - - @param fmt: message format - @param args: arguments - """ - self._log('warning', fmt, args) - - def logError(self, fmt, *args): - """Log an error message. - - @param fmt: message format - @param args: arguments - """ - self._log('error', fmt, args) - - def event_handler(self, event, val): - self.logInfo("EVENT> %s %s", str(event), str(val)) + def _logError(self, fmt, args): + """Logging function to log to stderr. We use this for XendRoot log + messages because they may be logged before the logger has been + configured. Other components can safely use the logger. + """ + print >>sys.stderr, "xend [ERROR]", fmt % args def configure(self): self.set_config() - self.configure_logger() - - def configure_logger(self): logfile = self.get_config_value("logfile", self.logfile_default) loglevel = self.get_config_value("loglevel", self.loglevel_default) - self.logging = XendLogging(logfile, level=loglevel) + XendLogging.init(logfile, level = loglevel) from xen.xend.server import params if params.XEND_DEBUG: - self.logging.addLogStderr() - - def get_logging(self): - """Get the XendLogging instance. - """ - return self.logging - - def get_logger(self): - """Get the logger. - """ - return self.logging and self.logging.getLogger() + XendLogging.addLogStderr() def set_config(self): """If the config file exists, read it. If not, ignore it. @@ -200,7 +138,6 @@ """ self.config_path = os.getenv(self.config_var, self.config_default) if os.path.exists(self.config_path): - #self.logInfo('Reading config file %s', self.config_path) try: fin = file(self.config_path, 'rb') try: @@ -210,10 +147,12 @@ config.insert(0, 'xend-config') self.config = config except Exception, ex: - self.logError('Reading config file %s: %s', self.config_path, str(ex)) + self._logError('Reading config file %s: %s', + self.config_path, str(ex)) raise else: - self.logError('Config file does not exist: %s', self.config_path) + self._logError('Config file does not exist: %s', + self.config_path) self.config = ['xend-config'] def get_config(self, name=None): @@ -339,11 +278,6 @@ inst = XendRoot() return inst -def logger(): - """Get the logger. - """ - return instance().get_logger() - def add_component(name, val): """Register a component with XendRoot. This is used to work-round import cycles. diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/server/SrvDaemon.py --- a/tools/python/xen/xend/server/SrvDaemon.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/server/SrvDaemon.py Tue Oct 11 22:57:44 2005 @@ -38,7 +38,7 @@ pythonex = '(?P<python>\S*python\S*)' cmdex = '(?P<cmd>.*)' procre = re.compile('^\s*' + pidex + '\s*' + pythonex + '\s*' + cmdex + '$') - xendre = re.compile('^/usr/sbin/xend\s*(start|restart)\s*.*$') + xendre = re.compile('^\S+/xend\s*(start|restart)\s*.*$') procs = os.popen('ps -e -o pid,args 2>/dev/null') for proc in procs: pm = procre.match(proc) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/server/SrvDomain.py --- a/tools/python/xen/xend/server/SrvDomain.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/server/SrvDomain.py Tue Oct 11 22:57:44 2005 @@ -51,40 +51,28 @@ val = self.xd.domain_pause(self.dom.domid) return val - def op_shutdown(self, op, req): - fn = FormFn(self.xd.domain_shutdown, - [['dom', 'int'], - ['reason', 'str']]) - val = fn(req.args, {'dom': self.dom.domid}) + def acceptCommand(self, req): req.setResponseCode(http.ACCEPTED) req.setHeader("Location", "%s/.." % req.prePathURL()) - return val + + def op_shutdown(self, op, req): + self.acceptCommand(req) + return self.dom.shutdown(req.args['reason'][0]) def op_sysrq(self, op, req): - fn = FormFn(self.xd.domain_sysrq, - [['dom', 'int'], - ['key', 'int']]) - val = fn(req.args, {'dom' : self.dom.domid}) - req.setResponseCode(http.ACCEPTED) - req.setHeader("Location", "%s/.." % req.prePathURL()) - return val + self.acceptCommand(req) + return self.dom.send_sysrq(int(req.args['key'][0])) def op_destroy(self, op, req): - fn = FormFn(self.xd.domain_destroy, - [['dom', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - req.setHeader("Location", "%s/.." % req.prePathURL()) - return val + self.acceptCommand(req) + return self.xd.domain_destroy(self.dom.domid) def op_save(self, op, req): + self.acceptCommand(req) return req.threadRequest(self.do_save, op, req) def do_save(self, op, req): - fn = FormFn(self.xd.domain_save, - [['dom', 'int'], - ['file', 'str']]) - val = fn(req.args, {'dom': self.dom.domid}) - return 0 + return self.xd.domain_save(self.dom.domid, req.args['file'][0]) def op_migrate(self, op, req): return req.threadRequest(self.do_migrate, op, req) @@ -134,43 +122,39 @@ ['memory', 'int']]) val = fn(req.args, {'dom': self.dom.domid}) return val - + + + def call(self, fn, args, req): + return FormFn(fn, args)(req.args) + + def op_mem_target_set(self, op, req): - fn = FormFn(self.xd.domain_mem_target_set, - [['dom', 'int'], - ['target', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val + return self.call(self.dom.setMemoryTarget, + [['target', 'int']], + req) def op_devices(self, op, req): - fn = FormFn(self.xd.domain_devtype_ls, - [['dom', 'int'], - ['type', 'str']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val + return self.call(self.dom.getDeviceSxprs, + [['type', 'str']], + req) def op_device_create(self, op, req): - fn = FormFn(self.xd.domain_device_create, - [['dom', 'int'], - ['config', 'sxpr']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val + return self.call(self.dom.device_create, + [['config', 'sxpr']], + req) def op_device_destroy(self, op, req): - fn = FormFn(self.xd.domain_device_destroy, - [['dom', 'int'], - ['type', 'str'], - ['dev', 'str']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val + return self.call(self.dom.destroyDevice, + [['type', 'str'], + ['dev', 'int']], + req) def op_device_configure(self, op, req): - fn = FormFn(self.xd.domain_device_configure, - [['dom', 'int'], - ['config', 'sxpr'], - ['dev', 'str']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val + return self.call(self.dom.device_configure, + [['config', 'sxpr'], + ['dev', 'int']], + req) + def op_vif_limit_set(self, op, req): fn = FormFn(self.xd.domain_vif_limit_set, @@ -182,12 +166,10 @@ return val def op_vcpu_hotplug(self, op, req): - fn = FormFn(self.xd.domain_vcpu_hotplug, - [['dom', 'int'], - ['vcpu', 'int'], - ['state', 'int']]) - val = fn(req.args, {'dom': self.dom.domid}) - return val + return self.call(self.dom.vcpu_hotplug, + [['vcpu', 'int'], + ['state', 'int']], + req) def render_POST(self, req): return self.perform(req) @@ -201,7 +183,6 @@ # # if op and op[0] in ['vifs', 'vif', 'vbds', 'vbd', 'mem_target_set']: # return self.perform(req) - self.dom.update() if self.use_sxp(req): req.setHeader("Content-Type", sxp.mime_type) sxp.show(self.dom.sxpr(), out=req) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/server/SrvDomainDir.py --- a/tools/python/xen/xend/server/SrvDomainDir.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/server/SrvDomainDir.py Tue Oct 11 22:57:44 2005 @@ -22,12 +22,14 @@ from xen.xend import sxp from xen.xend import XendDomain +from xen.xend.XendDomainInfo import XendDomainInfo from xen.xend.Args import FormFn from xen.xend.XendError import XendError from xen.xend.XendLogging import log from xen.web.SrvDir import SrvDir from SrvDomain import SrvDomain + class SrvDomainDir(SrvDir): """Service that manages the domain directory. @@ -124,28 +126,41 @@ out.close() return val + + def op_list(self, _, req): + """List the details for this domain.""" + self._list(req, True) + + def render_POST(self, req): return self.perform(req) def render_GET(self, req): + self._list(req, 'detail' in req.args and req.args['detail'] == ['1']) + + + def _list(self, req, detail): if self.use_sxp(req): req.setHeader("Content-Type", sxp.mime_type) - self.ls_domain(req, 1) + self.ls_domain(req, detail, True) else: req.write("<html><head></head><body>") self.print_path(req) self.ls(req) - self.ls_domain(req) + self.ls_domain(req, detail, False) self.form(req) req.write("</body></html>") - def ls_domain(self, req, use_sxp=0): + + def ls_domain(self, req, detail, use_sxp): url = req.prePathURL() if not url.endswith('/'): url += '/' if use_sxp: - domains = self.xd.list_names() - sxp.show(domains, out=req) + if detail: + sxp.show(map(XendDomainInfo.sxpr, self.xd.list()), out=req) + else: + sxp.show(self.xd.list_names(), out=req) else: domains = self.xd.list_sorted() req.write('<ul>') @@ -157,6 +172,7 @@ d.getMemoryTarget(), d.getSsidref())) req.write('</li>') req.write('</ul>') + def form(self, req): """Generate the form(s) for domain dir operations. diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/server/SrvServer.py Tue Oct 11 22:57:44 2005 @@ -1,4 +1,3 @@ -#!/usr/bin/python #============================================================================ # This library is free software; you can redistribute it and/or # modify it under the terms of version 2.1 of the GNU Lesser General Public diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/server/SrvXendLog.py --- a/tools/python/xen/xend/server/SrvXendLog.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/server/SrvXendLog.py Tue Oct 11 22:57:44 2005 @@ -13,11 +13,12 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ from xen.web import static -from xen.xend import XendRoot +from xen.xend import XendLogging from xen.web.SrvDir import SrvDir @@ -27,8 +28,8 @@ def __init__(self): SrvDir.__init__(self) - logging = XendRoot.instance().get_logging() - self.logfile = static.File(logging.getLogFilename(), defaultType="text/plain") + self.logfile = static.File(XendLogging.getLogFilename(), + defaultType="text/plain") self.logfile.type = "text/plain" self.logfile.encoding = None diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/server/event.py --- a/tools/python/xen/xend/server/event.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/server/event.py Tue Oct 11 22:57:44 2005 @@ -25,6 +25,7 @@ from xen.xend import sxp from xen.xend import PrettyPrint from xen.xend.XendError import XendError +from xen.xend import XendLogging from xen.xend import XendRoot @@ -146,11 +147,10 @@ def op_log_stderr(self, _, v): mode = v[1] - logging = xroot.get_logging() if mode == 'on': - logging.addLogStderr() + XendLogging.addLogStderr() else: - logging.removeLogStderr() + XendLogging.removeLogStderr() def op_domain_ls(self, _1, _2): xd = xroot.get_component("xen.xend.XendDomain") diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/sxp.py --- a/tools/python/xen/xend/sxp.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/sxp.py Tue Oct 11 22:57:44 2005 @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python #============================================================================ # This library is free software; you can redistribute it and/or # modify it under the terms of version 2.1 of the GNU Lesser General Public diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/uuid.py --- a/tools/python/xen/xend/uuid.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/uuid.py Tue Oct 11 22:57:44 2005 @@ -13,14 +13,19 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ # Copyright (C) 2005 Mike Wray <mike.wray@xxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ + """Universal(ly) Unique Identifiers (UUIDs). """ + + import commands import random -def uuidgen(random=True): + +def getUuidUuidgen(random = True): """Generate a UUID using the command uuidgen. If random is true (default) generates a random uuid. @@ -33,50 +38,21 @@ cmd += " -t" return commands.getoutput(cmd) -class UuidFactoryUuidgen: - """A uuid factory using uuidgen.""" +def getUuidRandom(): + """Generate a random UUID.""" + + bytes = [ random.randint(0, 255) for i in range(0, 16) ] + # Encode the variant. + bytes[6] = (bytes[6] & 0x0f) | 0x40 + bytes[8] = (bytes[8] & 0x3f) | 0x80 + f = "%02x" + return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(bytes) ) - def __init__(self): - pass - def getUuid(self): - return uuidgen() +#uuidFactory = getUuidUuidgen +uuidFactory = getUuidRandom -class UuidFactoryRandom: - - """A random uuid factory.""" - - def __init__(self): - f = file("/dev/urandom", "r") - seed = f.read(16) - f.close() - self.rand = random.Random(seed) - - def randBytes(self, n): - return [ self.rand.randint(0, 255) for i in range(0, n) ] - - def getUuid(self): - bytes = self.randBytes(16) - # Encode the variant. - bytes[6] = (bytes[6] & 0x0f) | 0x40 - bytes[8] = (bytes[8] & 0x3f) | 0x80 - f = "%02x" - return ( "-".join([f*4, f*2, f*2, f*2, f*6]) % tuple(bytes) ) - -def getFactory(): - """Get the factory to use for creating uuids. - This is so it's easy to change the uuid factory. - For example, for testing we might want repeatable uuids - rather than the random ones we normally use. - """ - global uuidFactory - try: - uuidFactory - except: - #uuidFactory = UuidFactoryUuidgen() - uuidFactory = UuidFactoryRandom() - return uuidFactory def getUuid(): - return getFactory().getUuid() + return uuidFactory() diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/xenstore/xstransact.py --- a/tools/python/xen/xend/xenstore/xstransact.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/xenstore/xstransact.py Tue Oct 11 22:57:44 2005 @@ -14,29 +14,34 @@ class xstransact: def __init__(self, path): - self.in_transaction = False self.path = path.rstrip("/") - xshandle().transaction_start() + self.transaction = xshandle().transaction_start() self.in_transaction = True def __del__(self): if self.in_transaction: - xshandle().transaction_end(True) + xshandle().transaction_end(self.transaction, True) def commit(self): if not self.in_transaction: raise RuntimeError self.in_transaction = False - return xshandle().transaction_end(False) + rc = xshandle().transaction_end(self.transaction, False) + self.transaction = "0" + return rc def abort(self): + if not self.in_transaction: + return True self.in_transaction = False - return xshandle().transaction_end(True) + rc = xshandle().transaction_end(self.transaction, True) + self.transaction = "0" + return rc def _read(self, key): path = "%s/%s" % (self.path, key) try: - return xshandle().read(path) + return xshandle().read(self.transaction, path) except RuntimeError, ex: raise RuntimeError(ex.args[0], '%s, while reading %s' % (ex.args[1], path)) @@ -50,7 +55,7 @@ instead. """ if len(args) == 0: - return xshandle().read(self.path) + return xshandle().read(self.transaction, self.path) if len(args) == 1: return self._read(args[0]) ret = [] @@ -61,7 +66,7 @@ def _write(self, key, data): path = "%s/%s" % (self.path, key) try: - xshandle().write(path, data) + xshandle().write(self.transaction, path, data) except RuntimeError, ex: raise RuntimeError(ex.args[0], ('%s, while writing %s : %s' % @@ -93,7 +98,7 @@ def _remove(self, key): path = "%s/%s" % (self.path, key) - return xshandle().rm(path) + return xshandle().rm(self.transaction, path) def remove(self, *args): """If no arguments are given, remove this transaction's path. @@ -101,14 +106,14 @@ path, and remove each of those instead. """ if len(args) == 0: - xshandle().rm(self.path) + xshandle().rm(self.transaction, self.path) else: for key in args: self._remove(key) def _list(self, key): path = "%s/%s" % (self.path, key) - l = xshandle().ls(path) + l = xshandle().ls(self.transaction, path) if l: return map(lambda x: key + "/" + x, l) return [] @@ -120,7 +125,7 @@ path, and return the cumulative listing of each of those instead. """ if len(args) == 0: - ret = xshandle().ls(self.path) + ret = xshandle().ls(self.transaction, self.path) if ret is None: return [] else: @@ -136,11 +141,11 @@ ret = [] for key in keys: new_subdir = subdir + "/" + key - l = xshandle().ls(new_subdir) + l = xshandle().ls(self.transaction, new_subdir) if l: ret.append([key, self.list_recursive_(new_subdir, l)]) else: - ret.append([key, xshandle().read(new_subdir)]) + ret.append([key, xshandle().read(self.transaction, new_subdir)]) return ret diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xend/xenstore/xswatch.py --- a/tools/python/xen/xend/xenstore/xswatch.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xend/xenstore/xswatch.py Tue Oct 11 22:57:44 2005 @@ -8,6 +8,7 @@ import select import threading from xen.lowlevel import xs +from xen.xend.xenstore.xsutil import xshandle class xswatch: @@ -27,10 +28,7 @@ if cls.watchThread: cls.xslock.release() return - # XXX: When we fix xenstored to have better watch semantics, - # this can change to shared xshandle(). Currently that would result - # in duplicate watch firings, thus failed extra xs.acknowledge_watch. - cls.xs = xs.open() + cls.xs = xshandle() cls.watchThread = threading.Thread(name="Watcher", target=cls.watchMain) cls.watchThread.setDaemon(True) @@ -43,11 +41,10 @@ while True: try: we = cls.xs.read_watch() - watch = we[1] - cls.xs.acknowledge_watch(watch) except RuntimeError, ex: print ex raise + watch = we[1] watch.fn(*watch.args, **watch.kwargs) watchMain = classmethod(watchMain) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xm/create.py Tue Oct 11 22:57:44 2005 @@ -14,11 +14,14 @@ #============================================================================ # Copyright (C) 2004, 2005 Mike Wray <mike.wray@xxxxxx> # Copyright (C) 2005 Nguyen Anh Quynh <aquynh@xxxxxxxxx> +# Copyright (C) 2005 XenSource Ltd #============================================================================ """Domain creation. """ import random +import os +import os.path import string import sys import socket @@ -35,6 +38,9 @@ from xen.util import blkif from xen.xm.opts import * + +import console + gopts = Opts(use="""[options] [vars] @@ -879,8 +885,7 @@ dom = make_domain(opts, config) if opts.vals.console_autoconnect: - cmd = "/usr/libexec/xen/xenconsole %d" % dom - os.execvp('/usr/libexec/xen/xenconsole', cmd.split()) + console.execConsole(dom) if __name__ == '__main__': main(sys.argv) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xm/main.py --- a/tools/python/xen/xm/main.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xm/main.py Tue Oct 11 22:57:44 2005 @@ -37,6 +37,8 @@ from xen.xend import PrettyPrint from xen.xend import sxp from xen.xm.opts import * + +import console shorthelp = """Usage: xm <subcommand> [args] @@ -225,25 +227,22 @@ if k in ['-v', '--vcpus']: show_vcpus = 1 - domsinfo = [] from xen.xend.XendClient import server if n == 0: - doms = server.xend_domains() - doms.sort() - else: - doms = params - for dom in doms: - info = server.xend_domain(dom) - domsinfo.append(parse_doms_info(info)) + doms = server.xend_list_domains() + else: + doms = map(server.xend_domain, params) if use_long: for dom in doms: - info = server.xend_domain(dom) - PrettyPrint.prettyprint(info) - elif show_vcpus: - xm_show_vcpus(domsinfo) - else: - xm_brief_list(domsinfo) + PrettyPrint.prettyprint(doms) + else: + domsinfo = map(parse_doms_info, doms) + + if show_vcpus: + xm_show_vcpus(domsinfo) + else: + xm_brief_list(domsinfo) def parse_doms_info(info): dominfo = {} @@ -279,12 +278,12 @@ return dominfo def xm_brief_list(domsinfo): - print 'Name Id Mem(MB) CPU VCPU(s) State Time(s)' + print 'Name ID Mem(MiB) CPU VCPUs State Time(s)' for dominfo in domsinfo: if dominfo.has_key("ssidref1"): - print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo) + print ("%(name)-16s %(dom)3d %(mem)8d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f s:%(ssidref2)02x/p:%(ssidref1)02x" % dominfo) else: - print ("%(name)-16s %(dom)3d %(mem)7d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f" % dominfo) + print ("%(name)-16s %(dom)3d %(mem)8d %(cpu)3s %(vcpus)5d %(state)5s %(cpu_time)7.1f" % dominfo) def xm_show_vcpus(domsinfo): print 'Name Id VCPU CPU CPUMAP' @@ -445,12 +444,11 @@ from xen.xend.XendClient import server info = server.xend_domain(dom) domid = int(sxp.child_value(info, 'domid', '-1')) - cmd = "/usr/libexec/xen/xenconsole %d" % domid - os.execvp('/usr/libexec/xen/xenconsole', cmd.split()) - console = sxp.child(info, "console") + console.execConsole(domid) + def xm_top(args): - os.execv('/usr/sbin/xentop', ['/usr/sbin/xentop']) + os.execvp('xentop', ['xentop']) def xm_dmesg(args): diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xm/sysrq.py --- a/tools/python/xen/xm/sysrq.py Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xm/sysrq.py Tue Oct 11 22:57:44 2005 @@ -1,16 +1,11 @@ # (C) Matthew Bloch <matthew@xxxxxxxxxxxxxx> 2004 +# Copyright (C) 2005 XenSource Ltd -"""Domain shutdown. +"""Domain sysrq. """ -import string -import sys -import time from xen.xend.XendClient import server from xen.xm.opts import * - -DOM0_NAME = 'Domain-0' -DOM0_ID = '0' gopts = Opts(use="""[DOM] [letter] diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xcutils/Makefile --- a/tools/xcutils/Makefile Tue Oct 11 21:50:21 2005 +++ b/tools/xcutils/Makefile Tue Oct 11 22:57:44 2005 @@ -15,7 +15,7 @@ XEN_ROOT = ../.. include $(XEN_ROOT)/tools/Rules.mk -PROGRAMS_INSTALL_DIR = /usr/libexec/xen +PROGRAMS_INSTALL_DIR = /usr/$(LIBDIR)/xen/bin INCLUDES += -I $(XEN_LIBXC) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/Makefile --- a/tools/xenstore/Makefile Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/Makefile Tue Oct 11 22:57:44 2005 @@ -8,7 +8,7 @@ INSTALL_DIR = $(INSTALL) -d -m0755 PROFILE=#-pg -BASECFLAGS=-Wall -W -g -Werror +BASECFLAGS=-Wall -g -Werror # Make gcc generate dependencies. BASECFLAGS += -Wp,-MD,.$(@F).d PROG_DEP = .*.d @@ -27,7 +27,7 @@ CLIENTS += xenstore-write CLIENTS_OBJS := $(patsubst xenstore-%,xenstore_%.o,$(CLIENTS)) -all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump +all: libxenstore.so xenstored $(CLIENTS) xs_tdb_dump xsls testcode: xs_test xenstored_test xs_random @@ -39,6 +39,9 @@ $(CLIENTS_OBJS): xenstore_%.o: xenstore_client.c $(COMPILE.c) -DCLIENT_$(*F) -o $@ $< + +xsls: xsls.o + $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lxenctrl -L. -lxenstore -o $@ 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 $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@ @@ -126,7 +129,7 @@ tarball: clean cd .. && tar -c -j -v -h -f xenstore.tar.bz2 xenstore/ -install: libxenstore.so xenstored $(CLIENTS) +install: libxenstore.so xenstored xsls $(CLIENTS) $(INSTALL_DIR) -p $(DESTDIR)/var/run/xenstored $(INSTALL_DIR) -p $(DESTDIR)/var/lib/xenstored $(INSTALL_DIR) -p $(DESTDIR)/usr/bin @@ -134,6 +137,7 @@ $(INSTALL_DIR) -p $(DESTDIR)/usr/include $(INSTALL_PROG) xenstored $(DESTDIR)/usr/sbin $(INSTALL_PROG) $(CLIENTS) $(DESTDIR)/usr/bin + $(INSTALL_PROG) xsls $(DESTDIR)/usr/bin $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR) $(INSTALL_DATA) libxenstore.so $(DESTDIR)/usr/$(LIBDIR) $(INSTALL_DATA) xs.h $(DESTDIR)/usr/include diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/testsuite/07watch.test --- a/tools/xenstore/testsuite/07watch.test Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/testsuite/07watch.test Tue Oct 11 22:57:44 2005 @@ -5,7 +5,6 @@ 2 write /test contents2 expect 1:/test:token 1 waitwatch -1 ackwatch token 1 close # Check that reads don't set it off. @@ -22,15 +21,12 @@ 2 mkdir /dir/newdir expect 1:/dir/newdir:token 1 waitwatch -1 ackwatch token 2 setperm /dir/newdir 0 READ expect 1:/dir/newdir:token 1 waitwatch -1 ackwatch token 2 rm /dir/newdir expect 1:/dir/newdir:token 1 waitwatch -1 ackwatch token 1 close 2 close @@ -49,7 +45,6 @@ read /dir/test expect /dir/test:token waitwatch -ackwatch token close # watch priority test: all simultaneous @@ -59,13 +54,10 @@ write /dir/test contents expect 3:/dir/test:token3 3 waitwatch -3 ackwatch token3 expect 2:/dir/test:token2 2 waitwatch -2 ackwatch token2 expect 1:/dir/test:token1 1 waitwatch -1 ackwatch token1 1 close 2 close 3 close @@ -79,7 +71,6 @@ 2 close expect 1:/dir/test:token1 1 waitwatch -1 ackwatch token1 1 close # If one dies (without reading at all), the other should still get ack. @@ -89,7 +80,6 @@ 2 close expect 1:/dir/test:token1 1 waitwatch -1 ackwatch token1 1 close 2 close @@ -111,7 +101,6 @@ 2 unwatch /dir token2 expect 1:/dir/test:token1 1 waitwatch -1 ackwatch token1 1 close 2 close @@ -123,14 +112,12 @@ write /dir/test contents2 expect 1:/dir/test:token2 1 waitwatch -1 ackwatch token2 # check we only get notified once. 1 watch /test token 2 write /test contents2 expect 1:/test:token 1 waitwatch -1 ackwatch token expect 1: waitwatch failed: Connection timed out 1 waitwatch 1 close @@ -142,13 +129,10 @@ 2 write /test3 contents expect 1:/test1:token 1 waitwatch -1 ackwatch token expect 1:/test2:token 1 waitwatch -1 ackwatch token expect 1:/test3:token 1 waitwatch -1 ackwatch token 1 close # Creation of subpaths should be covered correctly. @@ -157,10 +141,8 @@ 2 write /test/subnode/subnode contents2 expect 1:/test/subnode:token 1 waitwatch -1 ackwatch token expect 1:/test/subnode/subnode:token 1 waitwatch -1 ackwatch token expect 1: waitwatch failed: Connection timed out 1 waitwatch 1 close @@ -171,7 +153,6 @@ 1 watchnoack / token2 0 expect 1:/test/subnode:token 1 waitwatch -1 ackwatch token expect 1:/:token2 1 waitwatch expect 1: waitwatch failed: Connection timed out @@ -183,7 +164,6 @@ 2 rm /test expect 1:/test/subnode:token 1 waitwatch -1 ackwatch token # Watch should not double-send after we ack, even if we did something in between. 1 watch /test2 token @@ -192,6 +172,5 @@ 1 waitwatch expect 1:contents2 1 read /test2/foo -1 ackwatch token expect 1: waitwatch failed: Connection timed out 1 waitwatch diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/testsuite/08transaction.test --- a/tools/xenstore/testsuite/08transaction.test Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/testsuite/08transaction.test Tue Oct 11 22:57:44 2005 @@ -68,7 +68,6 @@ 2 commit expect 1:/test/dir/sub:token 1 waitwatch -1 ackwatch token 1 close # Rm inside transaction works like rm outside: children get notified. @@ -78,7 +77,6 @@ 2 commit expect 1:/test/dir/sub:token 1 waitwatch -1 ackwatch token 1 close # Multiple events from single transaction don't trigger assert @@ -89,8 +87,6 @@ 2 commit expect 1:/test/1:token 1 waitwatch -1 ackwatch token expect 1:/test/2:token 1 waitwatch -1 ackwatch token 1 close diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/testsuite/10domain-homedir.test --- a/tools/xenstore/testsuite/10domain-homedir.test Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/testsuite/10domain-homedir.test Tue Oct 11 22:57:44 2005 @@ -16,4 +16,3 @@ write /home/foo/bar contents expect 1:foo/bar:token 1 waitwatch -1 ackwatch token diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/testsuite/11domain-watch.test --- a/tools/xenstore/testsuite/11domain-watch.test Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/testsuite/11domain-watch.test Tue Oct 11 22:57:44 2005 @@ -10,7 +10,6 @@ write /test contents2 expect 1:/test:token 1 waitwatch -1 ackwatch token 1 unwatch /test token release 1 1 close @@ -25,7 +24,6 @@ 1 write /dir/test4 contents4 expect 1:/dir/test:token 1 waitwatch -1 ackwatch token release 1 1 close diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/testsuite/12readonly.test --- a/tools/xenstore/testsuite/12readonly.test Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/testsuite/12readonly.test Tue Oct 11 22:57:44 2005 @@ -36,4 +36,3 @@ 1 write /test contents expect /test:token waitwatch -ackwatch token diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/testsuite/13watch-ack.test --- a/tools/xenstore/testsuite/13watch-ack.test Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/testsuite/13watch-ack.test Tue Oct 11 22:57:44 2005 @@ -18,5 +18,4 @@ 1 waitwatch 3 write /test/1 contents1 4 write /test/3 contents3 -1 ackwatch token2 1 close diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/utils.h --- a/tools/xenstore/utils.h Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/utils.h Tue Oct 11 22:57:44 2005 @@ -55,4 +55,34 @@ #define dprintf(_fmt, _args...) ((void)0) #endif +/* + * Mux errno values onto returned pointers. + */ + +static inline void *ERR_PTR(long error) +{ + return (void *)error; +} + +static inline long PTR_ERR(const void *ptr) +{ + return (long)ptr; +} + +static inline long IS_ERR(const void *ptr) +{ + return ((unsigned long)ptr > (unsigned long)-1000L); +} + + #endif /* _UTILS_H */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstore_client.c --- a/tools/xenstore/xenstore_client.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstore_client.c Tue Oct 11 22:57:44 2005 @@ -20,11 +20,11 @@ usage(const char *progname) { #if defined(CLIENT_read) - errx(1, "Usage: %s [-h] [-p] key [...]", progname); + errx(1, "Usage: %s [-h] [-p] [-s] key [...]", progname); #elif defined(CLIENT_write) - errx(1, "Usage: %s [-h] key value [...]", progname); + errx(1, "Usage: %s [-h] [-s] key value [...]", progname); #elif defined(CLIENT_rm) || defined(CLIENT_exists) || defined(CLIENT_list) - errx(1, "Usage: %s [-h] key [...]", progname); + errx(1, "Usage: %s [-h] [-s] key [...]", progname); #endif } @@ -32,15 +32,12 @@ main(int argc, char **argv) { struct xs_handle *xsh; + struct xs_transaction_handle *xth; bool success; - int ret = 0; + int ret = 0, socket = 0; #if defined(CLIENT_read) || defined(CLIENT_list) int prefix = 0; #endif - - xsh = xs_domain_open(); - if (xsh == NULL) - err(1, "xs_domain_open"); while (1) { int c, index = 0; @@ -49,10 +46,11 @@ #if defined(CLIENT_read) || defined(CLIENT_list) {"prefix", 0, 0, 'p'}, #endif + {"socket", 0, 0, 's'}, {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "h" + c = getopt_long(argc, argv, "hs" #if defined(CLIENT_read) || defined(CLIENT_list) "p" #endif @@ -64,6 +62,9 @@ case 'h': usage(argv[0]); /* NOTREACHED */ + case 's': + socket = 1; + break; #if defined(CLIENT_read) || defined(CLIENT_list) case 'p': prefix = 1; @@ -83,14 +84,18 @@ } #endif + xsh = socket ? xs_daemon_open() : xs_domain_open(); + if (xsh == NULL) + err(1, socket ? "xs_daemon_open" : "xs_domain_open"); + again: - success = xs_transaction_start(xsh); - if (!success) + xth = xs_transaction_start(xsh); + if (xth == NULL) errx(1, "couldn't start transaction"); while (optind < argc) { #if defined(CLIENT_read) - char *val = xs_read(xsh, argv[optind], NULL); + char *val = xs_read(xsh, xth, argv[optind], NULL); if (val == NULL) { warnx("couldn't read path %s", argv[optind]); ret = 1; @@ -102,7 +107,7 @@ free(val); optind++; #elif defined(CLIENT_write) - success = xs_write(xsh, argv[optind], argv[optind + 1], + success = xs_write(xsh, xth, argv[optind], argv[optind + 1], strlen(argv[optind + 1])); if (!success) { warnx("could not write path %s", argv[optind]); @@ -111,7 +116,7 @@ } optind += 2; #elif defined(CLIENT_rm) - success = xs_rm(xsh, argv[optind]); + success = xs_rm(xsh, xth, argv[optind]); if (!success) { warnx("could not remove path %s", argv[optind]); ret = 1; @@ -119,7 +124,7 @@ } optind++; #elif defined(CLIENT_exists) - char *val = xs_read(xsh, argv[optind], NULL); + char *val = xs_read(xsh, xth, argv[optind], NULL); if (val == NULL) { ret = 1; goto out; @@ -128,7 +133,7 @@ optind++; #elif defined(CLIENT_list) unsigned int i, num; - char **list = xs_directory(xsh, argv[optind], &num); + char **list = xs_directory(xsh, xth, argv[optind], &num); if (list == NULL) { warnx("could not list path %s", argv[optind]); ret = 1; @@ -145,7 +150,7 @@ } out: - success = xs_transaction_end(xsh, ret ? true : false); + success = xs_transaction_end(xsh, xth, ret ? true : false); if (!success) { if (ret == 0 && errno == EAGAIN) goto again; diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_core.c Tue Oct 11 22:57:44 2005 @@ -154,7 +154,6 @@ case XS_READ: return "READ"; case XS_GET_PERMS: return "GET_PERMS"; case XS_WATCH: return "WATCH"; - case XS_WATCH_ACK: return "WATCH_ACK"; case XS_UNWATCH: return "UNWATCH"; case XS_TRANSACTION_START: return "TRANSACTION_START"; case XS_TRANSACTION_END: return "TRANSACTION_END"; @@ -236,10 +235,14 @@ talloc_free(str); } -static bool write_message(struct connection *conn) +static bool write_messages(struct connection *conn) { int ret; - struct buffered_data *out = conn->out; + struct buffered_data *out; + + out = list_top(&conn->out_list, struct buffered_data, list); + if (out == NULL) + return true; if (out->inhdr) { if (verbose) @@ -265,7 +268,6 @@ ret = conn->write(conn, out->buffer + out->used, out->hdr.msg.len - out->used); - if (ret < 0) return false; @@ -274,14 +276,10 @@ return true; trace_io(conn, "OUT", out); - conn->out = NULL; + + list_del(&out->list); talloc_free(out); - queue_next_event(conn); - - /* No longer busy? */ - if (!conn->out) - conn->state = OK; return true; } @@ -298,9 +296,9 @@ FD_SET(conn->fd, &set); none.tv_sec = none.tv_usec = 0; - while (conn->out + while (!list_empty(&conn->out_list) && select(conn->fd+1, NULL, &set, NULL, &none) == 1) - if (!write_message(conn)) + if (!write_messages(conn)) break; close(conn->fd); } @@ -327,9 +325,8 @@ list_for_each_entry(i, &connections, list) { if (i->domain) continue; - if (i->state == OK) - FD_SET(i->fd, inset); - if (i->out) + FD_SET(i->fd, inset); + if (!list_empty(&i->out_list)) FD_SET(i->fd, outset); if (i->fd > max) max = i->fd; @@ -542,6 +539,9 @@ struct buffered_data *data; data = talloc(ctx, struct buffered_data); + if (data == NULL) + return NULL; + data->inhdr = true; data->used = 0; data->buffer = NULL; @@ -586,23 +586,25 @@ { struct buffered_data *bdata; - /* When data gets freed, we want list entry is destroyed (so - * list entry is a child). */ + /* Message is a child of the connection context for auto-cleanup. */ bdata = new_buffer(conn); bdata->buffer = talloc_array(bdata, char, len); + /* Echo request header in reply unless this is an async watch event. */ + if (type != XS_WATCH_EVENT) { + memcpy(&bdata->hdr.msg, &conn->in->hdr.msg, + sizeof(struct xsd_sockmsg)); + } else { + memset(&bdata->hdr.msg, 0, sizeof(struct xsd_sockmsg)); + } + + /* Update relevant header fields and fill in the message body. */ bdata->hdr.msg.type = type; bdata->hdr.msg.len = len; memcpy(bdata->buffer, data, len); - /* There might be an event going out now. Queue behind it. */ - if (conn->out) { - assert(conn->out->hdr.msg.type == XS_WATCH_EVENT); - assert(!conn->waiting_reply); - conn->waiting_reply = bdata; - } else - conn->out = bdata; - conn->state = BUSY; + /* Queue for later transmission. */ + list_add_tail(&bdata->list, &conn->out_list); } /* Some routines (write, mkdir, etc) just need a non-error return */ @@ -1053,6 +1055,17 @@ */ static void process_message(struct connection *conn, struct buffered_data *in) { + struct transaction *trans; + + trans = transaction_lookup(conn, in->hdr.msg.tx_id); + if (IS_ERR(trans)) { + send_error(conn, -PTR_ERR(trans)); + return; + } + + assert(conn->transaction == NULL); + conn->transaction = trans; + switch (in->hdr.msg.type) { case XS_DIRECTORY: send_directory(conn, onearg(in)); @@ -1103,10 +1116,6 @@ do_watch(conn, in); break; - case XS_WATCH_ACK: - do_watch_ack(conn, onearg(in)); - break; - case XS_UNWATCH: do_unwatch(conn, in); break; @@ -1131,11 +1140,13 @@ do_get_domain_path(conn, onearg(in)); break; - case XS_WATCH_EVENT: default: eprintf("Client unknown operation %i", in->hdr.msg.type); send_error(conn, ENOSYS); - } + break; + } + + conn->transaction = NULL; } static int out_of_mem(void *data) @@ -1145,43 +1156,25 @@ static void consider_message(struct connection *conn) { - /* - * 'volatile' qualifier prevents register allocation which fixes: - * warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork' - */ - struct buffered_data *volatile in = NULL; - enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type; jmp_buf talloc_fail; - assert(conn->state == OK); + if (verbose) + xprintf("Got message %s len %i from %p\n", + sockmsg_string(conn->in->hdr.msg.type), + conn->in->hdr.msg.len, conn); /* For simplicity, we kill the connection on OOM. */ talloc_set_fail_handler(out_of_mem, &talloc_fail); if (setjmp(talloc_fail)) { - /* Free in before conn, in case it needs something. */ - talloc_free(in); talloc_free(conn); goto end; } - if (verbose) - xprintf("Got message %s len %i from %p\n", - sockmsg_string(type), conn->in->hdr.msg.len, conn); - - /* We might get a command while waiting for an ack: this means - * the other end discarded it: we will re-transmit. */ - if (type != XS_WATCH_ACK) - conn->waiting_for_ack = NULL; - - /* Careful: process_message may free connection. We detach - * "in" beforehand and allocate the new buffer to avoid - * touching conn after process_message. - */ - in = talloc_steal(talloc_autofree_context(), conn->in); + process_message(conn, conn->in); + + talloc_free(conn->in); conn->in = new_buffer(conn); - process_message(conn, in); - - talloc_free(in); + end: talloc_set_fail_handler(NULL, NULL); if (talloc_total_blocks(NULL) @@ -1196,10 +1189,7 @@ static void handle_input(struct connection *conn) { int bytes; - struct buffered_data *in; - - assert(conn->state == OK); - in = conn->in; + struct buffered_data *in = conn->in; /* Not finished header yet? */ if (in->inhdr) { @@ -1247,42 +1237,32 @@ static void handle_output(struct connection *conn) { - if (!write_message(conn)) + if (!write_messages(conn)) talloc_free(conn); } struct connection *new_connection(connwritefn_t *write, connreadfn_t *read) { - /* - * 'volatile' qualifier prevents register allocation which fixes: - * warning: variable 'xxx' might be clobbered by 'longjmp' or 'vfork' - */ - struct connection *volatile new; - jmp_buf talloc_fail; + struct connection *new; new = talloc(talloc_autofree_context(), struct connection); if (!new) return NULL; - new->state = OK; - new->out = new->waiting_reply = NULL; - new->waiting_for_ack = NULL; + memset(new, 0, sizeof(*new)); new->fd = -1; - new->id = 0; - new->domain = NULL; - new->transaction = NULL; new->write = write; new->read = read; new->can_write = true; + INIT_LIST_HEAD(&new->out_list); INIT_LIST_HEAD(&new->watches); - - talloc_set_fail_handler(out_of_mem, &talloc_fail); - if (setjmp(talloc_fail)) { + INIT_LIST_HEAD(&new->transaction_list); + + new->in = new_buffer(new); + if (new->in == NULL) { talloc_free(new); return NULL; } - new->in = new_buffer(new); - talloc_set_fail_handler(NULL, NULL); list_add_tail(&new->list, &connections); talloc_set_destructor(new, destroy_conn); @@ -1328,23 +1308,17 @@ list_for_each_entry(i, &connections, list) { printf("Connection %p:\n", i); printf(" state = %s\n", - i->state == OK ? "OK" - : i->state == BUSY ? "BUSY" - : "INVALID"); + list_empty(&i->out_list) ? "OK" : "BUSY"); if (i->id) printf(" id = %i\n", i->id); if (!i->in->inhdr || i->in->used) printf(" got %i bytes of %s\n", i->in->used, i->in->inhdr ? "header" : "data"); +#if 0 if (i->out) printf(" sending message %s (%s) out\n", sockmsg_string(i->out->hdr.msg.type), i->out->buffer); - if (i->waiting_reply) - printf(" ... and behind is queued %s (%s)\n", - sockmsg_string(i->waiting_reply->hdr.msg.type), - i->waiting_reply->buffer); -#if 0 if (i->transaction) dump_transaction(i); if (i->domain) @@ -1443,6 +1417,7 @@ static struct option options[] = { + { "no-domain-init", 0, NULL, 'D' }, { "pid-file", 1, NULL, 'F' }, { "no-fork", 0, NULL, 'N' }, { "output-pid", 0, NULL, 'P' }, @@ -1457,11 +1432,15 @@ fd_set inset, outset; bool dofork = true; bool outputpid = false; + bool no_domain_init = false; const char *pidfile = NULL; - while ((opt = getopt_long(argc, argv, "F:NPT:V", options, + while ((opt = getopt_long(argc, argv, "DF:NPT:V", options, NULL)) != -1) { switch (opt) { + case 'D': + no_domain_init = true; + break; case 'F': pidfile = optarg; break; @@ -1534,7 +1513,8 @@ setup_structure(); /* Listen to hypervisor. */ - event_fd = domain_init(); + if (!no_domain_init) + event_fd = domain_init(); /* Restore existing connections. */ restore_existing_connections(); @@ -1615,3 +1595,13 @@ max = initialize_set(&inset, &outset, *sock, *ro_sock); } } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_core.h --- a/tools/xenstore/xenstored_core.h Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_core.h Tue Oct 11 22:57:44 2005 @@ -31,14 +31,19 @@ struct buffered_data { + struct list_head list; + /* Are we still doing the header? */ bool inhdr; + /* How far are we? */ unsigned int used; + union { struct xsd_sockmsg msg; char raw[sizeof(struct xsd_sockmsg)]; } hdr; + /* The actual data. */ char *buffer; }; @@ -47,14 +52,6 @@ typedef int connwritefn_t(struct connection *, const void *, unsigned int); typedef int connreadfn_t(struct connection *, void *, unsigned int); -enum state -{ - /* Doing action, not listening */ - BUSY, - /* Completed */ - OK, -}; - struct connection { struct list_head list; @@ -62,29 +59,24 @@ /* The file descriptor we came in on. */ int fd; - /* Who am I? 0 for socket connections. */ + /* Who am I? 0 for socket connections. */ domid_t id; - - /* Blocked on transaction? Busy? */ - enum state state; /* Is this a read-only connection? */ bool can_write; - - /* Are we waiting for a watch event ack? */ - struct watch *waiting_for_ack; /* Buffered incoming data. */ struct buffered_data *in; /* Buffered output data */ - struct buffered_data *out; + struct list_head out_list; - /* If we had a watch fire outgoing when we needed to reply... */ - struct buffered_data *waiting_reply; + /* Transaction context for current request (NULL if none). */ + struct transaction *transaction; - /* My transaction, if any. */ - struct transaction *transaction; + /* List of in-progress transactions. */ + struct list_head transaction_list; + u32 next_transaction_id; /* The domain I'm associated with, if any. */ struct domain *domain; @@ -175,3 +167,13 @@ extern int event_fd; #endif /* _XENSTORED_CORE_H */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_domain.c Tue Oct 11 22:57:44 2005 @@ -52,6 +52,14 @@ /* Event channel port */ u16 port; + + /* The remote end of the event channel, used only to validate + repeated domain introductions. */ + u16 remote_port; + + /* The mfn associated with the event channel, used only to validate + repeated domain introductions. */ + unsigned long mfn; /* Domain path in store. */ char *path; @@ -276,12 +284,13 @@ bool domain_can_read(struct connection *conn) { - return conn->state == OK && buffer_has_input(conn->domain->input); + return buffer_has_input(conn->domain->input); } bool domain_can_write(struct connection *conn) { - return conn->out && buffer_has_output_room(conn->domain->output); + return (!list_empty(&conn->out_list) && + buffer_has_output_room(conn->domain->output)); } static struct domain *new_domain(void *context, domid_t domid, @@ -321,45 +330,13 @@ domain->port = rc; domain->conn = new_connection(writechn, readchn); domain->conn->domain = domain; + + domain->remote_port = port; + domain->mfn = mfn; + return domain; } -/* domid, mfn, evtchn, path */ -void do_introduce(struct connection *conn, struct buffered_data *in) -{ - struct domain *domain; - char *vec[4]; - - if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) { - send_error(conn, EINVAL); - return; - } - - if (conn->id != 0 || !conn->can_write) { - send_error(conn, EACCES); - return; - } - - /* Sanity check args. */ - if ((atoi(vec[2]) <= 0) || !is_valid_nodename(vec[3])) { - send_error(conn, EINVAL); - return; - } - /* Hang domain off "in" until we're finished. */ - domain = new_domain(in, atoi(vec[0]), atol(vec[1]), atol(vec[2]), - vec[3]); - if (!domain) { - send_error(conn, errno); - return; - } - - /* Now domain belongs to its connection. */ - talloc_steal(domain->conn, domain); - - fire_watches(conn, "@introduceDomain", false); - - send_ack(conn, XS_INTRODUCE); -} static struct domain *find_domain_by_domid(domid_t domid) { @@ -370,6 +347,67 @@ return i; } return NULL; +} + + +/* domid, mfn, evtchn, path */ +void do_introduce(struct connection *conn, struct buffered_data *in) +{ + struct domain *domain; + char *vec[4]; + domid_t domid; + unsigned long mfn; + u16 port; + const char *path; + + if (get_strings(in, vec, ARRAY_SIZE(vec)) < ARRAY_SIZE(vec)) { + send_error(conn, EINVAL); + return; + } + + if (conn->id != 0 || !conn->can_write) { + send_error(conn, EACCES); + return; + } + + domid = atoi(vec[0]); + mfn = atol(vec[1]); + port = atoi(vec[2]); + path = vec[3]; + + /* Sanity check args. */ + if ((port <= 0) || !is_valid_nodename(path)) { + send_error(conn, EINVAL); + return; + } + + domain = find_domain_by_domid(domid); + + if (domain == NULL) { + /* Hang domain off "in" until we're finished. */ + domain = new_domain(in, domid, mfn, port, path); + if (!domain) { + send_error(conn, errno); + return; + } + + /* Now domain belongs to its connection. */ + talloc_steal(domain->conn, domain); + + fire_watches(conn, "@introduceDomain", false); + } + else { + /* Check that the given details match the ones we have + previously recorded. */ + if (port != domain->remote_port || + mfn != domain->mfn || + strcmp(path, domain->path) != 0) { + send_error(conn, EINVAL); + return; + } + } + + send_ack(conn, XS_INTRODUCE); } /* domid */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_transaction.c --- a/tools/xenstore/xenstored_transaction.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_transaction.c Tue Oct 11 22:57:44 2005 @@ -37,7 +37,7 @@ struct changed_node { - /* The list within this transaction. */ + /* List of all changed nodes in the context of this transaction. */ struct list_head list; /* The name of the node. */ @@ -49,14 +49,14 @@ struct transaction { - /* Global list of transactions. */ + /* List of all transactions active on this connection. */ struct list_head list; + + /* Connection-local identifier for this transaction. */ + u32 id; /* Generation when transaction started. */ unsigned int generation; - - /* My owner (conn->transaction == me). */ - struct connection *conn; /* TDB to work on, and filename */ TDB_CONTEXT *tdb; @@ -65,7 +65,7 @@ /* List of changed nodes. */ struct list_head changes; }; -static LIST_HEAD(transactions); + static unsigned int generation; /* Return tdb context to use for this connection. */ @@ -100,7 +100,6 @@ { struct transaction *trans = _transaction; - list_del(&trans->list); trace_destroy(trans, "transaction"); if (trans->tdb) tdb_close(trans->tdb); @@ -108,10 +107,26 @@ return 0; } +struct transaction *transaction_lookup(struct connection *conn, u32 id) +{ + struct transaction *trans; + + if (id == 0) + return NULL; + + list_for_each_entry(trans, &conn->transaction_list, list) + if (trans->id == id) + return trans; + + return ERR_PTR(-ENOENT); +} + void do_transaction_start(struct connection *conn, struct buffered_data *in) { - struct transaction *trans; - + struct transaction *trans, *exists; + char id_str[20]; + + /* We don't support nested transactions. */ if (conn->transaction) { send_error(conn, EBUSY); return; @@ -120,7 +135,6 @@ /* Attach transaction to input for autofree until it's complete */ trans = talloc(in, struct transaction); INIT_LIST_HEAD(&trans->changes); - trans->conn = conn; trans->generation = generation; trans->tdb_name = talloc_asprintf(trans, "%s.%p", xs_daemon_tdb(), trans); @@ -132,11 +146,19 @@ /* Make it close if we go away. */ talloc_steal(trans, trans->tdb); + /* Pick an unused transaction identifier. */ + do { + trans->id = conn->next_transaction_id; + exists = transaction_lookup(conn, conn->next_transaction_id++); + } while (!IS_ERR(exists)); + /* Now we own it. */ - conn->transaction = talloc_steal(conn, trans); - list_add_tail(&trans->list, &transactions); + list_add_tail(&trans->list, &conn->transaction_list); + talloc_steal(conn, trans); talloc_set_destructor(trans, destroy_transaction); - send_ack(conn, XS_TRANSACTION_START); + + sprintf(id_str, "%u", trans->id); + send_reply(conn, XS_TRANSACTION_START, id_str, strlen(id_str)+1); } void do_transaction_end(struct connection *conn, const char *arg) @@ -149,14 +171,14 @@ return; } - if (!conn->transaction) { + if ((trans = conn->transaction) == NULL) { send_error(conn, ENOENT); return; } - /* Set to NULL so fire_watches sends events, tdb_context works. */ - trans = conn->transaction; conn->transaction = NULL; + list_del(&trans->list); + /* Attach transaction to arg for auto-cleanup */ talloc_steal(arg, trans); @@ -181,3 +203,12 @@ send_ack(conn, XS_TRANSACTION_END); } +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_transaction.h --- a/tools/xenstore/xenstored_transaction.h Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_transaction.h Tue Oct 11 22:57:44 2005 @@ -25,10 +25,11 @@ void do_transaction_start(struct connection *conn, struct buffered_data *node); void do_transaction_end(struct connection *conn, const char *arg); -bool transaction_block(struct connection *conn); +struct transaction *transaction_lookup(struct connection *conn, u32 id); /* This node was changed: can fail and longjmp. */ -void add_change_node(struct transaction *trans, const char *node, bool recurse); +void add_change_node(struct transaction *trans, const char *node, + bool recurse); /* Return tdb context to use for this connection. */ TDB_CONTEXT *tdb_transaction_context(struct transaction *trans); diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_watch.c --- a/tools/xenstore/xenstored_watch.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_watch.c Tue Oct 11 22:57:44 2005 @@ -32,17 +32,6 @@ #include "xenstored_test.h" #include "xenstored_domain.h" -/* FIXME: time out unacked watches. */ -struct watch_event -{ - /* The events on this watch. */ - struct list_head list; - - /* Data to send (node\0token\0). */ - unsigned int len; - char *data; -}; - struct watch { /* Watches on this connection */ @@ -58,54 +47,17 @@ char *node; }; -/* Look through our watches: if any of them have an event, queue it. */ -void queue_next_event(struct connection *conn) -{ - struct watch_event *event; - struct watch *watch; - - /* We had a reply queued already? Send it: other end will - * discard watch. */ - if (conn->waiting_reply) { - conn->out = conn->waiting_reply; - conn->waiting_reply = NULL; - conn->waiting_for_ack = NULL; - return; - } - - /* If we're already waiting for ack, don't queue more. */ - if (conn->waiting_for_ack) - return; - - list_for_each_entry(watch, &conn->watches, list) { - event = list_top(&watch->events, struct watch_event, list); - if (event) { - conn->waiting_for_ack = watch; - send_reply(conn,XS_WATCH_EVENT,event->data,event->len); - break; - } - } -} - -static int destroy_watch_event(void *_event) -{ - struct watch_event *event = _event; - - trace_destroy(event, "watch_event"); - return 0; -} - static void add_event(struct connection *conn, struct watch *watch, const char *name) { - struct watch_event *event; + /* Data to send (node\0token\0). */ + unsigned int len; + char *data; if (!check_event_node(name)) { /* Can this conn load node, or see that it doesn't exist? */ - struct node *node; - - node = get_node(conn, name, XS_PERM_READ); + struct node *node = get_node(conn, name, XS_PERM_READ); if (!node && errno != ENOENT) return; } @@ -116,14 +68,12 @@ name++; } - event = talloc(watch, struct watch_event); - event->len = strlen(name) + 1 + strlen(watch->token) + 1; - event->data = talloc_array(event, char, event->len); - strcpy(event->data, name); - strcpy(event->data + strlen(name) + 1, watch->token); - talloc_set_destructor(event, destroy_watch_event); - list_add_tail(&event->list, &watch->events); - trace_create(event, "watch_event"); + len = strlen(name) + 1 + strlen(watch->token) + 1; + data = talloc_array(watch, char, len); + strcpy(data, name); + strcpy(data + strlen(name) + 1, watch->token); + send_reply(conn, XS_WATCH_EVENT, data, len); + talloc_free(data); } /* FIXME: we fail to fire on out of memory. Should drop connections. */ @@ -143,11 +93,6 @@ add_event(i, watch, name); else if (recurse && is_child(watch->node, name)) add_event(i, watch, watch->node); - else - continue; - /* If connection not doing anything, queue this. */ - if (i->state == OK) - queue_next_event(i); } } } @@ -181,6 +126,15 @@ } } + /* Check for duplicates. */ + list_for_each_entry(watch, &conn->watches, list) { + if (streq(watch->node, vec[0]) && + streq(watch->token, vec[1])) { + send_error(conn, EEXIST); + return; + } + } + watch = talloc(conn, struct watch); watch->node = talloc_strdup(watch, vec[0]); watch->token = talloc_strdup(watch, vec[1]); @@ -200,37 +154,6 @@ add_event(conn, watch, watch->node); } -void do_watch_ack(struct connection *conn, const char *token) -{ - struct watch_event *event; - - if (!token) { - send_error(conn, EINVAL); - return; - } - - if (!conn->waiting_for_ack) { - send_error(conn, ENOENT); - return; - } - - if (!streq(conn->waiting_for_ack->token, token)) { - /* They're confused: this will cause us to send event again */ - conn->waiting_for_ack = NULL; - send_error(conn, EINVAL); - return; - } - - /* Remove event: after ack sent, core will call queue_next_event */ - event = list_top(&conn->waiting_for_ack->events, struct watch_event, - list); - list_del(&event->list); - talloc_free(event); - - conn->waiting_for_ack = NULL; - send_ack(conn, XS_WATCH_ACK); -} - void do_unwatch(struct connection *conn, struct buffered_data *in) { struct watch *watch; @@ -241,9 +164,6 @@ return; } - /* We don't need to worry if we're waiting for an ack for the - * watch we're deleting: conn->waiting_for_ack was reset by - * this command in consider_message anyway. */ node = canonicalize(conn, vec[0]); list_for_each_entry(watch, &conn->watches, list) { if (streq(watch->node, node) && streq(watch->token, vec[1])) { @@ -260,18 +180,19 @@ void dump_watches(struct connection *conn) { struct watch *watch; - struct watch_event *event; - if (conn->waiting_for_ack) - printf(" waiting_for_ack for watch on %s token %s\n", - conn->waiting_for_ack->node, - conn->waiting_for_ack->token); - - list_for_each_entry(watch, &conn->watches, list) { + list_for_each_entry(watch, &conn->watches, list) printf(" watch on %s token %s\n", watch->node, watch->token); - list_for_each_entry(event, &watch->events, list) - printf(" event: %s\n", event->data); - } } #endif + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xenstored_watch.h --- a/tools/xenstore/xenstored_watch.h Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xenstored_watch.h Tue Oct 11 22:57:44 2005 @@ -23,17 +23,9 @@ #include "xenstored_core.h" void do_watch(struct connection *conn, struct buffered_data *in); -void do_watch_ack(struct connection *conn, const char *token); void do_unwatch(struct connection *conn, struct buffered_data *in); -/* Is this a watch event message for this connection? */ -bool is_watch_event(struct connection *conn, struct buffered_data *out); - -/* Look through our watches: if any of them have an event, queue it. */ -void queue_next_event(struct connection *conn); - -/* Fire all watches: recurse means all the children are affected (ie. rm). - */ +/* Fire all watches: recurse means all the children are affected (ie. rm). */ void fire_watches(struct connection *conn, const char *name, bool recurse); void dump_watches(struct connection *conn); diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xs.c --- a/tools/xenstore/xs.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xs.c Tue Oct 11 22:57:44 2005 @@ -52,6 +52,7 @@ * signals waiters. */ pthread_t read_thr; + int read_thr_exists; /* * A list of fired watch messages, protected by a mutex. Users can @@ -75,11 +76,9 @@ /* One request at a time. */ pthread_mutex_t request_mutex; - - /* One transaction at a time. */ - pthread_mutex_t transaction_mutex; }; +static int read_message(struct xs_handle *h); static void *read_thread(void *arg); int xs_fileno(struct xs_handle *h) @@ -134,7 +133,7 @@ int fd = -1, saved_errno; if (stat(connect_to, &buf) != 0) - goto error; + return NULL; if (S_ISSOCK(buf.st_mode)) fd = get_socket(connect_to); @@ -142,11 +141,17 @@ fd = get_dev(connect_to); if (fd == -1) - goto error; + return NULL; h = malloc(sizeof(*h)); - if (h == NULL) - goto error; + if (h == NULL) { + saved_errno = errno; + close(fd); + errno = saved_errno; + return NULL; + } + + memset(h, 0, sizeof(*h)); h->fd = fd; @@ -162,21 +167,8 @@ pthread_cond_init(&h->reply_condvar, NULL); pthread_mutex_init(&h->request_mutex, NULL); - pthread_mutex_init(&h->transaction_mutex, NULL); - - if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0) - goto error; return h; - - error: - saved_errno = errno; - if (h != NULL) - free(h); - if (fd != -1) - close(fd); - errno = saved_errno; - return NULL; } struct xs_handle *xs_daemon_open(void) @@ -198,14 +190,15 @@ { struct xs_stored_msg *msg, *tmsg; - pthread_mutex_lock(&h->transaction_mutex); pthread_mutex_lock(&h->request_mutex); pthread_mutex_lock(&h->reply_mutex); pthread_mutex_lock(&h->watch_mutex); - /* XXX FIXME: May leak an unpublished message buffer. */ - pthread_cancel(h->read_thr); - pthread_join(h->read_thr, NULL); + if (h->read_thr_exists) { + /* XXX FIXME: May leak an unpublished message buffer. */ + pthread_cancel(h->read_thr); + pthread_join(h->read_thr, NULL); + } list_for_each_entry_safe(msg, tmsg, &h->reply_list, list) { free(msg->body); @@ -217,7 +210,6 @@ free(msg); } - pthread_mutex_unlock(&h->transaction_mutex); pthread_mutex_unlock(&h->request_mutex); pthread_mutex_unlock(&h->reply_mutex); pthread_mutex_unlock(&h->watch_mutex); @@ -277,6 +269,10 @@ struct xs_stored_msg *msg; char *body; + /* Read from comms channel ourselves if there is no reader thread. */ + if (!h->read_thr_exists && (read_message(h) == -1)) + return NULL; + pthread_mutex_lock(&h->reply_mutex); while (list_empty(&h->reply_list)) pthread_cond_wait(&h->reply_condvar, &h->reply_mutex); @@ -296,8 +292,10 @@ } /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */ -static void *xs_talkv(struct xs_handle *h, enum xsd_sockmsg_type type, - const struct iovec *iovec, unsigned int num_vecs, +static void *xs_talkv(struct xs_handle *h, struct xs_transaction_handle *t, + enum xsd_sockmsg_type type, + const struct iovec *iovec, + unsigned int num_vecs, unsigned int *len) { struct xsd_sockmsg msg; @@ -306,6 +304,7 @@ unsigned int i; struct sigaction ignorepipe, oldact; + msg.tx_id = (u32)(unsigned long)t; msg.type = type; msg.len = 0; for (i = 0; i < num_vecs; i++) @@ -368,14 +367,16 @@ } /* Simplified version of xs_talkv: single message. */ -static void *xs_single(struct xs_handle *h, enum xsd_sockmsg_type type, - const char *string, unsigned int *len) +static void *xs_single(struct xs_handle *h, struct xs_transaction_handle *t, + enum xsd_sockmsg_type type, + const char *string, + unsigned int *len) { struct iovec iovec; iovec.iov_base = (void *)string; iovec.iov_len = strlen(string) + 1; - return xs_talkv(h, type, &iovec, 1, len); + return xs_talkv(h, t, type, &iovec, 1, len); } static bool xs_bool(char *reply) @@ -386,12 +387,13 @@ return true; } -char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num) +char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, unsigned int *num) { char *strings, *p, **ret; unsigned int len; - strings = xs_single(h, XS_DIRECTORY, path, &len); + strings = xs_single(h, t, XS_DIRECTORY, path, &len); if (!strings) return NULL; @@ -417,16 +419,17 @@ * Returns a malloced value: call free() on it after use. * len indicates length in bytes, not including the nul. */ -void *xs_read(struct xs_handle *h, const char *path, unsigned int *len) -{ - return xs_single(h, XS_READ, path, len); +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, unsigned int *len) +{ + return xs_single(h, t, XS_READ, path, len); } /* Write the value of a single file. * Returns false on failure. */ -bool xs_write(struct xs_handle *h, const char *path, - const void *data, unsigned int len) +bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, const void *data, unsigned int len) { struct iovec iovec[2]; @@ -435,36 +438,40 @@ iovec[1].iov_base = (void *)data; iovec[1].iov_len = len; - return xs_bool(xs_talkv(h, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL)); + return xs_bool(xs_talkv(h, t, XS_WRITE, iovec, + ARRAY_SIZE(iovec), NULL)); } /* Create a new directory. * Returns false on failure, or success if it already exists. */ -bool xs_mkdir(struct xs_handle *h, const char *path) -{ - return xs_bool(xs_single(h, XS_MKDIR, path, NULL)); +bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path) +{ + return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL)); } /* Destroy a file or directory (directories must be empty). * Returns false on failure, or success if it doesn't exist. */ -bool xs_rm(struct xs_handle *h, const char *path) -{ - return xs_bool(xs_single(h, XS_RM, path, NULL)); +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path) +{ + return xs_bool(xs_single(h, t, XS_RM, path, NULL)); } /* Get permissions of node (first element is owner). * Returns malloced array, or NULL: call free() after use. */ struct xs_permissions *xs_get_permissions(struct xs_handle *h, + struct xs_transaction_handle *t, const char *path, unsigned int *num) { char *strings; unsigned int len; struct xs_permissions *ret; - strings = xs_single(h, XS_GET_PERMS, path, &len); + strings = xs_single(h, t, XS_GET_PERMS, path, &len); if (!strings) return NULL; @@ -490,7 +497,9 @@ /* Set permissions of node (must be owner). * Returns false on failure. */ -bool xs_set_permissions(struct xs_handle *h, const char *path, +bool xs_set_permissions(struct xs_handle *h, + struct xs_transaction_handle *t, + const char *path, struct xs_permissions *perms, unsigned int num_perms) { @@ -512,7 +521,7 @@ goto unwind; } - if (!xs_bool(xs_talkv(h, XS_SET_PERMS, iov, 1+num_perms, NULL))) + if (!xs_bool(xs_talkv(h, t, XS_SET_PERMS, iov, 1+num_perms, NULL))) goto unwind; for (i = 0; i < num_perms; i++) free(iov[i+1].iov_base); @@ -534,12 +543,24 @@ { struct iovec iov[2]; + /* We dynamically create a reader thread on demand. */ + pthread_mutex_lock(&h->request_mutex); + if (!h->read_thr_exists) { + if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0) { + pthread_mutex_unlock(&h->request_mutex); + return false; + } + h->read_thr_exists = 1; + } + pthread_mutex_unlock(&h->request_mutex); + iov[0].iov_base = (void *)path; iov[0].iov_len = strlen(path) + 1; iov[1].iov_base = (void *)token; iov[1].iov_len = strlen(token) + 1; - return xs_bool(xs_talkv(h, XS_WATCH, iov, ARRAY_SIZE(iov), NULL)); + return xs_bool(xs_talkv(h, NULL, XS_WATCH, iov, + ARRAY_SIZE(iov), NULL)); } /* Find out what node change was on (will block if nothing pending). @@ -593,15 +614,6 @@ return ret; } -/* Acknowledge watch on node. Watches must be acknowledged before - * any other watches can be read. - * Returns false on failure. - */ -bool xs_acknowledge_watch(struct xs_handle *h, const char *token) -{ - return xs_bool(xs_single(h, XS_WATCH_ACK, token, NULL)); -} - /* Remove a watch on a node. * Returns false on failure (no watch on that node). */ @@ -614,18 +626,28 @@ iov[1].iov_base = (char *)token; iov[1].iov_len = strlen(token) + 1; - return xs_bool(xs_talkv(h, XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL)); + return xs_bool(xs_talkv(h, NULL, XS_UNWATCH, iov, + ARRAY_SIZE(iov), NULL)); } /* Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. * You can only have one transaction at any time. - * Returns false on failure. - */ -bool xs_transaction_start(struct xs_handle *h) -{ - pthread_mutex_lock(&h->transaction_mutex); - return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL)); + * Returns NULL on failure. + */ +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h) +{ + char *id_str; + unsigned long id; + + id_str = xs_single(h, NULL, XS_TRANSACTION_START, "", NULL); + if (id_str == NULL) + return NULL; + + id = strtoul(id_str, NULL, 0); + free(id_str); + + return (struct xs_transaction_handle *)id; } /* End a transaction. @@ -633,21 +655,17 @@ * Returns false on failure, which indicates an error: transactions will * not fail spuriously. */ -bool xs_transaction_end(struct xs_handle *h, bool abort) +bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t, + bool abort) { char abortstr[2]; - bool rc; if (abort) strcpy(abortstr, "F"); else strcpy(abortstr, "T"); - rc = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL)); - - pthread_mutex_unlock(&h->transaction_mutex); - - return rc; + return xs_bool(xs_single(h, t, XS_TRANSACTION_END, abortstr, NULL)); } /* Introduce a new domain. @@ -675,7 +693,8 @@ iov[3].iov_base = (char *)path; iov[3].iov_len = strlen(path) + 1; - return xs_bool(xs_talkv(h, XS_INTRODUCE, iov, ARRAY_SIZE(iov), NULL)); + return xs_bool(xs_talkv(h, NULL, XS_INTRODUCE, iov, + ARRAY_SIZE(iov), NULL)); } bool xs_release_domain(struct xs_handle *h, domid_t domid) @@ -684,7 +703,7 @@ sprintf(domid_str, "%u", domid); - return xs_bool(xs_single(h, XS_RELEASE, domid_str, NULL)); + return xs_bool(xs_single(h, NULL, XS_RELEASE, domid_str, NULL)); } char *xs_get_domain_path(struct xs_handle *h, domid_t domid) @@ -693,7 +712,7 @@ sprintf(domid_str, "%u", domid); - return xs_single(h, XS_GET_DOMAIN_PATH, domid_str, NULL); + return xs_single(h, NULL, XS_GET_DOMAIN_PATH, domid_str, NULL); } /* Only useful for DEBUG versions */ @@ -707,68 +726,76 @@ iov[1].iov_base = data; iov[1].iov_len = len; - return xs_talkv(h, XS_DEBUG, iov, ARRAY_SIZE(iov), NULL); -} - -static void *read_thread(void *arg) -{ - struct xs_handle *h = arg; + return xs_talkv(h, NULL, XS_DEBUG, iov, + ARRAY_SIZE(iov), NULL); +} + +static int read_message(struct xs_handle *h) +{ struct xs_stored_msg *msg = NULL; char *body = NULL; - - for (;;) { - msg = NULL; - body = NULL; - - /* Allocate message structure and read the message header. */ - msg = malloc(sizeof(*msg)); - if (msg == NULL) + int saved_errno; + + /* Allocate message structure and read the message header. */ + msg = malloc(sizeof(*msg)); + if (msg == NULL) + goto error; + if (!read_all(h->fd, &msg->hdr, sizeof(msg->hdr))) + goto error; + + /* Allocate and read the message body. */ + body = msg->body = malloc(msg->hdr.len + 1); + if (body == NULL) + goto error; + if (!read_all(h->fd, body, msg->hdr.len)) + goto error; + body[msg->hdr.len] = '\0'; + + if (msg->hdr.type == XS_WATCH_EVENT) { + pthread_mutex_lock(&h->watch_mutex); + + /* Kick users out of their select() loop. */ + if (list_empty(&h->watch_list) && + (h->watch_pipe[1] != -1)) + while (write(h->watch_pipe[1], body, 1) != 1) + continue; + + list_add_tail(&msg->list, &h->watch_list); + pthread_cond_signal(&h->watch_condvar); + + pthread_mutex_unlock(&h->watch_mutex); + } else { + pthread_mutex_lock(&h->reply_mutex); + + /* There should only ever be one response pending! */ + if (!list_empty(&h->reply_list)) { + pthread_mutex_unlock(&h->reply_mutex); goto error; - if (!read_all(h->fd, &msg->hdr, sizeof(msg->hdr))) - goto error; - - /* Allocate and read the message body. */ - body = msg->body = malloc(msg->hdr.len + 1); - if (body == NULL) - goto error; - if (!read_all(h->fd, body, msg->hdr.len)) - goto error; - body[msg->hdr.len] = '\0'; - - if (msg->hdr.type == XS_WATCH_EVENT) { - pthread_mutex_lock(&h->watch_mutex); - - /* Kick users out of their select() loop. */ - if (list_empty(&h->watch_list) && - (h->watch_pipe[1] != -1)) - while (write(h->watch_pipe[1], body, 1) != 1) - continue; - - list_add_tail(&msg->list, &h->watch_list); - pthread_cond_signal(&h->watch_condvar); - - pthread_mutex_unlock(&h->watch_mutex); - } else { - pthread_mutex_lock(&h->reply_mutex); - - /* There should only ever be one response pending! */ - if (!list_empty(&h->reply_list)) { - pthread_mutex_unlock(&h->reply_mutex); - goto error; - } - - list_add_tail(&msg->list, &h->reply_list); - pthread_cond_signal(&h->reply_condvar); - - pthread_mutex_unlock(&h->reply_mutex); } - } + + list_add_tail(&msg->list, &h->reply_list); + pthread_cond_signal(&h->reply_condvar); + + pthread_mutex_unlock(&h->reply_mutex); + } + + return 0; error: - if (body != NULL) - free(body); - if (msg != NULL) - free(msg); + saved_errno = errno; + free(msg); + free(body); + errno = saved_errno; + return -1; +} + +static void *read_thread(void *arg) +{ + struct xs_handle *h = arg; + + while (read_message(h) != -1) + continue; + return NULL; } diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xs.h --- a/tools/xenstore/xs.h Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xs.h Tue Oct 11 22:57:44 2005 @@ -23,6 +23,7 @@ #include <xs_lib.h> struct xs_handle; +struct xs_transaction_handle; /* On failure, these routines set errno. */ @@ -44,41 +45,47 @@ * Returns a malloced array: call free() on it after use. * Num indicates size. */ -char **xs_directory(struct xs_handle *h, const char *path, unsigned int *num); +char **xs_directory(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, unsigned int *num); /* Get the value of a single file, nul terminated. * Returns a malloced value: call free() on it after use. * len indicates length in bytes, not including terminator. */ -void *xs_read(struct xs_handle *h, const char *path, unsigned int *len); +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, unsigned int *len); /* Write the value of a single file. * Returns false on failure. */ -bool xs_write(struct xs_handle *h, const char *path, const void *data, - unsigned int len); +bool xs_write(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, const void *data, unsigned int len); /* Create a new directory. * Returns false on failure, or success if it already exists. */ -bool xs_mkdir(struct xs_handle *h, const char *path); +bool xs_mkdir(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path); /* Destroy a file or directory (and children). * Returns false on failure, or success if it doesn't exist. */ -bool xs_rm(struct xs_handle *h, const char *path); +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path); /* Get permissions of node (first element is owner, first perms is "other"). * Returns malloced array, or NULL: call free() after use. */ struct xs_permissions *xs_get_permissions(struct xs_handle *h, + struct xs_transaction_handle *t, const char *path, unsigned int *num); /* Set permissions of node (must be owner). * Returns false on failure. */ -bool xs_set_permissions(struct xs_handle *h, const char *path, - struct xs_permissions *perms, unsigned int num_perms); +bool xs_set_permissions(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, struct xs_permissions *perms, + unsigned int num_perms); /* Watch a node for changes (poll on fd to detect, or call read_watch()). * When the node (or any child) changes, fd will become readable. @@ -96,12 +103,6 @@ */ char **xs_read_watch(struct xs_handle *h, unsigned int *num); -/* Acknowledge watch on node. Watches must be acknowledged before - * any other watches can be read. - * Returns false on failure. - */ -bool xs_acknowledge_watch(struct xs_handle *h, const char *token); - /* Remove a watch on a node: implicitly acks any outstanding watch. * Returns false on failure (no watch on that node). */ @@ -110,16 +111,17 @@ /* Start a transaction: changes by others will not be seen during this * transaction, and changes will not be visible to others until end. * You can only have one transaction at any time. - * Returns false on failure. + * Returns NULL on failure. */ -bool xs_transaction_start(struct xs_handle *h); +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h); /* End a transaction. * If abandon is true, transaction is discarded instead of committed. * Returns false on failure: if errno == EAGAIN, you have to restart * transaction. */ -bool xs_transaction_end(struct xs_handle *h, bool abort); +bool xs_transaction_end(struct xs_handle *h, struct xs_transaction_handle *t, + bool abort); /* Introduce a new domain. * This tells the store daemon about a shared memory page, event channel @@ -142,3 +144,13 @@ void *data, unsigned int len); #endif /* _XS_H */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xs_test.c --- a/tools/xenstore/xs_test.c Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xs_test.c Tue Oct 11 22:57:44 2005 @@ -42,6 +42,7 @@ #define XSTEST static struct xs_handle *handles[10] = { NULL }; +static struct xs_transaction_handle *txh[10] = { NULL }; static unsigned int timeout_ms = 500; static bool timeout_suppressed = true; @@ -201,7 +202,6 @@ " watch <path> <token>\n" " watchnoack <path> <token>\n" " waitwatch\n" - " ackwatch <token>\n" " unwatch <path> <token>\n" " close\n" " start <node>\n" @@ -313,7 +313,7 @@ char **entries; unsigned int i, num; - entries = xs_directory(handles[handle], path, &num); + entries = xs_directory(handles[handle], txh[handle], path, &num); if (!entries) { failed(handle); return; @@ -332,7 +332,7 @@ char *value; unsigned int len; - value = xs_read(handles[handle], path, &len); + value = xs_read(handles[handle], txh[handle], path, &len); if (!value) { failed(handle); return; @@ -348,7 +348,7 @@ static void do_write(unsigned int handle, char *path, char *data) { - if (!xs_write(handles[handle], path, data, strlen(data))) + if (!xs_write(handles[handle], txh[handle], path, data, strlen(data))) failed(handle); } @@ -361,13 +361,13 @@ static void do_mkdir(unsigned int handle, char *path) { - if (!xs_mkdir(handles[handle], path)) + if (!xs_mkdir(handles[handle], txh[handle], path)) failed(handle); } static void do_rm(unsigned int handle, char *path) { - if (!xs_rm(handles[handle], path)) + if (!xs_rm(handles[handle], txh[handle], path)) failed(handle); } @@ -376,7 +376,7 @@ unsigned int i, num; struct xs_permissions *perms; - perms = xs_get_permissions(handles[handle], path, &num); + perms = xs_get_permissions(handles[handle], txh[handle], path, &num); if (!perms) { failed(handle); return; @@ -437,7 +437,7 @@ barf("bad flags %s\n", arg); } - if (!xs_set_permissions(handles[handle], path, perms, i)) + if (!xs_set_permissions(handles[handle], txh[handle], path, perms, i)) failed(handle); } @@ -454,8 +454,6 @@ if (!vec || !streq(vec[XS_WATCH_PATH], node) || !streq(vec[XS_WATCH_TOKEN], token)) - failed(handle); - if (!xs_acknowledge_watch(handles[handle], token)) failed(handle); } } @@ -515,12 +513,6 @@ free(vec); } -static void do_ackwatch(unsigned int handle, const char *token) -{ - if (!xs_acknowledge_watch(handles[handle], token)) - failed(handle); -} - static void do_unwatch(unsigned int handle, const char *node, const char *token) { if (!xs_unwatch(handles[handle], node, token)) @@ -529,14 +521,16 @@ static void do_start(unsigned int handle) { - if (!xs_transaction_start(handles[handle])) + txh[handle] = xs_transaction_start(handles[handle]); + if (txh[handle] == NULL) failed(handle); } static void do_end(unsigned int handle, bool abort) { - if (!xs_transaction_end(handles[handle], abort)) - failed(handle); + if (!xs_transaction_end(handles[handle], txh[handle], abort)) + failed(handle); + txh[handle] = NULL; } static void do_introduce(unsigned int handle, @@ -626,7 +620,8 @@ sprintf(subnode, "%s/%s", node, dir[i]); - perms = xs_get_permissions(handles[handle], subnode,&numperms); + perms = xs_get_permissions(handles[handle], txh[handle], + subnode,&numperms); if (!perms) { failed(handle); return; @@ -643,7 +638,8 @@ output("\n"); /* Even directories can have contents. */ - contents = xs_read(handles[handle], subnode, &len); + contents = xs_read(handles[handle], txh[handle], + subnode, &len); if (!contents) { if (errno != EISDIR) failed(handle); @@ -653,7 +649,8 @@ } /* Every node is a directory. */ - subdirs = xs_directory(handles[handle], subnode, &subnum); + subdirs = xs_directory(handles[handle], txh[handle], + subnode, &subnum); if (!subdirs) { failed(handle); return; @@ -668,7 +665,7 @@ char **subdirs; unsigned int subnum; - subdirs = xs_directory(handles[handle], "/", &subnum); + subdirs = xs_directory(handles[handle], txh[handle], "/", &subnum); if (!subdirs) { failed(handle); return; @@ -746,13 +743,12 @@ do_watch(handle, arg(line, 1), arg(line, 2), false); else if (streq(command, "waitwatch")) do_waitwatch(handle); - else if (streq(command, "ackwatch")) - do_ackwatch(handle, arg(line, 1)); else if (streq(command, "unwatch")) do_unwatch(handle, arg(line, 1), arg(line, 2)); else if (streq(command, "close")) { xs_daemon_close(handles[handle]); handles[handle] = NULL; + txh[handle] = NULL; } else if (streq(command, "start")) do_start(handle); else if (streq(command, "commit")) @@ -836,3 +832,13 @@ return 0; } + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -r 333f722ed6d0 -r 74d56b7ff46c xen/Makefile --- a/xen/Makefile Tue Oct 11 21:50:21 2005 +++ b/xen/Makefile Tue Oct 11 22:57:44 2005 @@ -95,7 +95,7 @@ -e 's/@@version@@/$(XEN_VERSION)/g' \ -e 's/@@subversion@@/$(XEN_SUBVERSION)/g' \ -e 's/@@extraversion@@/$(XEN_EXTRAVERSION)/g' \ - -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' \ + -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' \ < include/xen/compile.h.in > $@.new @cat include/xen/banner.h >> $@.new @mv -f $@.new $@ diff -r 333f722ed6d0 -r 74d56b7ff46c xen/include/public/io/xs_wire.h --- a/xen/include/public/io/xs_wire.h Tue Oct 11 21:50:21 2005 +++ b/xen/include/public/io/xs_wire.h Tue Oct 11 22:57:44 2005 @@ -30,25 +30,23 @@ enum xsd_sockmsg_type { - XS_DEBUG, - XS_DIRECTORY, - XS_READ, - XS_GET_PERMS, - XS_WATCH, - XS_WATCH_ACK, - XS_UNWATCH, - XS_TRANSACTION_START, - XS_TRANSACTION_END, - XS_OP_READ_ONLY = XS_TRANSACTION_END, - XS_INTRODUCE, - XS_RELEASE, - XS_GET_DOMAIN_PATH, - XS_WRITE, - XS_MKDIR, - XS_RM, - XS_SET_PERMS, - XS_WATCH_EVENT, - XS_ERROR, + XS_DEBUG, + XS_DIRECTORY, + XS_READ, + XS_GET_PERMS, + XS_WATCH, + XS_UNWATCH, + XS_TRANSACTION_START, + XS_TRANSACTION_END, + XS_INTRODUCE, + XS_RELEASE, + XS_GET_DOMAIN_PATH, + XS_WRITE, + XS_MKDIR, + XS_RM, + XS_SET_PERMS, + XS_WATCH_EVENT, + XS_ERROR, }; #define XS_WRITE_NONE "NONE" @@ -58,38 +56,40 @@ /* We hand errors as strings, for portability. */ struct xsd_errors { - int errnum; - const char *errstring; + int errnum; + const char *errstring; }; #define XSD_ERROR(x) { x, #x } static struct xsd_errors xsd_errors[] __attribute__((unused)) = { - XSD_ERROR(EINVAL), - XSD_ERROR(EACCES), - XSD_ERROR(EEXIST), - XSD_ERROR(EISDIR), - XSD_ERROR(ENOENT), - XSD_ERROR(ENOMEM), - XSD_ERROR(ENOSPC), - XSD_ERROR(EIO), - XSD_ERROR(ENOTEMPTY), - XSD_ERROR(ENOSYS), - XSD_ERROR(EROFS), - XSD_ERROR(EBUSY), - XSD_ERROR(EAGAIN), - XSD_ERROR(EISCONN), + XSD_ERROR(EINVAL), + XSD_ERROR(EACCES), + XSD_ERROR(EEXIST), + XSD_ERROR(EISDIR), + XSD_ERROR(ENOENT), + XSD_ERROR(ENOMEM), + XSD_ERROR(ENOSPC), + XSD_ERROR(EIO), + XSD_ERROR(ENOTEMPTY), + XSD_ERROR(ENOSYS), + XSD_ERROR(EROFS), + XSD_ERROR(EBUSY), + XSD_ERROR(EAGAIN), + XSD_ERROR(EISCONN), }; struct xsd_sockmsg { - u32 type; - u32 len; /* Length of data following this. */ + u32 type; /* XS_??? */ + u32 req_id;/* Request identifier, echoed in daemon's response. */ + u32 tx_id; /* Transaction id (0 if not related to a transaction). */ + u32 len; /* Length of data following this. */ - /* Generally followed by nul-terminated string(s). */ + /* Generally followed by nul-terminated string(s). */ }; enum xs_watch_type { - XS_WATCH_PATH = 0, - XS_WATCH_TOKEN, + XS_WATCH_PATH = 0, + XS_WATCH_TOKEN, }; #endif /* _XS_WIRE_H */ diff -r 333f722ed6d0 -r 74d56b7ff46c tools/examples/xen-hotplug-common.sh --- /dev/null Tue Oct 11 21:50:21 2005 +++ b/tools/examples/xen-hotplug-common.sh Tue Oct 11 22:57:44 2005 @@ -0,0 +1,26 @@ +set -e + +export PATH=/sbin:/bin:/usr/bin:/usr/sbin:$PATH + +log() { + local level="$1" + shift + logger -p "daemon.$level" -- "$0:" "$@" || echo "$0 $@" >&2 +} + +xenstore_read() { + local v=$(xenstore-read "$@" || true) + if [ "$v" == "" ] + then + log error "xenstore-read $@ failed." + exit 1 + fi + echo "$v" +} + +xenstore_write() { + log debug "Writing $@ to xenstore." + xenstore-write "$@" || log error "Writing $@ to xenstore failed." +} + +log debug "$@" "XENBUS_PATH=$XENBUS_PATH" diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/util/asserts.py --- /dev/null Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/util/asserts.py Tue Oct 11 22:57:44 2005 @@ -0,0 +1,27 @@ +#=========================================================================== +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2005 XenSource Ltd +#============================================================================ + + +def isCharConvertible(c): + """Assert that the given value is convertible to a character using the %c + conversion. This implies that c is either an integer, or a character + (i.e. a string of length 1). + """ + + assert (isinstance(c, int) or + (isinstance(c, str) and + len(c) == 1)), "%s is not convertible to a character" % c diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/util/auxbin.py --- /dev/null Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/util/auxbin.py Tue Oct 11 22:57:44 2005 @@ -0,0 +1,44 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2005 XenSource Ltd +#============================================================================ + + +LIB_BIN_32 = "/usr/lib/xen/bin" +LIB_BIN_64 = "/usr/lib64/xen/bin" + + +import os +import os.path + + +def execute(exe, args = None): + exepath = pathTo(exe) + a = [ exepath ] + if args: + a.extend(args) + os.execv(exepath, a) + + +def pathTo(exe): + return os.path.join(path(), exe) + + +def path(): + machine = os.uname()[4] + if machine.find('64') != -1 and os.path.exists(LIB_BIN_64): + return LIB_BIN_64 + else: + return LIB_BIN_32 diff -r 333f722ed6d0 -r 74d56b7ff46c tools/python/xen/xm/console.py --- /dev/null Tue Oct 11 21:50:21 2005 +++ b/tools/python/xen/xm/console.py Tue Oct 11 22:57:44 2005 @@ -0,0 +1,26 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2005 XenSource Ltd +#============================================================================ + + +XENCONSOLE = "xenconsole" + + +import xen.util.auxbin + + +def execConsole(domid): + xen.util.auxbin.execute(XENCONSOLE, [str(domid)]) diff -r 333f722ed6d0 -r 74d56b7ff46c tools/xenstore/xsls.c --- /dev/null Tue Oct 11 21:50:21 2005 +++ b/tools/xenstore/xsls.c Tue Oct 11 22:57:44 2005 @@ -0,0 +1,47 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <err.h> +#include <xs.h> + +void print_dir(struct xs_handle *h, char *path, int cur_depth) +{ + char **e; + char newpath[512], *val; + int num, i, len; + + e = xs_directory(h, NULL, path, &num); + if (e == NULL) + err(1, "xs_directory (%s)", path); + + for (i = 0; i<num; i++) { + int j; + for (j=0; j<cur_depth; j++) printf(" "); + printf("%s", e[i]); + sprintf(newpath, "%s%s%s", path, + path[strlen(path)-1] == '/' ? "" : "/", + e[i]); + val = xs_read(h, NULL, newpath, &len); + if (val == NULL) + printf(":\n"); + else if ((unsigned)len > (151 - strlen(e[i]))) + printf(" = \"%.*s...\"\n", 148 - strlen(e[i]), val); + else + printf(" = \"%s\"\n", val); + free(val); + print_dir(h, newpath, cur_depth+1); + } + free(e); +} + +int main(int argc, char *argv[]) +{ + struct xs_handle *xsh = xs_daemon_open(); + + if (xsh == NULL) + err(1, "xs_daemon_open"); + + print_dir(xsh, argc == 1 ? "/" : argv[1], 0); + + return 0; +} diff -r 333f722ed6d0 -r 74d56b7ff46c xen/include/public/io/console.h --- /dev/null Tue Oct 11 21:50:21 2005 +++ b/xen/include/public/io/console.h Tue Oct 11 22:57:44 2005 @@ -0,0 +1,23 @@ +/****************************************************************************** + * console.h + * + * Console I/O interface for Xen guest OSes. + * + * Copyright (c) 2005, Keir Fraser + */ + +#ifndef __XEN_PUBLIC_IO_CONSOLE_H__ +#define __XEN_PUBLIC_IO_CONSOLE_H__ + +typedef u32 XENCONS_RING_IDX; + +#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1)) + +struct xencons_interface { + char in[1024]; + char out[2048]; + XENCONS_RING_IDX in_cons, in_prod; + XENCONS_RING_IDX out_cons, out_prod; +}; + +#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |