[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 08/11] mini-os/xenbus: Expose lower-level interface



Ian Jackson, le Fri 20 Jun 2014 20:04:47 +0100, a écrit :
> Provide an interface that allows a xenbus user to explicitly allocate
> ids, deal with responses asynchronously, specify the queues to be used
> for responses and watches, etc.
> 
> More specifically:
> 
> * Enhance xenbus_event to be capable of dealing with both watches and
>   command replies.  In particular, arrange that it will contain a
>   pointer to the watch.  We leave the old fields undisturbed because
>   of the way that this struct is already used in various places.
> 
> * Provide that a xenbus_event for a command response contains a copy
>   of the pointer to the reply message, rather than putting it in the
>   req_info (which is visible only internally).
> 
> * Rename `struct watch' to `struct xenbus_watch' because it needs
>   to be in the public interface.
> 
> * allocate_xenbus_id becomes xenbus_id_allocate; same for release.
> 
> * Make xb_write into a public function, xenbus_xb_write.
> 
> Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>

Acked-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>

> ---
>  include/mini-os/xenbus.h |   74 
> +++++++++++++++++++++++++++++++++++++++++++---
>  xen/xenbus/xenbus.c      |   66 +++++++++++++++++++++++++----------------
>  2 files changed, 110 insertions(+), 30 deletions(-)
> 
> diff --git a/include/mini-os/xenbus.h b/include/mini-os/xenbus.h
> index 7e70de0..b8d152d 100644
> --- a/include/mini-os/xenbus.h
> +++ b/include/mini-os/xenbus.h
> @@ -23,11 +23,18 @@ static inline void init_xenbus(void)
>     set to a malloc'd copy of the value. */
>  char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
>  
> -/* Watch event queue */
> +/* Queue for events (watches or async request replies - see below) */
>  struct xenbus_event {
> -    /* Keep these two as this for xs.c */
> -    char *path;
> -    char *token;
> +    union {
> +        struct {
> +            /* must be first, both for the bare minios xs.c, and for
> +             * xenbus_wait_for_watch's handling */
> +            char *path;
> +            char *token;
> +        };
> +        struct xsd_sockmsg *reply;
> +    };
> +    struct xenbus_watch *watch;
>      MINIOS_STAILQ_ENTRY(xenbus_event) entry;
>  };
>  struct xenbus_event_queue {
> @@ -111,6 +118,65 @@ char* xenbus_printf(xenbus_transaction_t xbt,
>  /* Utility function to figure out our domain id */
>  domid_t xenbus_get_self_id(void);
>  
> +/*
> + * ----- asynchronous low-level interface -----
> + */
> +
> +/* Allocate an identifier for a xenbus request.  Blocks if none are
> + * available.  Cannot fail.  On return, we may use the returned value
> + * as the id in a xenbus request.
> + *
> + * for_queue must already be allocated, but may be uninitialised.
> + *
> + * for_queue->watch is not touched by the xenbus machinery for
> + * handling requests/replies but should probably be initialised by the
> + * caller (probably to NULL) because this will help the caller
> + * distinguish the reply from any watch events which might end up in
> + * the same queue.
> + *
> + * reply_queue must exist and have been initialised.
> + *
> + * When the response arrives, the reply message will stored in
> + * for_queue->reply and for_queue will be queued on reply_queue.  The
> + * id must be then explicitly released (or, used again, if desired).
> + * After ->reply is done with the caller must pass it to free().
> + * (Do not use the id for more than one request at a time.) */
> +int xenbus_id_allocate(struct xenbus_event_queue *reply_queue,
> +                       struct xenbus_event *for_queue);
> +void xenbus_id_release(int id);
> +
> +/* Allocating a token for a watch.
> + *
> + * To use this:
> + *  - Include struct xenbus_watch in your own struct.
> + *  - Set events; then call prepare.  This will set token.
> + *    You may then use token in a WATCH request.
> + *  - You must UNWATCH before you call release.
> + * Do not modify token yourself.
> + * entry is private for the xenbus driver.
> + *
> + * When the watch fires, a new struct xenbus_event will be allocated
> + * and queued on events.  The field xenbus_event->watch will have been
> + * set to watch by the xenbus machinery, and xenbus_event->path will
> + * be the watch path.  After the caller is done with the event,
> + * its pointer should simply be passed to free(). */
> +struct xenbus_watch {
> +    char *token;
> +    struct xenbus_event_queue *events;
> +    MINIOS_LIST_ENTRY(xenbus_watch) entry;
> +};
> +void xenbus_watch_init(struct xenbus_watch *watch); /* makes release a noop 
> */
> +void xenbus_watch_prepare(struct xenbus_watch *watch); /* need not be init'd 
> */
> +void xenbus_watch_release(struct xenbus_watch *watch); /* idempotent */
> +
> +
> +/* Send data to xenbus.  This can block.  All of the requests are seen
> + * by xenbus as if sent atomically.  The header is added
> + * automatically, using type %type, req_id %req_id, and trans_id
> + * %trans_id. */
> +void xenbus_xb_write(int type, int req_id, xenbus_transaction_t trans_id,
> +                  const struct write_req *req, int nr_reqs);
> +
>  #ifdef CONFIG_XENBUS
>  /* Reset the XenBus system. */
>  void fini_xenbus(void);
> diff --git a/xen/xenbus/xenbus.c b/xen/xenbus/xenbus.c
> index d2e59b3..bf4bb45 100644
> --- a/xen/xenbus/xenbus.c
> +++ b/xen/xenbus/xenbus.c
> @@ -48,17 +48,11 @@ static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
>  static spinlock_t xb_lock = SPIN_LOCK_UNLOCKED; /* protects xenbus req ring 
> */
>  
>  struct xenbus_event_queue xenbus_default_watch_queue;
> -struct watch {
> -    char *token;
> -    struct xenbus_event_queue *events;
> -    MINIOS_LIST_ENTRY(watch) entry;
> -};
> -static MINIOS_LIST_HEAD(, watch) watches;
> +static MINIOS_LIST_HEAD(, xenbus_watch) watches;
>  struct xenbus_req_info 
>  {
>      struct xenbus_event_queue *reply_queue; /* non-0 iff in use */
>      struct xenbus_event *for_queue;
> -    void *reply;
>  };
>  
>  
> @@ -263,7 +257,7 @@ static void xenbus_thread_func(void *ign)
>               struct xenbus_event *event = malloc(sizeof(*event) + msg.len);
>                  struct xenbus_event_queue *events = NULL;
>               char *data = (char*)event + sizeof(*event);
> -                struct watch *watch;
> +                struct xenbus_watch *watch;
>  
>                  memcpy_from_ring(xenstore_buf->rsp,
>                   data,
> @@ -277,6 +271,7 @@ static void xenbus_thread_func(void *ign)
>  
>                  MINIOS_LIST_FOREACH(watch, &watches, entry)
>                      if (!strcmp(watch->token, event->token)) {
> +                        event->watch = watch;
>                          events = watch->events;
>                          break;
>                      }
> @@ -291,9 +286,10 @@ static void xenbus_thread_func(void *ign)
>  
>              else
>              {
> -                req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
> +                req_info[msg.req_id].for_queue->reply =
> +                    malloc(sizeof(msg) + msg.len);
>                  memcpy_from_ring(xenstore_buf->rsp,
> -                    req_info[msg.req_id].reply,
> +                    req_info[msg.req_id].for_queue->reply,
>                      MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
>                      msg.len + sizeof(msg));
>                  xenstore_buf->rsp_cons += msg.len + sizeof(msg);
> @@ -315,7 +311,7 @@ static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
>  static DECLARE_WAIT_QUEUE_HEAD(req_wq);
>  
>  /* Release a xenbus identifier */
> -static void release_xenbus_id(int id)
> +void xenbus_id_release(int id)
>  {
>      BUG_ON(!req_info[id].reply_queue);
>      spin_lock(&req_lock);
> @@ -326,10 +322,8 @@ static void release_xenbus_id(int id)
>      spin_unlock(&req_lock);
>  }
>  
> -/* Allocate an identifier for a xenbus request.  Blocks if none are
> -   available. */
> -static int allocate_xenbus_id(struct xenbus_event_queue *reply_queue,
> -                              struct xenbus_event *for_queue)
> +int xenbus_id_allocate(struct xenbus_event_queue *reply_queue,
> +                       struct xenbus_event *for_queue)
>  {
>      static int probe;
>      int o_probe;
> @@ -360,6 +354,30 @@ static int allocate_xenbus_id(struct xenbus_event_queue 
> *reply_queue,
>      return o_probe;
>  }
>  
> +void xenbus_watch_init(struct xenbus_watch *watch)
> +{
> +    watch->token = 0;
> +}
> +
> +void xenbus_watch_prepare(struct xenbus_watch *watch)
> +{
> +    BUG_ON(!watch->events);
> +    size_t size = sizeof(void*)*2 + 5;
> +    watch->token = malloc(size);
> +    int r = snprintf(watch->token,size,"*%p",(void*)watch);
> +    BUG_ON(!(r > 0 && r < size));
> +    MINIOS_LIST_INSERT_HEAD(&watches, watch, entry);
> +}
> +
> +void xenbus_watch_release(struct xenbus_watch *watch)
> +{
> +    if (!watch->token)
> +        return;
> +    MINIOS_LIST_REMOVE(watch, entry);
> +    free(watch->token);
> +    watch->token = 0;
> +}
> +
>  /* Initialise xenbus. */
>  void init_xenbus(void)
>  {
> @@ -381,11 +399,7 @@ void fini_xenbus(void)
>  {
>  }
>  
> -/* Send data to xenbus.  This can block.  All of the requests are seen
> -   by xenbus as if sent atomically.  The header is added
> -   automatically, using type %type, req_id %req_id, and trans_id
> -   %trans_id. */
> -static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
> +void xenbus_xb_write(int type, int req_id, xenbus_transaction_t trans_id,
>                    const struct write_req *req, int nr_reqs)
>  {
>      XENSTORE_RING_IDX prod;
> @@ -480,16 +494,16 @@ xenbus_msg_reply(int type,
>  
>      xenbus_event_queue_init(&queue);
>  
> -    id = allocate_xenbus_id(&queue,&event_buf);
> +    id = xenbus_id_allocate(&queue,&event_buf);
>  
> -    xb_write(type, id, trans, io, nr_reqs);
> +    xenbus_xb_write(type, id, trans, io, nr_reqs);
>  
>      struct xenbus_event *event = await_event(&queue);
>      BUG_ON(event != &event_buf);
>  
> -    rep = req_info[id].reply;
> +    rep = req_info[id].for_queue->reply;
>      BUG_ON(rep->req_id != id);
> -    release_xenbus_id(id);
> +    xenbus_id_release(id);
>      return rep;
>  }
>  
> @@ -600,7 +614,7 @@ char* xenbus_watch_path_token( xenbus_transaction_t xbt, 
> const char *path, const
>       {token, strlen(token) + 1},
>      };
>  
> -    struct watch *watch = malloc(sizeof(*watch));
> +    struct xenbus_watch *watch = malloc(sizeof(*watch));
>  
>      char *msg;
>  
> @@ -630,7 +644,7 @@ char* xenbus_unwatch_path_token( xenbus_transaction_t 
> xbt, const char *path, con
>       {token, strlen(token) + 1},
>      };
>  
> -    struct watch *watch;
> +    struct xenbus_watch *watch;
>  
>      char *msg;
>  
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel
> 

-- 
Samuel
As usual, this being a 1.3.x release, I haven't even compiled this
kernel yet.  So if it works, you should be doubly impressed.
(Linus Torvalds, announcing kernel 1.3.3 on the linux-kernel mailing list.)

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.