summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-03-31 16:10:18 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2019-04-30 17:17:03 -0400
commitbf7eaba81d33f206c62d9b1e4234fdfcd0510bc7 (patch)
tree4a029fbf3dcf1ac528b39d938c75bd70a15d8143
parent63f13e5d1073e1d61b8bfbc9053210d93bacbf78 (diff)
lockdep: debug_check_lock_not_held()
-rw-r--r--fs/bcachefs/btree_cache.c5
-rw-r--r--fs/bcachefs/btree_cache.h2
-rw-r--r--fs/bcachefs/btree_iter.c2
-rw-r--r--include/linux/debug_locks.h2
-rw-r--r--kernel/locking/lockdep.c18
5 files changed, 28 insertions, 1 deletions
diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c
index 2a20bdef8fd0..74edd09eec93 100644
--- a/fs/bcachefs/btree_cache.c
+++ b/fs/bcachefs/btree_cache.c
@@ -90,6 +90,8 @@ err:
list_move(&b->list, &bc->freed);
}
+struct lock_class_key bch2_btree_node_lock_key;
+
static struct btree *btree_node_mem_alloc(struct bch_fs *c, gfp_t gfp)
{
struct btree *b = kzalloc(sizeof(struct btree), gfp);
@@ -97,7 +99,8 @@ static struct btree *btree_node_mem_alloc(struct bch_fs *c, gfp_t gfp)
return NULL;
bkey_btree_ptr_init(&b->key);
- six_lock_init(&b->lock);
+ __six_lock_init(&b->lock, "&b->lock", &bch2_btree_node_lock_key);
+
INIT_LIST_HEAD(&b->list);
INIT_LIST_HEAD(&b->write_blocked);
diff --git a/fs/bcachefs/btree_cache.h b/fs/bcachefs/btree_cache.h
index 08e6f2a68ecb..59a0f2f79602 100644
--- a/fs/bcachefs/btree_cache.h
+++ b/fs/bcachefs/btree_cache.h
@@ -6,6 +6,8 @@
struct btree_iter;
+extern struct lock_class_key bch2_btree_node_lock_key;
+
extern const char * const bch2_btree_ids[];
void bch2_recalc_btree_reserve(struct bch_fs *);
diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index 5631f98f3845..18a6ecff155f 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1888,6 +1888,8 @@ int bch2_trans_unlock(struct btree_trans *trans)
iters ^= 1ULL << idx;
}
+ debug_check_lock_not_held(&bch2_btree_node_lock_key);
+
return ret;
}
diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h
index 257ab3c92cb8..b9718692460d 100644
--- a/include/linux/debug_locks.h
+++ b/include/linux/debug_locks.h
@@ -7,6 +7,7 @@
#include <linux/bug.h>
struct task_struct;
+struct lock_class_key;
extern int debug_locks __read_mostly;
extern int debug_locks_silent __read_mostly;
@@ -53,6 +54,7 @@ extern void debug_show_all_locks(void);
extern void debug_show_held_locks(struct task_struct *task);
extern void debug_check_no_locks_freed(const void *from, unsigned long len);
extern void debug_check_no_locks_held(void);
+void debug_check_lock_not_held(struct lock_class_key *);
#else
static inline void debug_show_all_locks(void)
{
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 95932333a48b..824b4c2136fa 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -4379,6 +4379,24 @@ void debug_check_no_locks_held(void)
}
EXPORT_SYMBOL_GPL(debug_check_no_locks_held);
+void debug_check_lock_not_held(struct lock_class_key *key)
+{
+ struct task_struct *p = current;
+ struct lock_class *class;
+ unsigned i, j;
+
+ for (i = 0; i < p->lockdep_depth; i++) {
+ class = hlock_class(p->held_locks + i);
+
+ for (j = 0; j < MAX_LOCKDEP_SUBCLASSES; j++)
+ if (&key->subkeys[j] == class->key) {
+ lockdep_print_held_locks(p);
+ panic("holding lock we shouldn't be\n");
+ }
+ }
+}
+EXPORT_SYMBOL_GPL(debug_check_lock_not_held);
+
#ifdef __KERNEL__
void debug_show_all_locks(void)
{