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

[Xen-devel] [GIT] Re: [PATCH] xenbus: do not hold transaction_mutex when returning to userspace



On Tue, 2009-03-24 at 13:44 -0400, Ian Campbell wrote:
> ================================================
>   [ BUG: lock held when returning to user space! ]
>   ------------------------------------------------
>   xenstore-list/3522 is leaving the kernel with locks still held!
>   1 lock held by xenstore-list/3522:
>    #0:  (&xs_state.transaction_mutex){......}, at: [<c026dc6f>] 
> xenbus_dev_request_and_reply+0x8f/0xa0

I'm still seeing these with xen-tip/master, I guess the patch got
dropped somewhere along the way? 

The following changes since commit 4c2f7369e095df4c0a9b5c4cd05926f68cc701dd:
  Jeremy Fitzhardinge (1):
        Merge branch 'xen-tip/core' into xen-tip/master

are available in the git repository at:

  git://xenbits.xensource.com/people/ianc/linux-2.6.git for-jeremy/xenbus

Ian Campbell (1):
      xenbus: do not hold transaction_mutex when returning to userspace

 drivers/xen/xenbus/xenbus_xs.c |   57 +++++++++++++++++++++++++++++++++-------
 1 files changed, 47 insertions(+), 10 deletions(-)


> 
> The canonical fix for this type of issue appears to be to maintain a
> count manually rather than using an rwsem so do that here.
> 
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
>  drivers/xen/xenbus/xenbus_xs.c |   57 
> +++++++++++++++++++++++++++++++++-------
>  1 files changed, 47 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
> index eab33f1..6f91e8c 100644
> --- a/drivers/xen/xenbus/xenbus_xs.c
> +++ b/drivers/xen/xenbus/xenbus_xs.c
> @@ -76,6 +76,14 @@ struct xs_handle {
>       /*
>        * Mutex ordering: transaction_mutex -> watch_mutex -> request_mutex.
>        * response_mutex is never taken simultaneously with the other three.
> +      *
> +      * transaction_mutex must be held before incrementing
> +      * transaction_count. The mutex is held when a suspend is in
> +      * progress to prevent new transactions starting.
> +      *
> +      * When decrementing transaction_count to zero the wait queue
> +      * should be woken up, the suspend code waits for count to
> +      * reach zero.
>        */
>  
>       /* One request at a time. */
> @@ -85,7 +93,9 @@ struct xs_handle {
>       struct mutex response_mutex;
>  
>       /* Protect transactions against save/restore. */
> -     struct rw_semaphore transaction_mutex;
> +     struct mutex transaction_mutex;
> +     atomic_t transaction_count;
> +     wait_queue_head_t transaction_wq;
>  
>       /* Protect watch (de)register against save/restore. */
>       struct rw_semaphore watch_mutex;
> @@ -157,6 +167,31 @@ static void *read_reply(enum xsd_sockmsg_type *type, 
> unsigned int *len)
>       return body;
>  }
>  
> +static void transaction_start(void)
> +{
> +     mutex_lock(&xs_state.transaction_mutex);
> +     atomic_inc(&xs_state.transaction_count);
> +     mutex_unlock(&xs_state.transaction_mutex);
> +}
> +
> +static void transaction_end(void)
> +{
> +     if (atomic_dec_and_test(&xs_state.transaction_count))
> +             wake_up(&xs_state.transaction_wq);
> +}
> +
> +static void transaction_suspend(void)
> +{
> +     mutex_lock(&xs_state.transaction_mutex);
> +     wait_event(xs_state.transaction_wq,
> +                atomic_read(&xs_state.transaction_count) == 0);
> +}
> +
> +static void transaction_resume(void)
> +{
> +     mutex_unlock(&xs_state.transaction_mutex);
> +}
> +
>  void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
>  {
>       void *ret;
> @@ -164,7 +199,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg 
> *msg)
>       int err;
>  
>       if (req_msg.type == XS_TRANSACTION_START)
> -             down_read(&xs_state.transaction_mutex);
> +             transaction_start();
>  
>       mutex_lock(&xs_state.request_mutex);
>  
> @@ -180,7 +215,7 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg 
> *msg)
>       if ((msg->type == XS_TRANSACTION_END) ||
>           ((req_msg.type == XS_TRANSACTION_START) &&
>            (msg->type == XS_ERROR)))
> -             up_read(&xs_state.transaction_mutex);
> +             transaction_end();
>  
>       return ret;
>  }
> @@ -432,11 +467,11 @@ int xenbus_transaction_start(struct xenbus_transaction 
> *t)
>  {
>       char *id_str;
>  
> -     down_read(&xs_state.transaction_mutex);
> +     transaction_start();
>  
>       id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL);
>       if (IS_ERR(id_str)) {
> -             up_read(&xs_state.transaction_mutex);
> +             transaction_end();
>               return PTR_ERR(id_str);
>       }
>  
> @@ -461,7 +496,7 @@ int xenbus_transaction_end(struct xenbus_transaction t, 
> int abort)
>  
>       err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
>  
> -     up_read(&xs_state.transaction_mutex);
> +     transaction_end();
>  
>       return err;
>  }
> @@ -662,7 +697,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watch);
>  
>  void xs_suspend(void)
>  {
> -     down_write(&xs_state.transaction_mutex);
> +     transaction_suspend();
>       down_write(&xs_state.watch_mutex);
>       mutex_lock(&xs_state.request_mutex);
>       mutex_lock(&xs_state.response_mutex);
> @@ -677,7 +712,7 @@ void xs_resume(void)
>  
>       mutex_unlock(&xs_state.response_mutex);
>       mutex_unlock(&xs_state.request_mutex);
> -     up_write(&xs_state.transaction_mutex);
> +     transaction_resume();
>  
>       /* No need for watches_lock: the watch_mutex is sufficient. */
>       list_for_each_entry(watch, &watches, list) {
> @@ -693,7 +728,7 @@ void xs_suspend_cancel(void)
>       mutex_unlock(&xs_state.response_mutex);
>       mutex_unlock(&xs_state.request_mutex);
>       up_write(&xs_state.watch_mutex);
> -     up_write(&xs_state.transaction_mutex);
> +     mutex_unlock(&xs_state.transaction_mutex);
>  }
>  
>  static int xenwatch_thread(void *unused)
> @@ -843,8 +878,10 @@ int xs_init(void)
>  
>       mutex_init(&xs_state.request_mutex);
>       mutex_init(&xs_state.response_mutex);
> -     init_rwsem(&xs_state.transaction_mutex);
> +     mutex_init(&xs_state.transaction_mutex);
>       init_rwsem(&xs_state.watch_mutex);
> +     atomic_set(&xs_state.transaction_count, 0);
> +     init_waitqueue_head(&xs_state.transaction_wq);
>  
>       /* Initialize the shared memory rings to talk to xenstored */
>       err = xb_init_comms();


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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