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