[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Merged.
# HG changeset patch # User emellor@ewan # Node ID 1ac39c7a043541cfa94655f0e9ab98d4503c29a2 # Parent 0e7c48861e95b738fdf96d4a4df6b0ba90a8423d # Parent b7dce4fe2488bf354e5718a84fdb82bed3919761 Merged. diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/arch/xen/kernel/reboot.c --- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c Mon Oct 10 13:46:53 2005 @@ -275,22 +275,23 @@ { 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; @@ -320,23 +321,24 @@ 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; @@ -360,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) @@ -371,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 diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c --- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c --- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Mon Oct 10 13:46:53 2005 @@ -130,15 +130,10 @@ 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... */ + 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 > len) @@ -173,12 +168,11 @@ const char *src; wait_event(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 > len) @@ -195,10 +189,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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Mon Oct 10 13:46:53 2005 @@ -46,85 +46,113 @@ #include <asm/hypervisor.h> 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. */ + int in_transaction; + + /* 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); + 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++; } - /* 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. */ + 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; + 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; + + 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) + u->in_transaction = 1; + if (u->u.msg.type == XS_TRANSACTION_END) + u->in_transaction = 0; + 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; } - return len; + + if (err == 0) { + u->len = 0; + err = len; + } + + return err; } static int xenbus_dev_open(struct inode *inode, struct file *filp) @@ -134,7 +162,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 +169,21 @@ return -ENOMEM; memset(u, 0, sizeof(*u)); + 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; + + if (u->in_transaction) + xenbus_transaction_end((struct xenbus_transaction *)1, 1); + + kfree(u); return 0; } diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Mon Oct 10 13:46:53 2005 @@ -43,6 +43,9 @@ static struct notifier_block *xenstore_chain; +/* Now used to protect xenbus probes against save/restore. */ +static DECLARE_MUTEX(xenbus_lock); + /* If something in array of ids matches this device, return it. */ static const struct xenbus_device_id * match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) @@ -125,7 +128,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 +136,7 @@ if (strlen(frontend) == 0) err = -ERANGE; - if (!err && !xenbus_exists(frontend, "")) + if (!err && !xenbus_exists(NULL, frontend, "")) err = -ENOENT; if (err) { @@ -447,7 +450,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 +473,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 +492,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 +538,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; @@ -625,12 +628,13 @@ 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); @@ -662,12 +666,16 @@ } 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:" @@ -685,6 +693,7 @@ /* Notify others that xenstore is up */ notifier_call_chain(&xenstore_chain, 0, 0); up(&xenbus_lock); + return 0; } @@ -698,6 +707,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 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Mon Oct 10 13:46:53 2005 @@ -42,11 +42,67 @@ #define streq(a, b) (strcmp((a), (b)) == 0) -static char printf_buffer[4096]; +struct xs_stored_msg { + struct xsd_sockmsg hdr; + + union { + /* Stored replies. */ + struct { + struct list_head list; + char *body; + } reply; + + /* Queued watch callbacks. */ + struct { + struct work_struct work; + 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; + + /* One transaction at a time. */ + struct semaphore transaction_mutex; + int transaction_pid; +}; + +static struct xs_handle xs_state; + static LIST_HEAD(watches); - -DECLARE_MUTEX(xenbus_lock); -EXPORT_SYMBOL(xenbus_lock); +static DEFINE_SPINLOCK(watches_lock); + +/* Can wait on !xs_resuming for suspend/resume cycle to complete. */ +static int xs_resuming; +static DECLARE_WAIT_QUEUE_HEAD(xs_resuming_waitq); + +static void request_mutex_acquire(void) +{ + /* + * We can't distinguish non-transactional from transactional + * requests right now. So temporarily acquire the transaction mutex + * if this task is outside transaction context. + */ + if (xs_state.transaction_pid != current->pid) + down(&xs_state.transaction_mutex); + down(&xs_state.request_mutex); +} + +static void request_mutex_release(void) +{ + up(&xs_state.request_mutex); + if (xs_state.transaction_pid != current->pid) + up(&xs_state.transaction_mutex); +} static int get_error(const char *errorstring) { @@ -65,29 +121,32 @@ 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(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, u.reply.list); + list_del(&msg->u.reply.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. */ @@ -98,10 +157,45 @@ msg.type = XS_DEBUG; msg.len = sizeof("print") + count + 1; + request_mutex_acquire(); xb_write(&msg, sizeof(msg)); xb_write("print", sizeof("print")); xb_write(str, count); xb_write("", 1); + request_mutex_release(); +} + +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(&xs_state.transaction_mutex); + xs_state.transaction_pid = current->pid; + } + + request_mutex_acquire(); + + 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); + } + + request_mutex_release(); + + if ((msg->type == XS_TRANSACTION_END) || + ((req_msg.type == XS_TRANSACTION_START) && + (msg->type == XS_ERROR))) { + xs_state.transaction_pid = -1; + up(&xs_state.transaction_mutex); + } + + return ret; } /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */ @@ -115,31 +209,33 @@ unsigned int i; int err; - WARN_ON(down_trylock(&xenbus_lock) == 0); - msg.type = type; msg.len = 0; for (i = 0; i < num_vecs; i++) msg.len += iovec[i].iov_len; + request_mutex_acquire(); + 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) { + request_mutex_release(); 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); + + request_mutex_release(); + + if (IS_ERR(ret)) + return ret; if (msg.type == XS_ERROR) { err = get_error(ret); @@ -187,8 +283,6 @@ { 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)); strcpy(buffer, dir); @@ -207,7 +301,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,7 +316,8 @@ return ret; } -char **xenbus_directory(const char *dir, const char *node, unsigned int *num) +char **xenbus_directory(struct xenbus_transaction *t, + const char *dir, const char *node, unsigned int *num) { char *strings; unsigned int len; @@ -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,7 +349,8 @@ * 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) +void *xenbus_read(struct xenbus_transaction *t, + const char *dir, const char *node, unsigned int *len) { return xs_single(XS_READ, join(dir, node), len); } @@ -262,7 +359,8 @@ /* 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]; @@ -279,14 +377,15 @@ EXPORT_SYMBOL(xenbus_write); /* Create a new directory. */ -int xenbus_mkdir(const char *dir, const char *node) +int xenbus_mkdir(struct xenbus_transaction *t, + const char *dir, const char *node) { return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL)); } EXPORT_SYMBOL(xenbus_mkdir); /* Destroy a file or directory (directories must be empty). */ -int xenbus_rm(const char *dir, const char *node) +int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node) { return xs_error(xs_single(XS_RM, join(dir, node), NULL)); } @@ -294,37 +393,57 @@ /* 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) +{ + int err; + + down(&xs_state.transaction_mutex); + xs_state.transaction_pid = current->pid; + + err = xs_error(xs_single(XS_TRANSACTION_START, "", NULL)); + if (err) { + xs_state.transaction_pid = -1; + up(&xs_state.transaction_mutex); + } + + return err ? ERR_PTR(err) : (struct xenbus_transaction *)1; } 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; + + BUG_ON(t == NULL); if (abort) strcpy(abortstr, "F"); else strcpy(abortstr, "T"); - return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL)); + + err = xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL)); + + xs_state.transaction_pid = -1; + up(&xs_state.transaction_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 +459,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 +490,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 +519,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 +529,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 +541,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; @@ -432,26 +570,6 @@ 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)); -} - static int xs_unwatch(const char *path, const char *token) { struct kvec iov[2]; @@ -464,7 +582,6 @@ return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL)); } -/* A little paranoia: we don't just trust token. */ static struct xenbus_watch *find_watch(const char *token) { struct xenbus_watch *i, *cmp; @@ -474,6 +591,7 @@ list_for_each_entry(i, &watches, list) if (i == cmp) return i; + return NULL; } @@ -485,11 +603,20 @@ int err; sprintf(token, "%lX", (long)watch); + + 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); + } + return err; } EXPORT_SYMBOL(register_xenbus_watch); @@ -500,77 +627,192 @@ int err; sprintf(token, "%lX", (long)watch); + + spin_lock(&watches_lock); BUG_ON(!find_watch(token)); + list_del(&watch->list); + spin_unlock(&watches_lock); + + /* Ensure xs_resume() is not in progress (see comments there). */ + wait_event(xs_resuming_waitq, !xs_resuming); 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); + + /* Make sure watch is not in use. */ + flush_scheduled_work(); } EXPORT_SYMBOL(unregister_xenbus_watch); -/* Re-register callbacks to all watches. */ -void reregister_xenbus_watches(void) -{ +void xs_suspend(void) +{ + down(&xs_state.transaction_mutex); + down(&xs_state.request_mutex); +} + +void xs_resume(void) +{ + struct list_head *ent, *prev_ent = &watches; struct xenbus_watch *watch; char token[sizeof(watch) * 2 + 1]; - list_for_each_entry(watch, &watches, list) { - sprintf(token, "%lX", (long)watch); - xs_watch(watch->node, token); - } -} - -static int watch_thread(void *unused) -{ + /* Protect against concurrent unregistration and freeing of watches. */ + BUG_ON(xs_resuming); + xs_resuming = 1; + + up(&xs_state.request_mutex); + up(&xs_state.transaction_mutex); + + /* + * Iterate over the watch list re-registering each node. We must + * be careful about concurrent registrations and unregistrations. + * We search for the node immediately following the previously + * re-registered node. If we get no match then either we are done + * (previous node is last in list) or the node was unregistered, in + * which case we restart from the beginning of the list. + * register_xenbus_watch() + unregister_xenbus_watch() is safe because + * it will only ever move a watch node earlier in the list, so it + * cannot cause us to skip nodes. + */ 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); - } -} - + spin_lock(&watches_lock); + list_for_each(ent, &watches) + if (ent->prev == prev_ent) + break; + spin_unlock(&watches_lock); + + /* No match because prev_ent is at the end of the list? */ + if ((ent == &watches) && (watches.prev == prev_ent)) + break; /* We're done! */ + + if ((prev_ent = ent) != &watches) { + /* + * Safe even with watch_lock not held. We are saved by + * (xs_resumed==1) check in unregister_xenbus_watch. + */ + watch = list_entry(ent, struct xenbus_watch, list); + sprintf(token, "%lX", (long)watch); + xs_watch(watch->node, token); + } + } + + xs_resuming = 0; + wake_up(&xs_resuming_waitq); +} + +static void xenbus_fire_watch(void *arg) +{ + struct xs_stored_msg *msg = arg; + + 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); +} + +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) { + INIT_WORK(&msg->u.watch.work, xenbus_fire_watch, msg); + + 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) { + schedule_work(&msg->u.watch.work); + } 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->u.reply.list, &xs_state.reply_list); + spin_unlock(&xs_state.reply_lock); + wake_up(&xs_state.reply_waitq); + } + + return 0; +} + +static int read_thread(void *unused) +{ + int err; + + for (;;) { + err = process_msg(); + if (err) + printk(KERN_WARNING "XENBUS error %d while reading " + "message\n", err); + } +} + +/* +** Initialize the interface to xenstore. +*/ int xs_init(void) { int err; - struct task_struct *watcher; - + struct task_struct *reader; + + 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_MUTEX(&xs_state.transaction_mutex); + xs_state.transaction_pid = -1; + + /* 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); + reader = kthread_run(read_thread, NULL, "xenbusd"); + if (IS_ERR(reader)) + return PTR_ERR(reader); + return 0; } diff -r 0e7c48861e95 -r 1ac39c7a0435 linux-2.6-xen-sparse/include/asm-xen/xenbus.h --- a/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Mon Oct 10 13:42:38 2005 +++ b/linux-2.6-xen-sparse/include/asm-xen/xenbus.h Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/blktap/xenbus.c --- a/tools/blktap/xenbus.c Mon Oct 10 13:42:38 2005 +++ b/tools/blktap/xenbus.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/console/client/main.c --- a/tools/console/client/main.c Mon Oct 10 13:42:38 2005 +++ b/tools/console/client/main.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/console/daemon/io.c --- a/tools/console/daemon/io.c Mon Oct 10 13:42:38 2005 +++ b/tools/console/daemon/io.c Mon Oct 10 13:46:53 2005 @@ -179,7 +179,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 +187,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 +216,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; @@ -505,7 +505,6 @@ domain_create_ring(dom); } - xs_acknowledge_watch(xs, vec[1]); free(vec); } diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/python/xen/lowlevel/xs/xs.c --- a/tools/python/xen/lowlevel/xs/xs.c Mon Oct 10 13:42:38 2005 +++ b/tools/python/xen/lowlevel/xs/xs.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/python/xen/xend/xenstore/xstransact.py --- a/tools/python/xen/xend/xenstore/xstransact.py Mon Oct 10 13:42:38 2005 +++ b/tools/python/xen/xend/xenstore/xstransact.py Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/python/xen/xend/xenstore/xswatch.py --- a/tools/python/xen/xend/xenstore/xswatch.py Mon Oct 10 13:42:38 2005 +++ b/tools/python/xen/xend/xenstore/xswatch.py Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/Makefile --- a/tools/xenstore/Makefile Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/Makefile Mon Oct 10 13:46:53 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 diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/07watch.test --- a/tools/xenstore/testsuite/07watch.test Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/testsuite/07watch.test Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/08transaction.test --- a/tools/xenstore/testsuite/08transaction.test Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/testsuite/08transaction.test Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/10domain-homedir.test --- a/tools/xenstore/testsuite/10domain-homedir.test Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/testsuite/10domain-homedir.test Mon Oct 10 13:46:53 2005 @@ -16,4 +16,3 @@ write /home/foo/bar contents expect 1:foo/bar:token 1 waitwatch -1 ackwatch token diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/11domain-watch.test --- a/tools/xenstore/testsuite/11domain-watch.test Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/testsuite/11domain-watch.test Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/12readonly.test --- a/tools/xenstore/testsuite/12readonly.test Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/testsuite/12readonly.test Mon Oct 10 13:46:53 2005 @@ -36,4 +36,3 @@ 1 write /test contents expect /test:token waitwatch -ackwatch token diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/testsuite/13watch-ack.test --- a/tools/xenstore/testsuite/13watch-ack.test Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/testsuite/13watch-ack.test Mon Oct 10 13:46:53 2005 @@ -18,5 +18,4 @@ 1 waitwatch 3 write /test/1 contents1 4 write /test/3 contents3 -1 ackwatch token2 1 close diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstore_client.c --- a/tools/xenstore/xenstore_client.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstore_client.c Mon Oct 10 13:46:53 2005 @@ -32,6 +32,7 @@ main(int argc, char **argv) { struct xs_handle *xsh; + struct xs_transaction_handle *xth; bool success; int ret = 0; #if defined(CLIENT_read) || defined(CLIENT_list) @@ -84,13 +85,13 @@ #endif 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 +103,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 +112,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 +120,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 +129,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 +146,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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_core.c --- a/tools/xenstore/xenstored_core.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstored_core.c Mon Oct 10 13:46:53 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,52 +235,50 @@ 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; - - if (out->inhdr) { - if (verbose) - xprintf("Writing msg %s (%s) out to %p\n", - sockmsg_string(out->hdr.msg.type), - out->buffer, conn); - ret = conn->write(conn, out->hdr.raw + out->used, - sizeof(out->hdr) - out->used); + struct buffered_data *out, *tmp; + + list_for_each_entry_safe(out, tmp, &conn->out_list, list) { + if (out->inhdr) { + if (verbose) + xprintf("Writing msg %s (%s) out to %p\n", + sockmsg_string(out->hdr.msg.type), + out->buffer, conn); + ret = conn->write(conn, out->hdr.raw + out->used, + sizeof(out->hdr) - out->used); + if (ret < 0) + return false; + + out->used += ret; + if (out->used < sizeof(out->hdr)) + return true; + + out->inhdr = false; + out->used = 0; + + /* Second write might block if non-zero. */ + if (out->hdr.msg.len && !conn->domain) + return true; + } + + ret = conn->write(conn, out->buffer + out->used, + out->hdr.msg.len - out->used); + if (ret < 0) return false; out->used += ret; - if (out->used < sizeof(out->hdr)) + if (out->used != out->hdr.msg.len) return true; - out->inhdr = false; - out->used = 0; - - /* Second write might block if non-zero. */ - if (out->hdr.msg.len && !conn->domain) - return true; - } - - ret = conn->write(conn, out->buffer + out->used, - out->hdr.msg.len - out->used); - - if (ret < 0) - return false; - - out->used += ret; - if (out->used != out->hdr.msg.len) - return true; - - trace_io(conn, "OUT", out); - conn->out = NULL; - talloc_free(out); - - queue_next_event(conn); - - /* No longer busy? */ - if (!conn->out) - conn->state = OK; + trace_io(conn, "OUT", out); + + list_del(&out->list); + talloc_free(out); + } + return true; } @@ -298,9 +295,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 +324,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; @@ -595,14 +591,7 @@ 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; + list_add_tail(&bdata->list, &conn->out_list); } /* Some routines (write, mkdir, etc) just need a non-error return */ @@ -1103,10 +1092,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; @@ -1153,8 +1138,6 @@ enum xsd_sockmsg_type volatile type = conn->in->hdr.msg.type; jmp_buf talloc_fail; - assert(conn->state == OK); - /* For simplicity, we kill the connection on OOM. */ talloc_set_fail_handler(out_of_mem, &talloc_fail); if (setjmp(talloc_fail)) { @@ -1168,11 +1151,6 @@ 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. @@ -1196,10 +1174,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,7 +1222,7 @@ static void handle_output(struct connection *conn) { - if (!write_message(conn)) + if (!write_messages(conn)) talloc_free(conn); } @@ -1264,9 +1239,6 @@ if (!new) return NULL; - new->state = OK; - new->out = new->waiting_reply = NULL; - new->waiting_for_ack = NULL; new->fd = -1; new->id = 0; new->domain = NULL; @@ -1274,6 +1246,7 @@ 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); @@ -1328,23 +1301,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) @@ -1615,3 +1582,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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_core.h --- a/tools/xenstore/xenstored_core.h Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstored_core.h Mon Oct 10 13:46:53 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,26 +59,17 @@ /* 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; - - /* If we had a watch fire outgoing when we needed to reply... */ - struct buffered_data *waiting_reply; + struct list_head out_list; /* My transaction, if any. */ struct transaction *transaction; @@ -175,3 +163,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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_domain.c --- a/tools/xenstore/xenstored_domain.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstored_domain.c Mon Oct 10 13:46:53 2005 @@ -276,12 +276,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, diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_transaction.c --- a/tools/xenstore/xenstored_transaction.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstored_transaction.c Mon Oct 10 13:46:53 2005 @@ -154,9 +154,9 @@ return; } - /* Set to NULL so fire_watches sends events, tdb_context works. */ trans = conn->transaction; conn->transaction = NULL; + /* Attach transaction to arg for auto-cleanup */ talloc_steal(arg, trans); diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_watch.c --- a/tools/xenstore/xenstored_watch.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstored_watch.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xenstored_watch.h --- a/tools/xenstore/xenstored_watch.h Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xenstored_watch.h Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xs.c --- a/tools/xenstore/xs.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xs.c Mon Oct 10 13:46:53 2005 @@ -78,9 +78,33 @@ /* One transaction at a time. */ pthread_mutex_t transaction_mutex; + pthread_t transaction_pthread; }; +struct xs_transaction_handle { + int id; +}; + static void *read_thread(void *arg); + +static void request_mutex_acquire(struct xs_handle *h) +{ + /* + * We can't distinguish non-transactional from transactional + * requests right now. So temporarily acquire the transaction mutex + * if this task is outside transaction context. + */ + if (h->transaction_pthread != pthread_self()) + pthread_mutex_lock(&h->transaction_mutex); + pthread_mutex_lock(&h->request_mutex); +} + +static void request_mutex_release(struct xs_handle *h) +{ + pthread_mutex_unlock(&h->request_mutex); + if (h->transaction_pthread != pthread_self()) + pthread_mutex_unlock(&h->transaction_mutex); +} int xs_fileno(struct xs_handle *h) { @@ -163,6 +187,7 @@ pthread_mutex_init(&h->request_mutex, NULL); pthread_mutex_init(&h->transaction_mutex, NULL); + h->transaction_pthread = -1; if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0) goto error; @@ -316,7 +341,7 @@ ignorepipe.sa_flags = 0; sigaction(SIGPIPE, &ignorepipe, &oldact); - pthread_mutex_lock(&h->request_mutex); + request_mutex_acquire(h); if (!xs_write_all(h->fd, &msg, sizeof(msg))) goto fail; @@ -329,7 +354,7 @@ if (!ret) goto fail; - pthread_mutex_unlock(&h->request_mutex); + request_mutex_release(h); sigaction(SIGPIPE, &oldact, NULL); if (msg.type == XS_ERROR) { @@ -350,7 +375,7 @@ fail: /* We're in a bad state, so close fd. */ saved_errno = errno; - pthread_mutex_unlock(&h->request_mutex); + request_mutex_release(h); sigaction(SIGPIPE, &oldact, NULL); close_fd: close(h->fd); @@ -386,7 +411,8 @@ 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; @@ -417,7 +443,8 @@ * 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) +void *xs_read(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path, unsigned int *len) { return xs_single(h, XS_READ, path, len); } @@ -425,8 +452,8 @@ /* 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]; @@ -441,7 +468,8 @@ /* 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) { return xs_bool(xs_single(h, XS_MKDIR, path, NULL)); } @@ -449,7 +477,8 @@ /* 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) +bool xs_rm(struct xs_handle *h, struct xs_transaction_handle *t, + const char *path) { return xs_bool(xs_single(h, XS_RM, path, NULL)); } @@ -458,6 +487,7 @@ * 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; @@ -490,7 +520,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) { @@ -593,15 +625,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). */ @@ -620,12 +643,22 @@ /* 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) -{ + * Returns NULL on failure. + */ +struct xs_transaction_handle *xs_transaction_start(struct xs_handle *h) +{ + bool rc; + pthread_mutex_lock(&h->transaction_mutex); - return xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL)); + h->transaction_pthread = pthread_self(); + + rc = xs_bool(xs_single(h, XS_TRANSACTION_START, "", NULL)); + if (!rc) { + h->transaction_pthread = -1; + pthread_mutex_unlock(&h->transaction_mutex); + } + + return (struct xs_transaction_handle *)rc; } /* End a transaction. @@ -633,10 +666,14 @@ * 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 (t == NULL) + return -EINVAL; if (abort) strcpy(abortstr, "F"); @@ -645,6 +682,7 @@ rc = xs_bool(xs_single(h, XS_TRANSACTION_END, abortstr, NULL)); + h->transaction_pthread = -1; pthread_mutex_unlock(&h->transaction_mutex); return rc; diff -r 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xs.h --- a/tools/xenstore/xs.h Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xs.h Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 tools/xenstore/xs_test.c --- a/tools/xenstore/xs_test.c Mon Oct 10 13:42:38 2005 +++ b/tools/xenstore/xs_test.c Mon Oct 10 13:46:53 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 0e7c48861e95 -r 1ac39c7a0435 xen/include/public/io/xs_wire.h --- a/xen/include/public/io/xs_wire.h Mon Oct 10 13:42:38 2005 +++ b/xen/include/public/io/xs_wire.h Mon Oct 10 13:46:53 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 */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |