Hi all,
this patch refactors minios' xenbus state machine: it implements
xenbus_wait_for_state_change and xenbus_switch_state and changes the
various frontends to use the two functions and do proper error checking.
Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
diff -r 50e048b77ad1 extras/mini-os/blkfront.c
--- a/extras/mini-os/blkfront.c Fri May 29 09:28:15 2009 +0100
+++ b/extras/mini-os/blkfront.c Tue Jun 02 18:14:57 2009 +0100
@@ -149,8 +149,12 @@
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 @@
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 @@
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 @@
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);
+ snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &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);
- 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, 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 -r 50e048b77ad1 extras/mini-os/fbfront.c
--- a/extras/mini-os/fbfront.c Fri May 29 09:28:15 2009 +0100
+++ b/extras/mini-os/fbfront.c Tue Jun 02 18:14:57 2009 +0100
@@ -121,7 +121,8 @@
}
}
- 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 @@
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 @@
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);
+ 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);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &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);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ 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 @@
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 @@
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 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);
+ 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);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &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);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
+ 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 -r 50e048b77ad1 extras/mini-os/include/xenbus.h
--- a/extras/mini-os/include/xenbus.h Fri May 29 09:28:15 2009 +0100
+++ b/extras/mini-os/include/xenbus.h Tue Jun 02 18:14:57 2009 +0100
@@ -1,5 +1,7 @@
#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 @@
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 -r 50e048b77ad1 extras/mini-os/netfront.c
--- a/extras/mini-os/netfront.c Fri May 29 09:28:15 2009 +0100
+++ b/extras/mini-os/netfront.c Tue Jun 02 18:14:57 2009 +0100
@@ -405,9 +405,12 @@
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 @@
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 @@
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);
+ 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);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &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);
- 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,
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 -r 50e048b77ad1 extras/mini-os/pcifront.c
--- a/extras/mini-os/pcifront.c Fri May 29 09:28:15 2009 +0100
+++ b/extras/mini-os/pcifront.c Tue Jun 02 18:14:57 2009 +0100
@@ -111,9 +111,12 @@
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 @@
{
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 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);
+ 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);
- err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
- xenbus_wait_for_value(path, "6", &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);
- 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,
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 -r 50e048b77ad1 extras/mini-os/xenbus/xenbus.c
--- a/extras/mini-os/xenbus/xenbus.c Fri May 29 09:28:15 2009 +0100
+++ b/extras/mini-os/xenbus/xenbus.c Tue Jun 02 18:14:57 2009 +0100
@@ -118,6 +118,70 @@
else xenbus_wait_for_watch(queue);
}
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, ¤t_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;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|