|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 09/11] mini-os/xenbus: Sort out request and watch locking
Ian Jackson, le Fri 20 Jun 2014 20:04:48 +0100, a écrit :
> Make the xenbus_req_lock public, and lock it everywhere it is needed.
> It needs to protect not just the xenbus request ring itself, but also
> a number of internal data structures.
>
> Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Acked-by: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>
> ---
> include/mini-os/xenbus.h | 7 +++++++
> xen/xenbus/xenbus.c | 42 ++++++++++++++++++++++++++++++++++++------
> 2 files changed, 43 insertions(+), 6 deletions(-)
>
> diff --git a/include/mini-os/xenbus.h b/include/mini-os/xenbus.h
> index b8d152d..a811c19 100644
> --- a/include/mini-os/xenbus.h
> +++ b/include/mini-os/xenbus.h
> @@ -5,6 +5,7 @@
> #include <mini-os/sched.h>
> #include <mini-os/waittypes.h>
> #include <mini-os/queue.h>
> +#include <mini-os/spinlock.h>
>
> typedef unsigned long xenbus_transaction_t;
> #define XBT_NIL ((xenbus_transaction_t)0)
> @@ -23,6 +24,12 @@ 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);
>
> +/* All accesses to an active xenbus_event_queue must occur with this
> + * lock held. The public functions here will do that for you, but
> + * your own accesses to the queue (including the contained waitq)
> + * must be protected by the lock. */
> +extern spinlock_t xenbus_req_lock;
> +
> /* Queue for events (watches or async request replies - see below) */
> struct xenbus_event {
> union {
> diff --git a/xen/xenbus/xenbus.c b/xen/xenbus/xenbus.c
> index bf4bb45..7b391c5 100644
> --- a/xen/xenbus/xenbus.c
> +++ b/xen/xenbus/xenbus.c
> @@ -56,6 +56,17 @@ struct xenbus_req_info
> };
>
>
> +spinlock_t xenbus_req_lock = SPIN_LOCK_UNLOCKED;
> +/*
> + * This lock protects:
> + * the xenbus request ring
> + * req_info[]
> + * all live struct xenbus_event_queue (including
> xenbus_default_watch_queue)
> + * nr_live_reqs
> + * req_wq
> + * watches
> + */
> +
> void xenbus_event_queue_init(struct xenbus_event_queue *queue)
> {
> MINIOS_STAILQ_INIT(&queue->events);
> @@ -64,6 +75,7 @@ void xenbus_event_queue_init(struct xenbus_event_queue
> *queue)
>
> static struct xenbus_event *remove_event(struct xenbus_event_queue *queue)
> {
> + /* Called with lock held */
> struct xenbus_event *event;
>
> event = MINIOS_STAILQ_FIRST(&queue->events);
> @@ -78,6 +90,7 @@ static struct xenbus_event *remove_event(struct
> xenbus_event_queue *queue)
> static void queue_event(struct xenbus_event_queue *queue,
> struct xenbus_event *event)
> {
> + /* Called with lock held */
> MINIOS_STAILQ_INSERT_TAIL(&queue->events, event, entry);
> wake_up(&queue->waitq);
> }
> @@ -86,11 +99,15 @@ static struct xenbus_event *await_event(struct
> xenbus_event_queue *queue)
> {
> struct xenbus_event *event;
> DEFINE_WAIT(w);
> + spin_lock(&xenbus_req_lock);
> while (!(event = remove_event(queue))) {
> add_waiter(w, queue->waitq);
> + spin_unlock(&xenbus_req_lock);
> schedule();
> + spin_lock(&xenbus_req_lock);
> }
> remove_waiter(w, queue->waitq);
> + spin_unlock(&xenbus_req_lock);
> return event;
> }
>
> @@ -269,6 +286,8 @@ static void xenbus_thread_func(void *ign)
>
> xenstore_buf->rsp_cons += msg.len + sizeof(msg);
>
> + spin_lock(&xenbus_req_lock);
> +
> MINIOS_LIST_FOREACH(watch, &watches, entry)
> if (!strcmp(watch->token, event->token)) {
> event->watch = watch;
> @@ -282,6 +301,8 @@ static void xenbus_thread_func(void *ign)
> printk("unexpected watch token %s\n", event->token);
> free(event);
> }
> +
> + spin_unlock(&xenbus_req_lock);
> }
>
> else
> @@ -293,8 +314,10 @@ static void xenbus_thread_func(void *ign)
> MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
> msg.len + sizeof(msg));
> xenstore_buf->rsp_cons += msg.len + sizeof(msg);
> + spin_lock(&xenbus_req_lock);
> queue_event(req_info[msg.req_id].reply_queue,
> req_info[msg.req_id].for_queue);
> + spin_unlock(&xenbus_req_lock);
> }
> }
> }
> @@ -307,19 +330,18 @@ static void xenbus_evtchn_handler(evtchn_port_t port,
> struct pt_regs *regs,
> }
>
> static int nr_live_reqs;
> -static spinlock_t req_lock = SPIN_LOCK_UNLOCKED;
> static DECLARE_WAIT_QUEUE_HEAD(req_wq);
>
> /* Release a xenbus identifier */
> void xenbus_id_release(int id)
> {
> BUG_ON(!req_info[id].reply_queue);
> - spin_lock(&req_lock);
> + spin_lock(&xenbus_req_lock);
> req_info[id].reply_queue = 0;
> nr_live_reqs--;
> if (nr_live_reqs == NR_REQS - 1)
> wake_up(&req_wq);
> - spin_unlock(&req_lock);
> + spin_unlock(&xenbus_req_lock);
> }
>
> int xenbus_id_allocate(struct xenbus_event_queue *reply_queue,
> @@ -330,10 +352,10 @@ int xenbus_id_allocate(struct xenbus_event_queue
> *reply_queue,
>
> while (1)
> {
> - spin_lock(&req_lock);
> + spin_lock(&xenbus_req_lock);
> if (nr_live_reqs < NR_REQS)
> break;
> - spin_unlock(&req_lock);
> + spin_unlock(&xenbus_req_lock);
> wait_event(req_wq, (nr_live_reqs < NR_REQS));
> }
>
> @@ -349,7 +371,7 @@ int xenbus_id_allocate(struct xenbus_event_queue
> *reply_queue,
> req_info[o_probe].reply_queue = reply_queue;
> req_info[o_probe].for_queue = for_queue;
> probe = (o_probe + 1) % NR_REQS;
> - spin_unlock(&req_lock);
> + spin_unlock(&xenbus_req_lock);
>
> return o_probe;
> }
> @@ -366,14 +388,18 @@ void xenbus_watch_prepare(struct xenbus_watch *watch)
> watch->token = malloc(size);
> int r = snprintf(watch->token,size,"*%p",(void*)watch);
> BUG_ON(!(r > 0 && r < size));
> + spin_lock(&xenbus_req_lock);
> MINIOS_LIST_INSERT_HEAD(&watches, watch, entry);
> + spin_unlock(&xenbus_req_lock);
> }
>
> void xenbus_watch_release(struct xenbus_watch *watch)
> {
> if (!watch->token)
> return;
> + spin_lock(&xenbus_req_lock);
> MINIOS_LIST_REMOVE(watch, entry);
> + spin_unlock(&xenbus_req_lock);
> free(watch->token);
> watch->token = 0;
> }
> @@ -624,7 +650,9 @@ char* xenbus_watch_path_token( xenbus_transaction_t xbt,
> const char *path, const
> watch->token = strdup(token);
> watch->events = events;
>
> + spin_lock(&xenbus_req_lock);
> MINIOS_LIST_INSERT_HEAD(&watches, watch, entry);
> + spin_unlock(&xenbus_req_lock);
>
> rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
>
> @@ -654,6 +682,7 @@ char* xenbus_unwatch_path_token( xenbus_transaction_t
> xbt, const char *path, con
> if (msg) return msg;
> free(rep);
>
> + spin_lock(&xenbus_req_lock);
> MINIOS_LIST_FOREACH(watch, &watches, entry)
> if (!strcmp(watch->token, token)) {
> free(watch->token);
> @@ -661,6 +690,7 @@ char* xenbus_unwatch_path_token( xenbus_transaction_t
> xbt, const char *path, con
> free(watch);
> break;
> }
> + spin_unlock(&xenbus_req_lock);
>
> return NULL;
> }
> --
> 1.7.10.4
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel
>
--
Samuel
<g> r: et la marmotte, elle écrit un papier IPDPS
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |