aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm/core.c
diff options
context:
space:
mode:
authorMatias Bjørling <m@bjorling.me>2016-07-07 03:54:17 -0400
committerJens Axboe <axboe@fb.com>2016-07-07 10:51:52 -0400
commit5cd907853d5b777c11ecbc8de4482ea5f51663bc (patch)
tree23cf4e800cba9be0351780bb82824713ade3dc82 /drivers/lightnvm/core.c
parentb76eb20bb0c6f4f9c2e1ad493f73c52817b8aaff (diff)
lightnvm: remove nested lock conflict with mm
If a media manager tries to initialize it targets upon media manager initialization, the media manager will need to know which target types are available in LightNVM. The lists of which managers and target types are available shares the same lock. Therefore, on initialization, the nvm_lock is taken by LightNVM core, which later leads to a deadlock when target types are enumerated by the media manager. Add an exclusive lock for target types to resolve this conflict. Signed-off-by: Matias Bjørling <m@bjorling.me> Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r--drivers/lightnvm/core.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c
index 8afb04cc4d5a..04469e0c84ce 100644
--- a/drivers/lightnvm/core.c
+++ b/drivers/lightnvm/core.c
@@ -28,6 +28,7 @@
28#include <linux/sched/sysctl.h> 28#include <linux/sched/sysctl.h>
29 29
30static LIST_HEAD(nvm_tgt_types); 30static LIST_HEAD(nvm_tgt_types);
31static DECLARE_RWSEM(nvm_tgtt_lock);
31static LIST_HEAD(nvm_mgrs); 32static LIST_HEAD(nvm_mgrs);
32static LIST_HEAD(nvm_devices); 33static LIST_HEAD(nvm_devices);
33static DECLARE_RWSEM(nvm_lock); 34static DECLARE_RWSEM(nvm_lock);
@@ -37,7 +38,7 @@ struct nvm_tgt_type *nvm_find_target_type(const char *name, int lock)
37 struct nvm_tgt_type *tmp, *tt = NULL; 38 struct nvm_tgt_type *tmp, *tt = NULL;
38 39
39 if (lock) 40 if (lock)
40 down_write(&nvm_lock); 41 down_write(&nvm_tgtt_lock);
41 42
42 list_for_each_entry(tmp, &nvm_tgt_types, list) 43 list_for_each_entry(tmp, &nvm_tgt_types, list)
43 if (!strcmp(name, tmp->name)) { 44 if (!strcmp(name, tmp->name)) {
@@ -46,7 +47,7 @@ struct nvm_tgt_type *nvm_find_target_type(const char *name, int lock)
46 } 47 }
47 48
48 if (lock) 49 if (lock)
49 up_write(&nvm_lock); 50 up_write(&nvm_tgtt_lock);
50 return tt; 51 return tt;
51} 52}
52EXPORT_SYMBOL(nvm_find_target_type); 53EXPORT_SYMBOL(nvm_find_target_type);
@@ -55,12 +56,12 @@ int nvm_register_tgt_type(struct nvm_tgt_type *tt)
55{ 56{
56 int ret = 0; 57 int ret = 0;
57 58
58 down_write(&nvm_lock); 59 down_write(&nvm_tgtt_lock);
59 if (nvm_find_target_type(tt->name, 0)) 60 if (nvm_find_target_type(tt->name, 0))
60 ret = -EEXIST; 61 ret = -EEXIST;
61 else 62 else
62 list_add(&tt->list, &nvm_tgt_types); 63 list_add(&tt->list, &nvm_tgt_types);
63 up_write(&nvm_lock); 64 up_write(&nvm_tgtt_lock);
64 65
65 return ret; 66 return ret;
66} 67}