[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] minios: refactor xenbus state machine
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1244023754 -3600 # Node ID 18c8270da77cbb970b3b0498b09ad10481c1e6fb # Parent f72d26c0000292889cfe3a85008d2c4482fee772 minios: refactor xenbus state machine Implement xenbus_wait_for_state_change and xenbus_switch_state and change the various frontends to use the two functions and do proper error checking. Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> --- extras/mini-os/blkfront.c | 66 ++++++++++++++++----- extras/mini-os/fbfront.c | 125 ++++++++++++++++++++++++++++++++-------- extras/mini-os/include/xenbus.h | 4 + extras/mini-os/netfront.c | 66 ++++++++++++++++----- extras/mini-os/pcifront.c | 75 ++++++++++++++++++------ extras/mini-os/xenbus/xenbus.c | 64 ++++++++++++++++++++ 6 files changed, 327 insertions(+), 73 deletions(-) diff -r f72d26c00002 -r 18c8270da77c extras/mini-os/blkfront.c --- a/extras/mini-os/blkfront.c Tue Jun 02 11:50:16 2009 +0100 +++ b/extras/mini-os/blkfront.c Wed Jun 03 11:09:14 2009 +0100 @@ -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); - - 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_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 -r f72d26c00002 -r 18c8270da77c extras/mini-os/fbfront.c --- a/extras/mini-os/fbfront.c Tue Jun 02 11:50:16 2009 +0100 +++ b/extras/mini-os/fbfront.c Wed Jun 03 11:09:14 2009 +0100 @@ -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 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 * 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 -r f72d26c00002 -r 18c8270da77c extras/mini-os/include/xenbus.h --- a/extras/mini-os/include/xenbus.h Tue Jun 02 11:50:16 2009 +0100 +++ b/extras/mini-os/include/xenbus.h Wed Jun 03 11:09:14 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_ 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 f72d26c00002 -r 18c8270da77c extras/mini-os/netfront.c --- a/extras/mini-os/netfront.c Tue Jun 02 11:50:16 2009 +0100 +++ b/extras/mini-os/netfront.c Wed Jun 03 11:09:14 2009 +0100 @@ -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); - - 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_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 -r f72d26c00002 -r 18c8270da77c extras/mini-os/pcifront.c --- a/extras/mini-os/pcifront.c Tue Jun 02 11:50:16 2009 +0100 +++ b/extras/mini-os/pcifront.c Wed Jun 03 11:09:14 2009 +0100 @@ -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); - - xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */ + 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; + } + + 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 * 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 -r f72d26c00002 -r 18c8270da77c extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Tue Jun 02 11:50:16 2009 +0100 +++ b/extras/mini-os/xenbus/xenbus.c Wed Jun 03 11:09:14 2009 +0100 @@ -120,6 +120,70 @@ char* xenbus_wait_for_value(const char* 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; +} + static void xenbus_thread_func(void *ign) { _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |