aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extras/mini-os/blkfront.c62
-rw-r--r--extras/mini-os/fbfront.c125
-rw-r--r--extras/mini-os/include/xenbus.h4
-rw-r--r--extras/mini-os/netfront.c62
-rw-r--r--extras/mini-os/pcifront.c71
-rw-r--r--extras/mini-os/xenbus/xenbus.c64
6 files changed, 321 insertions, 67 deletions
diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c
index 1534747acb..bba1a2ffa6 100644
--- a/extras/mini-os/blkfront.c
+++ b/extras/mini-os/blkfront.c
@@ -149,8 +149,12 @@ again:
goto abort_transaction;
}
- err = xenbus_printf(xbt, nodename, "state", "%u",
- 4); /* connected */
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateConnected);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
err = xenbus_transaction_end(xbt, 0, &retry);
@@ -179,6 +183,7 @@ done:
dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
{
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 19 + 1];
snprintf(path, sizeof(path), "%s/mode", dev->backend);
msg = xenbus_read(XBT_NIL, path, &c);
@@ -196,7 +201,15 @@ done:
xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
- xenbus_wait_for_value(path, "4", &dev->events);
+ msg = NULL;
+ state = xenbus_read_integer(path);
+ while (msg == NULL && state < XenbusStateConnected)
+ msg = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (msg != NULL || state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
snprintf(path, sizeof(path), "%s/info", dev->backend);
dev->info.info = xenbus_read_integer(path);
@@ -230,25 +243,48 @@ error:
void shutdown_blkfront(struct blkfront_dev *dev)
{
- char* err;
- char *nodename = dev->nodename;
+ char* err = NULL;
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 5 + 1];
+ char nodename[strlen(dev->nodename) + 1 + 5 + 1];
blkfront_sync(dev);
- printk("close blk: backend at %s\n",dev->backend);
+ printk("close blk: backend=%s node=%s\n", dev->backend, dev->nodename);
snprintf(path, sizeof(path), "%s/state", dev->backend);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
- xenbus_wait_for_value(path, "5", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &dev->events);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
- xenbus_wait_for_value(path, "2", &dev->events);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_blkfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_blkfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ if (state < XenbusStateClosed)
+ xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_blkfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close;
+ }
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+close:
xenbus_unwatch_path(XBT_NIL, path);
snprintf(path, sizeof(path), "%s/ring-ref", nodename);
diff --git a/extras/mini-os/fbfront.c b/extras/mini-os/fbfront.c
index fe227d6ca5..355b8eef06 100644
--- a/extras/mini-os/fbfront.c
+++ b/extras/mini-os/fbfront.c
@@ -121,7 +121,8 @@ again:
}
}
- err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
if (err)
printk("error writing initialized: %s\n", err);
@@ -150,17 +151,33 @@ done:
printk("backend at %s\n", dev->backend);
{
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 6 + 1];
+ char frontpath[strlen(nodename) + 1 + 6 + 1];
snprintf(path, sizeof(path), "%s/state", dev->backend);
xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
- xenbus_wait_for_value(path, "4", &dev->events);
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
printk("%s connected\n", dev->backend);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
+ snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
+ if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
+ != NULL) {
+ printk("error switching state: %s\n", err);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
}
unmask_evtchn(dev->evtchn);
@@ -211,24 +228,43 @@ int kbdfront_receive(struct kbdfront_dev *dev, union xenkbd_in_event *buf, int n
void shutdown_kbdfront(struct kbdfront_dev *dev)
{
- char* err;
- char *nodename = dev->nodename;
+ char* err = NULL;
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 5 + 1];
+ char nodename[strlen(dev->nodename) + 1 + 5 + 1];
printk("close kbd: backend at %s\n",dev->backend);
snprintf(path, sizeof(path), "%s/state", dev->backend);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
- xenbus_wait_for_value(path, "5", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_kbdfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close_kbdfront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_kbdfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close_kbdfront;
+ }
+ state = xenbus_read_integer(path);
+ if (state < XenbusStateClosed)
+ xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_kbdfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close_kbdfront;
+ }
// does not work yet.
//xenbus_wait_for_value(path, "2", &dev->events);
+close_kbdfront:
xenbus_unwatch_path(XBT_NIL, path);
snprintf(path, sizeof(path), "%s/page-ref", nodename);
@@ -432,8 +468,12 @@ again:
goto abort_transaction;
}
- err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
-
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
err = xenbus_transaction_end(xbt, 0, &retry);
if (retry) {
@@ -459,20 +499,36 @@ done:
printk("backend at %s\n", dev->backend);
{
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 14 + 1];
+ char frontpath[strlen(nodename) + 1 + 6 + 1];
snprintf(path, sizeof(path), "%s/state", dev->backend);
xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
- xenbus_wait_for_value(path, "4", &dev->events);
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not available, state=%d\n", state);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
printk("%s connected\n", dev->backend);
snprintf(path, sizeof(path), "%s/request-update", dev->backend);
dev->request_update = xenbus_read_integer(path);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
+ snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
+ != NULL) {
+ printk("error switching state: %s\n", err);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
}
unmask_evtchn(dev->evtchn);
@@ -551,24 +607,43 @@ void fbfront_resize(struct fbfront_dev *dev, int width, int height, int stride,
void shutdown_fbfront(struct fbfront_dev *dev)
{
- char* err;
- char *nodename = dev->nodename;
+ char* err = NULL;
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 5 + 1];
+ char nodename[strlen(dev->nodename) + 1 + 5 + 1];
printk("close fb: backend at %s\n",dev->backend);
snprintf(path, sizeof(path), "%s/state", dev->backend);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
- xenbus_wait_for_value(path, "5", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_fbfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close_fbfront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_fbfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close_fbfront;
+ }
+ state = xenbus_read_integer(path);
+ if (state < XenbusStateClosed)
+ xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_fbfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close_fbfront;
+ }
// does not work yet
//xenbus_wait_for_value(path, "2", &dev->events);
+close_fbfront:
xenbus_unwatch_path(XBT_NIL, path);
snprintf(path, sizeof(path), "%s/page-ref", nodename);
diff --git a/extras/mini-os/include/xenbus.h b/extras/mini-os/include/xenbus.h
index 30a1c08143..de618fcfa5 100644
--- a/extras/mini-os/include/xenbus.h
+++ b/extras/mini-os/include/xenbus.h
@@ -1,6 +1,8 @@
#ifndef XENBUS_H__
#define XENBUS_H__
+#include <xen/io/xenbus.h>
+
typedef unsigned long xenbus_transaction_t;
#define XBT_NIL ((xenbus_transaction_t)0)
@@ -27,6 +29,8 @@ extern struct wait_queue_head xenbus_watch_queue;
void xenbus_wait_for_watch(xenbus_event_queue *queue);
char **xenbus_wait_for_watch_return(xenbus_event_queue *queue);
char* xenbus_wait_for_value(const char *path, const char *value, xenbus_event_queue *queue);
+char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue);
+char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state);
/* When no token is provided, use a global queue. */
#define XENBUS_WATCH_PATH_TOKEN "xenbus_watch_path"
diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c
index a235769377..ea092df074 100644
--- a/extras/mini-os/netfront.c
+++ b/extras/mini-os/netfront.c
@@ -405,9 +405,12 @@ again:
goto abort_transaction;
}
- err = xenbus_printf(xbt, nodename, "state", "%u",
- 4); /* connected */
-
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateConnected);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
err = xenbus_transaction_end(xbt, 0, &retry);
if (retry) {
@@ -437,12 +440,21 @@ done:
printk("mac is %s\n",dev->mac);
{
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 5 + 1];
snprintf(path, sizeof(path), "%s/state", dev->backend);
xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
- xenbus_wait_for_value(path, "4", &dev->events);
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not avalable, state=%d\n", state);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
if (ip) {
snprintf(path, sizeof(path), "%s/ip", dev->backend);
@@ -490,24 +502,46 @@ int netfront_tap_open(char *nodename) {
void shutdown_netfront(struct netfront_dev *dev)
{
- char* err;
- char *nodename = dev->nodename;
+ char* err = NULL;
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 5 + 1];
+ char nodename[strlen(dev->nodename) + 1 + 5 + 1];
printk("close network: backend at %s\n",dev->backend);
snprintf(path, sizeof(path), "%s/state", dev->backend);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
- xenbus_wait_for_value(path, "5", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
- xenbus_wait_for_value(path, "2", &dev->events);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_netfront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_netfront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close;
+ }
+ state = xenbus_read_integer(path);
+ if (state < XenbusStateClosed)
+ xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_netfront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close;
+ }
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+close:
xenbus_unwatch_path(XBT_NIL, path);
snprintf(path, sizeof(path), "%s/tx-ring-ref", nodename);
diff --git a/extras/mini-os/pcifront.c b/extras/mini-os/pcifront.c
index 5b68d86b56..70ea89b82d 100644
--- a/extras/mini-os/pcifront.c
+++ b/extras/mini-os/pcifront.c
@@ -111,9 +111,12 @@ again:
goto abort_transaction;
}
- err = xenbus_printf(xbt, nodename, "state", "%u",
- 3); /* initialised */
-
+ snprintf(path, sizeof(path), "%s/state", nodename);
+ err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
+ if (err) {
+ message = "switching state";
+ goto abort_transaction;
+ }
err = xenbus_transaction_end(xbt, 0, &retry);
if (retry) {
@@ -140,13 +143,29 @@ done:
{
char path[strlen(dev->backend) + 1 + 5 + 1];
+ char frontpath[strlen(nodename) + 1 + 5 + 1];
+ XenbusState state;
snprintf(path, sizeof(path), "%s/state", dev->backend);
xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
- xenbus_wait_for_value(path, "4", &dev->events);
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateConnected)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+ if (state != XenbusStateConnected) {
+ printk("backend not avalable, state=%d\n", state);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
- xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
+ snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
+ != NULL) {
+ printk("error switching state %s\n", err);
+ xenbus_unwatch_path(XBT_NIL, path);
+ goto error;
+ }
}
unmask_evtchn(dev->evtchn);
@@ -190,23 +209,45 @@ void pcifront_scan(struct pcifront_dev *dev, void (*func)(unsigned int domain, u
void shutdown_pcifront(struct pcifront_dev *dev)
{
- char* err;
- char *nodename = dev->nodename;
+ char* err = NULL;
+ XenbusState state;
char path[strlen(dev->backend) + 1 + 5 + 1];
+ char nodename[strlen(dev->nodename) + 1 + 5 + 1];
printk("close pci: backend at %s\n",dev->backend);
snprintf(path, sizeof(path), "%s/state", dev->backend);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
- xenbus_wait_for_value(path, "5", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &dev->events);
-
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
- xenbus_wait_for_value(path, "2", &dev->events);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
+ printk("shutdown_pcifront: error changing state to %d: %s\n",
+ XenbusStateClosing, err);
+ goto close_pcifront;
+ }
+ state = xenbus_read_integer(path);
+ while (err == NULL && state < XenbusStateClosing)
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
+ printk("shutdown_pcifront: error changing state to %d: %s\n",
+ XenbusStateClosed, err);
+ goto close_pcifront;
+ }
+ state = xenbus_read_integer(path);
+ if (state < XenbusStateClosed)
+ xenbus_wait_for_state_change(path, &state, &dev->events);
+
+ if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
+ printk("shutdown_pcifront: error changing state to %d: %s\n",
+ XenbusStateInitialising, err);
+ goto close_pcifront;
+ }
+ err = NULL;
+ state = xenbus_read_integer(path);
+ while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
+ err = xenbus_wait_for_state_change(path, &state, &dev->events);
+close_pcifront:
xenbus_unwatch_path(XBT_NIL, path);
snprintf(path, sizeof(path), "%s/info-ref", nodename);
diff --git a/extras/mini-os/xenbus/xenbus.c b/extras/mini-os/xenbus/xenbus.c
index 5ed42a3da7..958e010dab 100644
--- a/extras/mini-os/xenbus/xenbus.c
+++ b/extras/mini-os/xenbus/xenbus.c
@@ -120,6 +120,70 @@ char* xenbus_wait_for_value(const char* path, const char* value, xenbus_event_qu
return NULL;
}
+char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state)
+{
+ char *current_state;
+ char *msg = NULL;
+ char *msg2 = NULL;
+ char value[2];
+ XenbusState rs;
+ int xbt_flag = 0;
+ int retry = 0;
+
+ do {
+ if (xbt == XBT_NIL) {
+ xenbus_transaction_start(&xbt);
+ xbt_flag = 1;
+ }
+
+ msg = xenbus_read(xbt, path, &current_state);
+ if (msg) goto exit;
+
+ rs = (XenbusState) (current_state[0] - '0');
+ free(current_state);
+ if (rs == state) {
+ msg = NULL;
+ goto exit;
+ }
+
+ snprintf(value, 2, "%d", state);
+ msg = xenbus_write(xbt, path, value);
+
+exit:
+ if (xbt_flag)
+ msg2 = xenbus_transaction_end(xbt, 0, &retry);
+ if (msg == NULL && msg2 != NULL)
+ msg = msg2;
+ } while (retry);
+
+ return msg;
+}
+
+char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue)
+{
+ if (!queue)
+ queue = &xenbus_events;
+ for(;;)
+ {
+ char *res, *msg;
+ XenbusState rs;
+
+ msg = xenbus_read(XBT_NIL, path, &res);
+ if(msg) return msg;
+
+ rs = (XenbusState) (res[0] - 48);
+ free(res);
+
+ if (rs == *state)
+ xenbus_wait_for_watch(queue);
+ else {
+ *state = rs;
+ break;
+ }
+ }
+ return NULL;
+}
+
static void xenbus_thread_func(void *ign)
{