lkml.org 
[lkml]   [2013]   [Nov]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subjectmm/dmapool.c: possible circular locking dependency detected
During pci hotplug tests I received this one:

[ 34.735836] ======================================================
[ 34.735838] [ INFO: possible circular locking dependency detected ]
[ 34.735840] 3.12.0-01915-g6c86ae2-dirty #125 Not tainted
[ 34.735842] -------------------------------------------------------
[ 34.735843] kworker/u128:3/49 is trying to acquire lock:
[ 34.735845] (s_active#27){++++.+}, at: [<00000000003048c2>] sysfs_addrm_finish+0x52/0x8c
[ 34.735854]
[ 34.735854] but task is already holding lock:
[ 34.735856] (pools_lock){+.+.+.}, at: [<0000000000262e22>] dma_pool_destroy+0x32/0x1a4
[ 34.735862]
[ 34.735862] which lock already depends on the new lock.
[ 34.735862]
[ 34.735864]
[ 34.735864] the existing dependency chain (in reverse order) is:
[ 34.735866]
[ 34.735866] -> #1 (pools_lock){+.+.+.}:
[ 34.735869] [<00000000001aa4c0>] __lock_acquire+0xf24/0x1698
[ 34.735874] [<00000000001ab360>] lock_acquire+0xb8/0x1f8
[ 34.735876] [<0000000000610a66>] mutex_lock_nested+0x7a/0x3a4
[ 34.735880] [<0000000000262cfa>] show_pools+0x5a/0x150
[ 34.735883] [<0000000000476e80>] dev_attr_show+0x38/0x78
[ 34.735886] [<00000000003027f8>] sysfs_seq_show+0x108/0x1b4
[ 34.735888] [<00000000002a3f46>] seq_read+0x136/0x550
[ 34.735891] [<0000000000279c9e>] vfs_read+0x8e/0x160
[ 34.735894] [<0000000000279f6a>] SyS_read+0x5e/0xb0
[ 34.735896] [<00000000006158ec>] sysc_nr_ok+0x22/0x28
[ 34.735900] [<0000004963071e98>] 0x4963071e98
[ 34.735902]
[ 34.735902] -> #0 (s_active#27){++++.+}:
[ 34.735906] [<00000000001a68f8>] check_prev_add+0x748/0x74c
[ 34.735908] [<00000000001aa4c0>] __lock_acquire+0xf24/0x1698
[ 34.735910] [<00000000001ab360>] lock_acquire+0xb8/0x1f8
[ 34.735913] [<0000000000303bf4>] sysfs_deactivate+0xa4/0x124
[ 34.735915] [<00000000003048c2>] sysfs_addrm_finish+0x52/0x8c
[ 34.735917] [<0000000000304ea6>] sysfs_hash_and_remove+0x66/0xb0
[ 34.735919] [<0000000000262f70>] dma_pool_destroy+0x180/0x1a4
[ 34.735922] [<000003ff805cc0b2>] mlx4_cmd_cleanup+0x2e/0xa0 [mlx4_core]
[ 34.735938] [<000003ff805d7e58>] mlx4_remove_one+0x170/0x34c [mlx4_core]
[ 34.735947] [<00000000004425be>] pci_device_remove+0x42/0x7c
[ 34.735950] [<000000000047ad96>] __device_release_driver+0x6e/0xe0
[ 34.735953] [<000000000047ae46>] device_release_driver+0x3e/0x50
[ 34.735956] [<000000000047a7a0>] bus_remove_device+0x128/0x198
[ 34.735958] [<000000000047771c>] device_del+0x13c/0x1c8
[ 34.735960] [<000000000043bd40>] pci_stop_bus_device+0xb4/0xd8
[ 34.735963] [<000000000043beec>] pci_stop_and_remove_bus_device+0x28/0x38
[ 34.735965] [<000000000044410e>] remove_callback+0x3e/0x50
[ 34.735968] [<00000000003028d4>] sysfs_schedule_callback_work+0x30/0x84
[ 34.735970] [<000000000014eea8>] process_one_work+0x200/0x614
[ 34.735975] [<0000000000150674>] worker_thread+0x11c/0x308
[ 34.735977] [<000000000015903a>] kthread+0xd2/0xdc
[ 34.735981] [<0000000000615a72>] kernel_thread_starter+0x6/0xc
[ 34.735983] [<0000000000615a6c>] kernel_thread_starter+0x0/0xc
[ 34.735986]
[ 34.735986] other info that might help us debug this:
[ 34.735986]
[ 34.736001] Possible unsafe locking scenario:
[ 34.736001]
[ 34.736003] CPU0 CPU1
[ 34.736005] ---- ----
[ 34.736006] lock(pools_lock);
[ 34.736008] lock(s_active#27);
[ 34.736010] lock(pools_lock);
[ 34.736013] lock(s_active#27);
[ 34.736015]
[ 34.736015] *** DEADLOCK ***
[ 34.736015]
[ 34.736018] 5 locks held by kworker/u128:3/49:
[ 34.736020] #0: (%s#5){.+.+.+}, at: [<000000000014ee22>] process_one_work+0x17a/0x614
[ 34.736025] #1: ((&ss->work)){+.+.+.}, at: [<000000000014ee22>] process_one_work+0x17a/0x614
[ 34.736030] #2: (pci_remove_rescan_mutex){+.+.+.}, at: [<0000000000444102>] remove_callback+0x32/0x50
[ 34.736034] #3: (&__lockdep_no_validate__){......}, at: [<000000000047ae3c>] device_release_driver+0x34/0x50
[ 34.736039] #4: (pools_lock){+.+.+.}, at: [<0000000000262e22>] dma_pool_destroy+0x32/0x1a4
[ 34.736043]
[ 34.736043] stack backtrace:
[ 34.736046] CPU: 0 PID: 49 Comm: kworker/u128:3 Not tainted 3.12.0-01915-g6c86ae2-dirty #125
[ 34.736049] Workqueue: sysfsd sysfs_schedule_callback_work
[ 34.736051] 000000007c827620 000000007c827630 0000000000000002 0000000000000000
[ 34.736051] 000000007c8276c0 000000007c827638 000000007c827638 000000000011157c
[ 34.736051] 0000000000000000 000000000078a13e 00000000007a4b50 000000000000000b
[ 34.736051] 000000007c827680 000000007c827620 0000000000000000 0000000000000000
[ 34.736051] 0000000000000000 000000000011157c 000000007c827620 000000007c827680
[ 34.736067] Call Trace:
[ 34.736070] ([<0000000000111464>] show_trace+0xf8/0x158)
[ 34.736072] [<000000000011152e>] show_stack+0x6a/0xe8
[ 34.736074] [<000000000060d0a6>] dump_stack+0x82/0xac
[ 34.736076] [<00000000006071bc>] print_circular_bug+0x304/0x318
[ 34.736078] [<00000000001a68f8>] check_prev_add+0x748/0x74c
[ 34.736080] [<00000000001aa4c0>] __lock_acquire+0xf24/0x1698
[ 34.736082] [<00000000001ab360>] lock_acquire+0xb8/0x1f8
[ 34.736084] [<0000000000303bf4>] sysfs_deactivate+0xa4/0x124
[ 34.736086] [<00000000003048c2>] sysfs_addrm_finish+0x52/0x8c
[ 34.736088] [<0000000000304ea6>] sysfs_hash_and_remove+0x66/0xb0
[ 34.736090] [<0000000000262f70>] dma_pool_destroy+0x180/0x1a4
[ 34.736097] [<000003ff805cc0b2>] mlx4_cmd_cleanup+0x2e/0xa0 [mlx4_core]
[ 34.736105] [<000003ff805d7e58>] mlx4_remove_one+0x170/0x34c [mlx4_core]
[ 34.736107] [<00000000004425be>] pci_device_remove+0x42/0x7c
[ 34.736109] [<000000000047ad96>] __device_release_driver+0x6e/0xe0
[ 34.736111] [<000000000047ae46>] device_release_driver+0x3e/0x50
[ 34.736113] [<000000000047a7a0>] bus_remove_device+0x128/0x198
[ 34.736115] [<000000000047771c>] device_del+0x13c/0x1c8
[ 34.736117] [<000000000043bd40>] pci_stop_bus_device+0xb4/0xd8
[ 34.736119] [<000000000043beec>] pci_stop_and_remove_bus_device+0x28/0x38
[ 34.736121] [<000000000044410e>] remove_callback+0x3e/0x50
[ 34.736123] [<00000000003028d4>] sysfs_schedule_callback_work+0x30/0x84
[ 34.736125] [<000000000014eea8>] process_one_work+0x200/0x614
[ 34.736127] [<0000000000150674>] worker_thread+0x11c/0x308
[ 34.736129] [<000000000015903a>] kthread+0xd2/0xdc
[ 34.736131] [<0000000000615a72>] kernel_thread_starter+0x6/0xc
[ 34.736133] [<0000000000615a6c>] kernel_thread_starter+0x0/0xc
[ 34.736135] INFO: lockdep is turned off.

The following patch fixes this for me - but maybe someone has a better
idea to handle this.

Regards,
Sebastian
--

mm/dmapool: fix a possible deadlock

Reading from $DEV/pools could result in a deadlock when the last
dmapool is removed from this device at the same time:

[ 34.735836] ======================================================
[ 34.735838] [ INFO: possible circular locking dependency detected ]
[ 34.735840] 3.12.0-01915-g6c86ae2-dirty #125 Not tainted
[ 34.735842] -------------------------------------------------------
[ 34.735843] kworker/u128:3/49 is trying to acquire lock:
[ 34.735845] (s_active#27){++++.+}, at: [<00000000003048c2>] sysfs_addrm_finish+0x52/0x8c
[ 34.735854]
[ 34.735854] but task is already holding lock:
[ 34.735856] (pools_lock){+.+.+.}, at: [<0000000000262e22>] dma_pool_destroy+0x32/0x1a4
[ 34.735862]
[ 34.735862] which lock already depends on the new lock.
...
[ 34.736001] Possible unsafe locking scenario:
[ 34.736001]
[ 34.736003] CPU0 CPU1
[ 34.736005] ---- ----
[ 34.736006] lock(pools_lock);
[ 34.736008] lock(s_active#27);
[ 34.736010] lock(pools_lock);
[ 34.736013] lock(s_active#27);
[ 34.736015]
[ 34.736015] *** DEADLOCK ***

Fix this by moving the pools attribute creation and removal outside
the pools_lock (which is used to protect access to the dma_pools
list). And add a new lock to serialize the pools attribute
creation/removal.

Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
---
mm/dmapool.c | 39 ++++++++++++++++++++++++---------------
1 file changed, 24 insertions(+), 15 deletions(-)

--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -61,7 +61,8 @@ struct dma_page { /* cacheable header f
unsigned int offset;
};

-static DEFINE_MUTEX(pools_lock);
+static DEFINE_MUTEX(pools_lock); /* protect dev->dma_pools access */
+static DEFINE_MUTEX(pools_attr_lock);/* serialize pools attr creation/removal */

static ssize_t
show_pools(struct device *dev, struct device_attribute *attr, char *buf)
@@ -171,21 +172,24 @@ struct dma_pool *dma_pool_create(const c
retval->allocation = allocation;

if (dev) {
- int ret;
+ bool empty;

+ mutex_lock(&pools_attr_lock);
mutex_lock(&pools_lock);
- if (list_empty(&dev->dma_pools))
- ret = device_create_file(dev, &dev_attr_pools);
- else
- ret = 0;
- /* note: not currently insisting "name" be unique */
- if (!ret)
- list_add(&retval->pools, &dev->dma_pools);
- else {
- kfree(retval);
- retval = NULL;
- }
+ empty = list_empty(&dev->dma_pools);
+ list_add(&retval->pools, &dev->dma_pools);
mutex_unlock(&pools_lock);
+ if (empty) {
+ if (device_create_file(dev, &dev_attr_pools)) {
+ mutex_lock(&pools_lock);
+ list_del(&retval->pools);
+ mutex_unlock(&pools_lock);
+
+ kfree(retval);
+ retval = NULL;
+ }
+ }
+ mutex_unlock(&pools_attr_lock);
} else
INIT_LIST_HEAD(&retval->pools);

@@ -259,11 +263,16 @@ static void pool_free_page(struct dma_po
*/
void dma_pool_destroy(struct dma_pool *pool)
{
+ bool empty;
+
+ mutex_lock(&pools_attr_lock);
mutex_lock(&pools_lock);
list_del(&pool->pools);
- if (pool->dev && list_empty(&pool->dev->dma_pools))
- device_remove_file(pool->dev, &dev_attr_pools);
+ empty = pool->dev && list_empty(&pool->dev->dma_pools);
mutex_unlock(&pools_lock);
+ if (empty)
+ device_remove_file(pool->dev, &dev_attr_pools);
+ mutex_unlock(&pools_attr_lock);

while (!list_empty(&pool->page_list)) {
struct dma_page *page;


\
 
 \ /
  Last update: 2013-11-08 18:41    [W:0.021 / U:0.016 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site