From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756004Ab1IPTGQ (ORCPT ); Fri, 16 Sep 2011 15:06:16 -0400 Received: from acsinet15.oracle.com ([141.146.126.227]:64865 "EHLO acsinet15.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753832Ab1IPTGM (ORCPT ); Fri, 16 Sep 2011 15:06:12 -0400 Date: Fri, 16 Sep 2011 15:06:01 -0400 From: Konrad Rzeszutek Wilk To: xen-devel@lists.xensource.com, JBeulich@suse.com Cc: linux-kernel@vger.kernel.org Subject: [PATCH] xen/pciback: Use mutexes when working with Xenbus state transitions. Message-ID: <20110916190601.GA31796@phenom.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Source-IP: acsinet22.oracle.com [141.146.126.238] X-Auth-Type: Internal IP X-CT-RefId: str=0001.0A090205.4E739E20.00BA:SCFMA922111,ss=1,re=-4.000,fgs=0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The caller that orchestrates the state changes is xenwatch_thread and it takes a mutex. In our processing of Xenbus states we can take the luxery of going to sleep on a mutex, so lets do that and also fix this bug: BUG: sleeping function called from invalid context at /linux/kernel/mutex.c:271 in_atomic(): 1, irqs_disabled(): 0, pid: 32, name: xenwatch 2 locks held by xenwatch/32: #0: (xenwatch_mutex){......}, at: [] xenwatch_thread+0x4b/0x180 #1: (&(&pdev->dev_lock)->rlock){......}, at: [] xen_pcibk_disconnect+0x1b/0x80 Pid: 32, comm: xenwatch Not tainted 3.1.0-rc6-00015-g3ce340d #2 Call Trace: [] __might_sleep+0x102/0x130 [] mutex_lock_nested+0x2f/0x50 [] unbind_from_irq+0x2c/0x1b0 [] ? free_irq+0x56/0xb0 [] unbind_from_irqhandler+0x1c/0x30 [] xen_pcibk_disconnect+0x2b/0x80 [] xen_pcibk_frontend_changed+0xe8/0x140 [] xenbus_otherend_changed+0xd2/0x150 [] ? get_parent_ip+0x11/0x50 [] frontend_changed+0x10/0x20 [] xenwatch_thread+0xb2/0x180 Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xen-pciback/pciback.h | 2 +- drivers/xen/xen-pciback/xenbus.c | 16 +++++----------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index a0e131a..c3af628 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h @@ -27,7 +27,7 @@ struct pci_dev_entry { struct xen_pcibk_device { void *pci_dev_data; - spinlock_t dev_lock; + struct mutex dev_lock; struct xenbus_device *xdev; struct xenbus_watch be_watch; u8 be_watching; diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index 978d2c6..c057d67 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c @@ -44,7 +44,7 @@ static struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev) pdev->xdev = xdev; dev_set_drvdata(&xdev->dev, pdev); - spin_lock_init(&pdev->dev_lock); + mutex_init(&pdev->dev_lock); pdev->sh_info = NULL; pdev->evtchn_irq = INVALID_EVTCHN_IRQ; @@ -62,14 +62,13 @@ out: static void xen_pcibk_disconnect(struct xen_pcibk_device *pdev) { - spin_lock(&pdev->dev_lock); + mutex_lock(&pdev->dev_lock); /* Ensure the guest can't trigger our handler before removing devices */ if (pdev->evtchn_irq != INVALID_EVTCHN_IRQ) { unbind_from_irqhandler(pdev->evtchn_irq, pdev); pdev->evtchn_irq = INVALID_EVTCHN_IRQ; } - spin_unlock(&pdev->dev_lock); /* If the driver domain started an op, make sure we complete it * before releasing the shared memory */ @@ -77,13 +76,11 @@ static void xen_pcibk_disconnect(struct xen_pcibk_device *pdev) /* Note, the workqueue does not use spinlocks at all.*/ flush_workqueue(xen_pcibk_wq); - spin_lock(&pdev->dev_lock); if (pdev->sh_info != NULL) { xenbus_unmap_ring_vfree(pdev->xdev, pdev->sh_info); pdev->sh_info = NULL; } - spin_unlock(&pdev->dev_lock); - + mutex_unlock(&pdev->dev_lock); } static void free_pdev(struct xen_pcibk_device *pdev) @@ -120,9 +117,8 @@ static int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref, goto out; } - spin_lock(&pdev->dev_lock); + mutex_lock(&pdev->dev_lock); pdev->sh_info = vaddr; - spin_unlock(&pdev->dev_lock); err = bind_interdomain_evtchn_to_irqhandler( pdev->xdev->otherend_id, remote_evtchn, xen_pcibk_handle_event, @@ -132,14 +128,12 @@ static int xen_pcibk_do_attach(struct xen_pcibk_device *pdev, int gnt_ref, "Error binding event channel to IRQ"); goto out; } - - spin_lock(&pdev->dev_lock); pdev->evtchn_irq = err; - spin_unlock(&pdev->dev_lock); err = 0; dev_dbg(&pdev->xdev->dev, "Attached!\n"); out: + mutex_unlock(&pdev->dev_lock); return err; } -- 1.7.4.1