ia64/xen-unstable

changeset 16743:76d88d1da324

minios: add xenbus token support and separate watch event queues

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jan 17 15:20:02 2008 +0000 (2008-01-17)
parents acb35c1088fd
children dc9916adaa1d
files extras/mini-os/include/xenbus.h extras/mini-os/netfront.c extras/mini-os/xenbus/xenbus.c
line diff
     1.1 --- a/extras/mini-os/include/xenbus.h	Thu Jan 17 15:18:38 2008 +0000
     1.2 +++ b/extras/mini-os/include/xenbus.h	Thu Jan 17 15:20:02 2008 +0000
     1.3 @@ -12,14 +12,46 @@ void init_xenbus(void);
     1.4     set to a malloc'd copy of the value. */
     1.5  char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
     1.6  
     1.7 -char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
     1.8 -void wait_for_watch(void);
     1.9 -char* xenbus_wait_for_value(const char*,const char*);
    1.10 +/* Watch event queue */
    1.11 +struct xenbus_event {
    1.12 +    /* Keep these two as this for xs.c */
    1.13 +    char *path;
    1.14 +    char *token;
    1.15 +    struct xenbus_event *next;
    1.16 +};
    1.17 +
    1.18 +char *xenbus_watch_path_token(xenbus_transaction_t xbt, const char *path, const char *token, struct xenbus_event *volatile *events);
    1.19 +char *xenbus_unwatch_path_token(xenbus_transaction_t xbt, const char *path, const char *token);
    1.20 +extern struct wait_queue_head xenbus_watch_queue;
    1.21 +void xenbus_wait_for_watch(void);
    1.22 +char **xenbus_wait_for_watch_return(void);
    1.23 +char* xenbus_wait_for_value(const char *path, const char *value);
    1.24 +
    1.25 +/* When no token is provided, use a global queue. */
    1.26 +#define XENBUS_WATCH_PATH_TOKEN "xenbus_watch_path"
    1.27 +extern struct xenbus_event * volatile xenbus_events;
    1.28 +#define xenbus_watch_path(xbt, path) xenbus_watch_path_token(xbt, path, XENBUS_WATCH_PATH_TOKEN, NULL)
    1.29 +#define xenbus_unwatch_path(xbt, path) xenbus_unwatch_path_token(xbt, path, XENBUS_WATCH_PATH_TOKEN)
    1.30 +
    1.31  
    1.32  /* Associates a value with a path.  Returns a malloc'd error string on
    1.33     failure. */
    1.34  char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value);
    1.35  
    1.36 +struct write_req {
    1.37 +    const void *data;
    1.38 +    unsigned len;
    1.39 +};
    1.40 +
    1.41 +/* Send a message to xenbus, in the same fashion as xb_write, and
    1.42 +   block waiting for a reply.  The reply is malloced and should be
    1.43 +   freed by the caller. */
    1.44 +struct xsd_sockmsg *
    1.45 +xenbus_msg_reply(int type,
    1.46 +                 xenbus_transaction_t trans,
    1.47 +                 struct write_req *io,
    1.48 +                 int nr_reqs);
    1.49 +
    1.50  /* Removes the value associated with a path.  Returns a malloc'd error
    1.51     string on failure. */
    1.52  char *xenbus_rm(xenbus_transaction_t xbt, const char *path);
    1.53 @@ -52,4 +84,9 @@ char *xenbus_transaction_end(xenbus_tran
    1.54  /* Read path and parse it as an integer.  Returns -1 on error. */
    1.55  int xenbus_read_integer(char *path);
    1.56  
    1.57 +/* Contraction of snprintf and xenbus_write(path/node). */
    1.58 +char* xenbus_printf(xenbus_transaction_t xbt,
    1.59 +                                  char* node, char* path,
    1.60 +                                  char* fmt, ...);
    1.61 +
    1.62  #endif /* XENBUS_H__ */
     2.1 --- a/extras/mini-os/netfront.c	Thu Jan 17 15:18:38 2008 +0000
     2.2 +++ b/extras/mini-os/netfront.c	Thu Jan 17 15:20:02 2008 +0000
     2.3 @@ -27,20 +27,6 @@ struct net_info {
     2.4  } net_info;
     2.5  
     2.6  
     2.7 -char* xenbus_printf(xenbus_transaction_t xbt,
     2.8 -        char* node,char* path,
     2.9 -        char* fmt,unsigned int arg)
    2.10 -{
    2.11 -    char fullpath[256];
    2.12 -    char val[256];
    2.13 -
    2.14 -    sprintf(fullpath,"%s/%s",node,path);
    2.15 -    sprintf(val,fmt,arg);
    2.16 -    xenbus_write(xbt,fullpath,val);
    2.17 -
    2.18 -    return NULL;
    2.19 -}
    2.20 -
    2.21  
    2.22  #define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE)
    2.23  #define NET_RX_RING_SIZE __RING_SIZE((struct netif_rx_sring *)0, PAGE_SIZE)
     3.1 --- a/extras/mini-os/xenbus/xenbus.c	Thu Jan 17 15:18:38 2008 +0000
     3.2 +++ b/extras/mini-os/xenbus/xenbus.c	Thu Jan 17 15:20:02 2008 +0000
     3.3 @@ -43,7 +43,14 @@
     3.4  
     3.5  static struct xenstore_domain_interface *xenstore_buf;
     3.6  static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
     3.7 -static DECLARE_WAIT_QUEUE_HEAD(watch_queue);
     3.8 +DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue);
     3.9 +
    3.10 +struct xenbus_event *volatile xenbus_events;
    3.11 +static struct watch {
    3.12 +    char *token;
    3.13 +    struct xenbus_event *volatile *events;
    3.14 +    struct watch *next;
    3.15 +} *watches;
    3.16  struct xenbus_req_info 
    3.17  {
    3.18      int in_use:1;
    3.19 @@ -68,16 +75,27 @@ static void memcpy_from_ring(const void 
    3.20      memcpy(dest + c1, ring, c2);
    3.21  }
    3.22  
    3.23 -void wait_for_watch(void)
    3.24 +char **xenbus_wait_for_watch_return()
    3.25  {
    3.26 +    struct xenbus_event *event;
    3.27      DEFINE_WAIT(w);
    3.28 -    add_waiter(w,watch_queue);
    3.29 -    schedule();
    3.30 +    while (!(event = xenbus_events)) {
    3.31 +        add_waiter(w, xenbus_watch_queue);
    3.32 +        schedule();
    3.33 +    }
    3.34      remove_waiter(w);
    3.35 -    wake(current);
    3.36 +    xenbus_events = event->next;
    3.37 +    return &event->path;
    3.38  }
    3.39  
    3.40 -char* xenbus_wait_for_value(const char* path,const char* value)
    3.41 +void xenbus_wait_for_watch(void)
    3.42 +{
    3.43 +    char **ret;
    3.44 +    ret = xenbus_wait_for_watch_return();
    3.45 +    free(ret);
    3.46 +}
    3.47 +
    3.48 +char* xenbus_wait_for_value(const char* path, const char* value)
    3.49  {
    3.50      for(;;)
    3.51      {
    3.52 @@ -91,7 +109,7 @@ char* xenbus_wait_for_value(const char* 
    3.53          free(res);
    3.54  
    3.55          if(r==0) break;
    3.56 -        else wait_for_watch();
    3.57 +        else xenbus_wait_for_watch();
    3.58      }
    3.59      return NULL;
    3.60  }
    3.61 @@ -129,20 +147,32 @@ static void xenbus_thread_func(void *ign
    3.62  
    3.63              if(msg.type == XS_WATCH_EVENT)
    3.64              {
    3.65 -                char* payload = (char*)malloc(sizeof(msg) + msg.len);
    3.66 -                char *path,*token;
    3.67 +		struct xenbus_event *event = malloc(sizeof(*event) + msg.len),
    3.68 +                                    *volatile *events = NULL;
    3.69 +		char *data = (char*)event + sizeof(*event);
    3.70 +                struct watch *watch;
    3.71  
    3.72                  memcpy_from_ring(xenstore_buf->rsp,
    3.73 -                    payload,
    3.74 -                    MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
    3.75 -                    msg.len + sizeof(msg));
    3.76 +		    data,
    3.77 +                    MASK_XENSTORE_IDX(xenstore_buf->rsp_cons + sizeof(msg)),
    3.78 +                    msg.len);
    3.79  
    3.80 -                path = payload + sizeof(msg);
    3.81 -                token = path + strlen(path) + 1;
    3.82 +		event->path = data;
    3.83 +		event->token = event->path + strlen(event->path) + 1;
    3.84  
    3.85                  xenstore_buf->rsp_cons += msg.len + sizeof(msg);
    3.86 -                free(payload);
    3.87 -                wake_up(&watch_queue);
    3.88 +
    3.89 +                for (watch = watches; watch; watch = watch->next)
    3.90 +                    if (!strcmp(watch->token, event->token)) {
    3.91 +                        events = watch->events;
    3.92 +                        break;
    3.93 +                    }
    3.94 +                if (!events)
    3.95 +                    events = &xenbus_events;
    3.96 +
    3.97 +		event->next = *events;
    3.98 +		*events = event;
    3.99 +                wake_up(&xenbus_watch_queue);
   3.100              }
   3.101  
   3.102              else
   3.103 @@ -230,11 +260,6 @@ void init_xenbus(void)
   3.104      DEBUG("xenbus on irq %d\n", err);
   3.105  }
   3.106  
   3.107 -struct write_req {
   3.108 -    const void *data;
   3.109 -    unsigned len;
   3.110 -};
   3.111 -
   3.112  /* Send data to xenbus.  This can block.  All of the requests are seen
   3.113     by xenbus as if sent atomically.  The header is added
   3.114     automatically, using type %type, req_id %req_id, and trans_id
   3.115 @@ -316,7 +341,7 @@ static void xb_write(int type, int req_i
   3.116  /* Send a mesasge to xenbus, in the same fashion as xb_write, and
   3.117     block waiting for a reply.  The reply is malloced and should be
   3.118     freed by the caller. */
   3.119 -static struct xsd_sockmsg *
   3.120 +struct xsd_sockmsg *
   3.121  xenbus_msg_reply(int type,
   3.122  		 xenbus_transaction_t trans,
   3.123  		 struct write_req *io,
   3.124 @@ -437,18 +462,22 @@ char *xenbus_write(xenbus_transaction_t 
   3.125      return NULL;
   3.126  }
   3.127  
   3.128 -char* xenbus_watch_path( xenbus_transaction_t xbt, const char *path)
   3.129 +char* xenbus_watch_path_token( xenbus_transaction_t xbt, const char *path, const char *token, struct xenbus_event *volatile *events)
   3.130  {
   3.131 -	/* in the future one could have multiple watch queues, and use
   3.132 -	 * the token for demuxing. For now the token is 0. */
   3.133 -
   3.134      struct xsd_sockmsg *rep;
   3.135  
   3.136      struct write_req req[] = { 
   3.137          {path, strlen(path) + 1},
   3.138 -        {"0",2 },
   3.139 +	{token, strlen(token) + 1},
   3.140      };
   3.141  
   3.142 +    struct watch *watch = malloc(sizeof(*watch));
   3.143 +
   3.144 +    watch->token = strdup(token);
   3.145 +    watch->events = events;
   3.146 +    watch->next = watches;
   3.147 +    watches = watch;
   3.148 +
   3.149      rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
   3.150  
   3.151      char *msg = errmsg(rep);
   3.152 @@ -458,6 +487,34 @@ char* xenbus_watch_path( xenbus_transact
   3.153      return NULL;
   3.154  }
   3.155  
   3.156 +char* xenbus_unwatch_path_token( xenbus_transaction_t xbt, const char *path, const char *token)
   3.157 +{
   3.158 +    struct xsd_sockmsg *rep;
   3.159 +
   3.160 +    struct write_req req[] = { 
   3.161 +        {path, strlen(path) + 1},
   3.162 +	{token, strlen(token) + 1},
   3.163 +    };
   3.164 +
   3.165 +    struct watch *watch, **prev;
   3.166 +
   3.167 +    rep = xenbus_msg_reply(XS_UNWATCH, xbt, req, ARRAY_SIZE(req));
   3.168 +
   3.169 +    char *msg = errmsg(rep);
   3.170 +    if (msg) return msg;
   3.171 +    free(rep);
   3.172 +
   3.173 +    for (prev = &watches, watch = *prev; watch; prev = &watch->next, watch = *prev)
   3.174 +        if (!strcmp(watch->token, token)) {
   3.175 +            free(watch->token);
   3.176 +            *prev = watch->next;
   3.177 +            free(watch);
   3.178 +            break;
   3.179 +        }
   3.180 +
   3.181 +    return NULL;
   3.182 +}
   3.183 +
   3.184  char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
   3.185  {
   3.186      struct write_req req[] = { {path, strlen(path) + 1} };
   3.187 @@ -566,6 +623,25 @@ int xenbus_read_integer(char *path)
   3.188      return t;
   3.189  }
   3.190  
   3.191 +char* xenbus_printf(xenbus_transaction_t xbt,
   3.192 +                                  char* node, char* path,
   3.193 +                                  char* fmt, ...)
   3.194 +{
   3.195 +#define BUFFER_SIZE 256
   3.196 +    char fullpath[BUFFER_SIZE];
   3.197 +    char val[BUFFER_SIZE];
   3.198 +    va_list args;
   3.199 +
   3.200 +    BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
   3.201 +    sprintf(fullpath,"%s/%s", node, path);
   3.202 +    va_start(args, fmt);
   3.203 +    vsprintf(val, fmt, args);
   3.204 +    va_end(args);
   3.205 +    xenbus_write(xbt,fullpath,val);
   3.206 +
   3.207 +    return NULL;
   3.208 +}
   3.209 +
   3.210  static void do_ls_test(const char *pre)
   3.211  {
   3.212      char **dirs;