ia64/xen-unstable

changeset 19699:18c8270da77c

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@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jun 03 11:09:14 2009 +0100 (2009-06-03)
parents f72d26c00002
children e7b63b30ae3d
files extras/mini-os/blkfront.c extras/mini-os/fbfront.c extras/mini-os/include/xenbus.h extras/mini-os/netfront.c extras/mini-os/pcifront.c extras/mini-os/xenbus/xenbus.c
line diff
     1.1 --- a/extras/mini-os/blkfront.c	Tue Jun 02 11:50:16 2009 +0100
     1.2 +++ b/extras/mini-os/blkfront.c	Wed Jun 03 11:09:14 2009 +0100
     1.3 @@ -149,8 +149,12 @@ again:
     1.4          goto abort_transaction;
     1.5      }
     1.6  
     1.7 -    err = xenbus_printf(xbt, nodename, "state", "%u",
     1.8 -            4); /* connected */
     1.9 +    snprintf(path, sizeof(path), "%s/state", nodename);
    1.10 +    err = xenbus_switch_state(xbt, path, XenbusStateConnected);
    1.11 +    if (err) {
    1.12 +        message = "switching state";
    1.13 +        goto abort_transaction;
    1.14 +    }
    1.15  
    1.16  
    1.17      err = xenbus_transaction_end(xbt, 0, &retry);
    1.18 @@ -179,6 +183,7 @@ done:
    1.19      dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0);
    1.20  
    1.21      {
    1.22 +        XenbusState state;
    1.23          char path[strlen(dev->backend) + 1 + 19 + 1];
    1.24          snprintf(path, sizeof(path), "%s/mode", dev->backend);
    1.25          msg = xenbus_read(XBT_NIL, path, &c);
    1.26 @@ -196,7 +201,15 @@ done:
    1.27  
    1.28          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
    1.29  
    1.30 -        xenbus_wait_for_value(path, "4", &dev->events);
    1.31 +        msg = NULL;
    1.32 +        state = xenbus_read_integer(path);
    1.33 +        while (msg == NULL && state < XenbusStateConnected)
    1.34 +            msg = xenbus_wait_for_state_change(path, &state, &dev->events);
    1.35 +        if (msg != NULL || state != XenbusStateConnected) {
    1.36 +            printk("backend not available, state=%d\n", state);
    1.37 +            xenbus_unwatch_path(XBT_NIL, path);
    1.38 +            goto error;
    1.39 +        }
    1.40  
    1.41          snprintf(path, sizeof(path), "%s/info", dev->backend);
    1.42          dev->info.info = xenbus_read_integer(path);
    1.43 @@ -230,25 +243,48 @@ error:
    1.44  
    1.45  void shutdown_blkfront(struct blkfront_dev *dev)
    1.46  {
    1.47 -    char* err;
    1.48 -    char *nodename = dev->nodename;
    1.49 +    char* err = NULL;
    1.50 +    XenbusState state;
    1.51  
    1.52      char path[strlen(dev->backend) + 1 + 5 + 1];
    1.53 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
    1.54  
    1.55      blkfront_sync(dev);
    1.56  
    1.57 -    printk("close blk: backend at %s\n",dev->backend);
    1.58 +    printk("close blk: backend=%s node=%s\n", dev->backend, dev->nodename);
    1.59  
    1.60      snprintf(path, sizeof(path), "%s/state", dev->backend);
    1.61 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
    1.62 -    xenbus_wait_for_value(path, "5", &dev->events);
    1.63 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
    1.64  
    1.65 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    1.66 -    xenbus_wait_for_value(path, "6", &dev->events);
    1.67 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
    1.68 +        printk("shutdown_blkfront: error changing state to %d: %s\n",
    1.69 +                XenbusStateClosing, err);
    1.70 +        goto close;
    1.71 +    }
    1.72 +    state = xenbus_read_integer(path);
    1.73 +    while (err == NULL && state < XenbusStateClosing)
    1.74 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
    1.75  
    1.76 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
    1.77 -    xenbus_wait_for_value(path, "2", &dev->events);
    1.78 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
    1.79 +        printk("shutdown_blkfront: error changing state to %d: %s\n",
    1.80 +                XenbusStateClosed, err);
    1.81 +        goto close;
    1.82 +    }
    1.83 +    state = xenbus_read_integer(path);
    1.84 +    if (state < XenbusStateClosed)
    1.85 +        xenbus_wait_for_state_change(path, &state, &dev->events);
    1.86  
    1.87 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
    1.88 +        printk("shutdown_blkfront: error changing state to %d: %s\n",
    1.89 +                XenbusStateInitialising, err);
    1.90 +        goto close;
    1.91 +    }
    1.92 +    err = NULL;
    1.93 +    state = xenbus_read_integer(path);
    1.94 +    while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
    1.95 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
    1.96 +
    1.97 +close:
    1.98      xenbus_unwatch_path(XBT_NIL, path);
    1.99  
   1.100      snprintf(path, sizeof(path), "%s/ring-ref", nodename);
     2.1 --- a/extras/mini-os/fbfront.c	Tue Jun 02 11:50:16 2009 +0100
     2.2 +++ b/extras/mini-os/fbfront.c	Wed Jun 03 11:09:14 2009 +0100
     2.3 @@ -121,7 +121,8 @@ again:
     2.4          }
     2.5      }
     2.6  
     2.7 -    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
     2.8 +    snprintf(path, sizeof(path), "%s/state", nodename);
     2.9 +    err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
    2.10      if (err)
    2.11          printk("error writing initialized: %s\n", err);
    2.12  
    2.13 @@ -150,17 +151,33 @@ done:
    2.14      printk("backend at %s\n", dev->backend);
    2.15  
    2.16      {
    2.17 +        XenbusState state;
    2.18          char path[strlen(dev->backend) + 1 + 6 + 1];
    2.19 +        char frontpath[strlen(nodename) + 1 + 6 + 1];
    2.20  
    2.21          snprintf(path, sizeof(path), "%s/state", dev->backend);
    2.22  
    2.23          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
    2.24  
    2.25 -        xenbus_wait_for_value(path, "4", &dev->events);
    2.26 +        err = NULL;
    2.27 +        state = xenbus_read_integer(path);
    2.28 +        while (err == NULL && state < XenbusStateConnected)
    2.29 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
    2.30 +        if (state != XenbusStateConnected) {
    2.31 +            printk("backend not available, state=%d\n", state);
    2.32 +            xenbus_unwatch_path(XBT_NIL, path);
    2.33 +            goto error;
    2.34 +        }
    2.35  
    2.36          printk("%s connected\n", dev->backend);
    2.37  
    2.38 -        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
    2.39 +        snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
    2.40 +        if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
    2.41 +            != NULL) {
    2.42 +            printk("error switching state: %s\n", err);
    2.43 +            xenbus_unwatch_path(XBT_NIL, path);
    2.44 +            goto error;
    2.45 +        }
    2.46      }
    2.47      unmask_evtchn(dev->evtchn);
    2.48  
    2.49 @@ -211,24 +228,43 @@ int kbdfront_receive(struct kbdfront_dev
    2.50  
    2.51  void shutdown_kbdfront(struct kbdfront_dev *dev)
    2.52  {
    2.53 -    char* err;
    2.54 -    char *nodename = dev->nodename;
    2.55 +    char* err = NULL;
    2.56 +    XenbusState state;
    2.57  
    2.58      char path[strlen(dev->backend) + 1 + 5 + 1];
    2.59 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
    2.60  
    2.61      printk("close kbd: backend at %s\n",dev->backend);
    2.62  
    2.63      snprintf(path, sizeof(path), "%s/state", dev->backend);
    2.64 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
    2.65 -    xenbus_wait_for_value(path, "5", &dev->events);
    2.66 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
    2.67 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
    2.68 +        printk("shutdown_kbdfront: error changing state to %d: %s\n",
    2.69 +                XenbusStateClosing, err);
    2.70 +        goto close_kbdfront;
    2.71 +    }
    2.72 +    state = xenbus_read_integer(path);
    2.73 +    while (err == NULL && state < XenbusStateClosing)
    2.74 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
    2.75  
    2.76 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    2.77 -    xenbus_wait_for_value(path, "6", &dev->events);
    2.78 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
    2.79 +        printk("shutdown_kbdfront: error changing state to %d: %s\n",
    2.80 +                XenbusStateClosed, err);
    2.81 +        goto close_kbdfront;
    2.82 +    }
    2.83 +    state = xenbus_read_integer(path);
    2.84 +    if (state < XenbusStateClosed)
    2.85 +        xenbus_wait_for_state_change(path, &state, &dev->events);
    2.86  
    2.87 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
    2.88 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
    2.89 +        printk("shutdown_kbdfront: error changing state to %d: %s\n",
    2.90 +                XenbusStateInitialising, err);
    2.91 +        goto close_kbdfront;
    2.92 +    }
    2.93      // does not work yet.
    2.94      //xenbus_wait_for_value(path, "2", &dev->events);
    2.95  
    2.96 +close_kbdfront:
    2.97      xenbus_unwatch_path(XBT_NIL, path);
    2.98  
    2.99      snprintf(path, sizeof(path), "%s/page-ref", nodename);
   2.100 @@ -432,8 +468,12 @@ again:
   2.101          goto abort_transaction;
   2.102      }
   2.103  
   2.104 -    err = xenbus_printf(xbt, nodename, "state", "%u", 3); /* initialized */
   2.105 -
   2.106 +    snprintf(path, sizeof(path), "%s/state", nodename);
   2.107 +    err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
   2.108 +    if (err) {
   2.109 +        message = "switching state";
   2.110 +        goto abort_transaction;
   2.111 +    }
   2.112  
   2.113      err = xenbus_transaction_end(xbt, 0, &retry);
   2.114      if (retry) {
   2.115 @@ -459,20 +499,36 @@ done:
   2.116      printk("backend at %s\n", dev->backend);
   2.117  
   2.118      {
   2.119 +        XenbusState state;
   2.120          char path[strlen(dev->backend) + 1 + 14 + 1];
   2.121 +        char frontpath[strlen(nodename) + 1 + 6 + 1];
   2.122  
   2.123          snprintf(path, sizeof(path), "%s/state", dev->backend);
   2.124  
   2.125          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
   2.126  
   2.127 -        xenbus_wait_for_value(path, "4", &dev->events);
   2.128 +        err = NULL;
   2.129 +        state = xenbus_read_integer(path);
   2.130 +        while (err == NULL && state < XenbusStateConnected)
   2.131 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
   2.132 +        if (state != XenbusStateConnected) {
   2.133 +            printk("backend not available, state=%d\n", state);
   2.134 +            xenbus_unwatch_path(XBT_NIL, path);
   2.135 +            goto error;
   2.136 +        }
   2.137  
   2.138          printk("%s connected\n", dev->backend);
   2.139  
   2.140          snprintf(path, sizeof(path), "%s/request-update", dev->backend);
   2.141          dev->request_update = xenbus_read_integer(path);
   2.142  
   2.143 -        err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 4); /* connected */
   2.144 +        snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
   2.145 +        if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
   2.146 +            != NULL) {
   2.147 +            printk("error switching state: %s\n", err);
   2.148 +            xenbus_unwatch_path(XBT_NIL, path);
   2.149 +            goto error;
   2.150 +        }
   2.151      }
   2.152      unmask_evtchn(dev->evtchn);
   2.153  
   2.154 @@ -551,24 +607,43 @@ void fbfront_resize(struct fbfront_dev *
   2.155  
   2.156  void shutdown_fbfront(struct fbfront_dev *dev)
   2.157  {
   2.158 -    char* err;
   2.159 -    char *nodename = dev->nodename;
   2.160 +    char* err = NULL;
   2.161 +    XenbusState state;
   2.162  
   2.163      char path[strlen(dev->backend) + 1 + 5 + 1];
   2.164 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
   2.165  
   2.166      printk("close fb: backend at %s\n",dev->backend);
   2.167  
   2.168      snprintf(path, sizeof(path), "%s/state", dev->backend);
   2.169 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
   2.170 -    xenbus_wait_for_value(path, "5", &dev->events);
   2.171 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
   2.172 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
   2.173 +        printk("shutdown_fbfront: error changing state to %d: %s\n",
   2.174 +                XenbusStateClosing, err);
   2.175 +        goto close_fbfront;
   2.176 +    }
   2.177 +    state = xenbus_read_integer(path);
   2.178 +    while (err == NULL && state < XenbusStateClosing)
   2.179 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   2.180  
   2.181 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
   2.182 -    xenbus_wait_for_value(path, "6", &dev->events);
   2.183 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
   2.184 +        printk("shutdown_fbfront: error changing state to %d: %s\n",
   2.185 +                XenbusStateClosed, err);
   2.186 +        goto close_fbfront;
   2.187 +    }
   2.188 +    state = xenbus_read_integer(path);
   2.189 +    if (state < XenbusStateClosed)
   2.190 +        xenbus_wait_for_state_change(path, &state, &dev->events);
   2.191  
   2.192 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
   2.193 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
   2.194 +        printk("shutdown_fbfront: error changing state to %d: %s\n",
   2.195 +                XenbusStateInitialising, err);
   2.196 +        goto close_fbfront;
   2.197 +    }
   2.198      // does not work yet
   2.199      //xenbus_wait_for_value(path, "2", &dev->events);
   2.200  
   2.201 +close_fbfront:
   2.202      xenbus_unwatch_path(XBT_NIL, path);
   2.203  
   2.204      snprintf(path, sizeof(path), "%s/page-ref", nodename);
     3.1 --- a/extras/mini-os/include/xenbus.h	Tue Jun 02 11:50:16 2009 +0100
     3.2 +++ b/extras/mini-os/include/xenbus.h	Wed Jun 03 11:09:14 2009 +0100
     3.3 @@ -1,6 +1,8 @@
     3.4  #ifndef XENBUS_H__
     3.5  #define XENBUS_H__
     3.6  
     3.7 +#include <xen/io/xenbus.h>
     3.8 +
     3.9  typedef unsigned long xenbus_transaction_t;
    3.10  #define XBT_NIL ((xenbus_transaction_t)0)
    3.11  
    3.12 @@ -27,6 +29,8 @@ extern struct wait_queue_head xenbus_wat
    3.13  void xenbus_wait_for_watch(xenbus_event_queue *queue);
    3.14  char **xenbus_wait_for_watch_return(xenbus_event_queue *queue);
    3.15  char* xenbus_wait_for_value(const char *path, const char *value, xenbus_event_queue *queue);
    3.16 +char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue);
    3.17 +char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state);
    3.18  
    3.19  /* When no token is provided, use a global queue. */
    3.20  #define XENBUS_WATCH_PATH_TOKEN "xenbus_watch_path"
     4.1 --- a/extras/mini-os/netfront.c	Tue Jun 02 11:50:16 2009 +0100
     4.2 +++ b/extras/mini-os/netfront.c	Wed Jun 03 11:09:14 2009 +0100
     4.3 @@ -405,9 +405,12 @@ again:
     4.4          goto abort_transaction;
     4.5      }
     4.6  
     4.7 -    err = xenbus_printf(xbt, nodename, "state", "%u",
     4.8 -            4); /* connected */
     4.9 -
    4.10 +    snprintf(path, sizeof(path), "%s/state", nodename);
    4.11 +    err = xenbus_switch_state(xbt, path, XenbusStateConnected);
    4.12 +    if (err) {
    4.13 +        message = "switching state";
    4.14 +        goto abort_transaction;
    4.15 +    }
    4.16  
    4.17      err = xenbus_transaction_end(xbt, 0, &retry);
    4.18      if (retry) {
    4.19 @@ -437,12 +440,21 @@ done:
    4.20      printk("mac is %s\n",dev->mac);
    4.21  
    4.22      {
    4.23 +        XenbusState state;
    4.24          char path[strlen(dev->backend) + 1 + 5 + 1];
    4.25          snprintf(path, sizeof(path), "%s/state", dev->backend);
    4.26  
    4.27          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
    4.28  
    4.29 -        xenbus_wait_for_value(path, "4", &dev->events);
    4.30 +        err = NULL;
    4.31 +        state = xenbus_read_integer(path);
    4.32 +        while (err == NULL && state < XenbusStateConnected)
    4.33 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
    4.34 +        if (state != XenbusStateConnected) {
    4.35 +            printk("backend not avalable, state=%d\n", state);
    4.36 +            xenbus_unwatch_path(XBT_NIL, path);
    4.37 +            goto error;
    4.38 +        }
    4.39  
    4.40          if (ip) {
    4.41              snprintf(path, sizeof(path), "%s/ip", dev->backend);
    4.42 @@ -490,24 +502,46 @@ int netfront_tap_open(char *nodename) {
    4.43  
    4.44  void shutdown_netfront(struct netfront_dev *dev)
    4.45  {
    4.46 -    char* err;
    4.47 -    char *nodename = dev->nodename;
    4.48 +    char* err = NULL;
    4.49 +    XenbusState state;
    4.50  
    4.51      char path[strlen(dev->backend) + 1 + 5 + 1];
    4.52 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
    4.53  
    4.54      printk("close network: backend at %s\n",dev->backend);
    4.55  
    4.56      snprintf(path, sizeof(path), "%s/state", dev->backend);
    4.57 -
    4.58 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
    4.59 -    xenbus_wait_for_value(path, "5", &dev->events);
    4.60 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
    4.61  
    4.62 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    4.63 -    xenbus_wait_for_value(path, "6", &dev->events);
    4.64 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
    4.65 +        printk("shutdown_netfront: error changing state to %d: %s\n",
    4.66 +                XenbusStateClosing, err);
    4.67 +        goto close;
    4.68 +    }
    4.69 +    state = xenbus_read_integer(path);
    4.70 +    while (err == NULL && state < XenbusStateClosing)
    4.71 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
    4.72  
    4.73 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
    4.74 -    xenbus_wait_for_value(path, "2", &dev->events);
    4.75 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
    4.76 +        printk("shutdown_netfront: error changing state to %d: %s\n",
    4.77 +                XenbusStateClosed, err);
    4.78 +        goto close;
    4.79 +    }
    4.80 +    state = xenbus_read_integer(path);
    4.81 +    if (state < XenbusStateClosed)
    4.82 +        xenbus_wait_for_state_change(path, &state, &dev->events);
    4.83  
    4.84 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
    4.85 +        printk("shutdown_netfront: error changing state to %d: %s\n",
    4.86 +                XenbusStateInitialising, err);
    4.87 +        goto close;
    4.88 +    }
    4.89 +    err = NULL;
    4.90 +    state = xenbus_read_integer(path);
    4.91 +    while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
    4.92 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
    4.93 +
    4.94 +close:
    4.95      xenbus_unwatch_path(XBT_NIL, path);
    4.96  
    4.97      snprintf(path, sizeof(path), "%s/tx-ring-ref", nodename);
     5.1 --- a/extras/mini-os/pcifront.c	Tue Jun 02 11:50:16 2009 +0100
     5.2 +++ b/extras/mini-os/pcifront.c	Wed Jun 03 11:09:14 2009 +0100
     5.3 @@ -111,9 +111,12 @@ again:
     5.4          goto abort_transaction;
     5.5      }
     5.6  
     5.7 -    err = xenbus_printf(xbt, nodename, "state", "%u",
     5.8 -            3); /* initialised */
     5.9 -
    5.10 +    snprintf(path, sizeof(path), "%s/state", nodename);
    5.11 +    err = xenbus_switch_state(xbt, path, XenbusStateInitialised);
    5.12 +    if (err) {
    5.13 +        message = "switching state";
    5.14 +        goto abort_transaction;
    5.15 +    }
    5.16  
    5.17      err = xenbus_transaction_end(xbt, 0, &retry);
    5.18      if (retry) {
    5.19 @@ -140,13 +143,29 @@ done:
    5.20  
    5.21      {
    5.22          char path[strlen(dev->backend) + 1 + 5 + 1];
    5.23 +        char frontpath[strlen(nodename) + 1 + 5 + 1];
    5.24 +        XenbusState state;
    5.25          snprintf(path, sizeof(path), "%s/state", dev->backend);
    5.26  
    5.27          xenbus_watch_path_token(XBT_NIL, path, path, &dev->events);
    5.28  
    5.29 -        xenbus_wait_for_value(path, "4", &dev->events);
    5.30 +        err = NULL;
    5.31 +        state = xenbus_read_integer(path);
    5.32 +        while (err == NULL && state < XenbusStateConnected)
    5.33 +            err = xenbus_wait_for_state_change(path, &state, &dev->events);
    5.34 +        if (state != XenbusStateConnected) {
    5.35 +            printk("backend not avalable, state=%d\n", state);
    5.36 +            xenbus_unwatch_path(XBT_NIL, path);
    5.37 +            goto error;
    5.38 +        }
    5.39  
    5.40 -        xenbus_printf(xbt, nodename, "state", "%u", 4); /* connected */
    5.41 +        snprintf(frontpath, sizeof(frontpath), "%s/state", nodename);
    5.42 +        if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected))
    5.43 +            != NULL) {
    5.44 +            printk("error switching state %s\n", err);
    5.45 +            xenbus_unwatch_path(XBT_NIL, path);
    5.46 +            goto error;
    5.47 +        }
    5.48      }
    5.49      unmask_evtchn(dev->evtchn);
    5.50  
    5.51 @@ -190,23 +209,45 @@ void pcifront_scan(struct pcifront_dev *
    5.52  
    5.53  void shutdown_pcifront(struct pcifront_dev *dev)
    5.54  {
    5.55 -    char* err;
    5.56 -    char *nodename = dev->nodename;
    5.57 +    char* err = NULL;
    5.58 +    XenbusState state;
    5.59  
    5.60      char path[strlen(dev->backend) + 1 + 5 + 1];
    5.61 +    char nodename[strlen(dev->nodename) + 1 + 5 + 1];
    5.62  
    5.63      printk("close pci: backend at %s\n",dev->backend);
    5.64  
    5.65      snprintf(path, sizeof(path), "%s/state", dev->backend);
    5.66 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 5); /* closing */
    5.67 -    xenbus_wait_for_value(path, "5", &dev->events);
    5.68 +    snprintf(nodename, sizeof(nodename), "%s/state", dev->nodename);
    5.69 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosing)) != NULL) {
    5.70 +        printk("shutdown_pcifront: error changing state to %d: %s\n",
    5.71 +                XenbusStateClosing, err);
    5.72 +        goto close_pcifront;
    5.73 +    }
    5.74 +    state = xenbus_read_integer(path);
    5.75 +    while (err == NULL && state < XenbusStateClosing)
    5.76 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
    5.77  
    5.78 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 6);
    5.79 -    xenbus_wait_for_value(path, "6", &dev->events);
    5.80 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateClosed)) != NULL) {
    5.81 +        printk("shutdown_pcifront: error changing state to %d: %s\n",
    5.82 +                XenbusStateClosed, err);
    5.83 +        goto close_pcifront;
    5.84 +    }
    5.85 +    state = xenbus_read_integer(path);
    5.86 +    if (state < XenbusStateClosed)
    5.87 +        xenbus_wait_for_state_change(path, &state, &dev->events);
    5.88  
    5.89 -    err = xenbus_printf(XBT_NIL, nodename, "state", "%u", 1);
    5.90 -    xenbus_wait_for_value(path, "2", &dev->events);
    5.91 +    if ((err = xenbus_switch_state(XBT_NIL, nodename, XenbusStateInitialising)) != NULL) {
    5.92 +        printk("shutdown_pcifront: error changing state to %d: %s\n",
    5.93 +                XenbusStateInitialising, err);
    5.94 +        goto close_pcifront;
    5.95 +    }
    5.96 +    err = NULL;
    5.97 +    state = xenbus_read_integer(path);
    5.98 +    while (err == NULL && (state < XenbusStateInitWait || state >= XenbusStateClosed))
    5.99 +        err = xenbus_wait_for_state_change(path, &state, &dev->events);
   5.100  
   5.101 +close_pcifront:
   5.102      xenbus_unwatch_path(XBT_NIL, path);
   5.103  
   5.104      snprintf(path, sizeof(path), "%s/info-ref", nodename);
     6.1 --- a/extras/mini-os/xenbus/xenbus.c	Tue Jun 02 11:50:16 2009 +0100
     6.2 +++ b/extras/mini-os/xenbus/xenbus.c	Wed Jun 03 11:09:14 2009 +0100
     6.3 @@ -120,6 +120,70 @@ char* xenbus_wait_for_value(const char* 
     6.4      return NULL;
     6.5  }
     6.6  
     6.7 +char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state)
     6.8 +{
     6.9 +    char *current_state;
    6.10 +    char *msg = NULL;
    6.11 +    char *msg2 = NULL;
    6.12 +    char value[2];
    6.13 +    XenbusState rs;
    6.14 +    int xbt_flag = 0;
    6.15 +    int retry = 0;
    6.16 +
    6.17 +    do {
    6.18 +        if (xbt == XBT_NIL) {
    6.19 +            xenbus_transaction_start(&xbt);
    6.20 +            xbt_flag = 1;
    6.21 +        }
    6.22 +
    6.23 +        msg = xenbus_read(xbt, path, &current_state);
    6.24 +        if (msg) goto exit;
    6.25 +
    6.26 +        rs = (XenbusState) (current_state[0] - '0');
    6.27 +        free(current_state);
    6.28 +        if (rs == state) {
    6.29 +            msg = NULL;
    6.30 +            goto exit;
    6.31 +        }
    6.32 +
    6.33 +        snprintf(value, 2, "%d", state);
    6.34 +        msg = xenbus_write(xbt, path, value);
    6.35 +
    6.36 +exit:
    6.37 +        if (xbt_flag)
    6.38 +            msg2 = xenbus_transaction_end(xbt, 0, &retry);
    6.39 +        if (msg == NULL && msg2 != NULL)
    6.40 +            msg = msg2;
    6.41 +    } while (retry);
    6.42 +
    6.43 +    return msg;
    6.44 +}
    6.45 +
    6.46 +char *xenbus_wait_for_state_change(const char* path, XenbusState *state, xenbus_event_queue *queue)
    6.47 +{
    6.48 +    if (!queue)
    6.49 +        queue = &xenbus_events;
    6.50 +    for(;;)
    6.51 +    {
    6.52 +        char *res, *msg;
    6.53 +        XenbusState rs;
    6.54 +
    6.55 +        msg = xenbus_read(XBT_NIL, path, &res);
    6.56 +        if(msg) return msg;
    6.57 +
    6.58 +        rs = (XenbusState) (res[0] - 48);
    6.59 +        free(res);
    6.60 +
    6.61 +        if (rs == *state)
    6.62 +            xenbus_wait_for_watch(queue);
    6.63 +        else {
    6.64 +            *state = rs;
    6.65 +            break;
    6.66 +        }
    6.67 +    }
    6.68 +    return NULL;
    6.69 +}
    6.70 +
    6.71  
    6.72  static void xenbus_thread_func(void *ign)
    6.73  {