From: Matthew Wilcox (Oracle) Date: Wed, 20 Oct 2021 12:49:48 +0000 (-0400) Subject: maple tree: Support lockdep validation of external locks X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9738bd0f6816ca04c75c0e8895346cca5ef3f932;p=users%2Fwilly%2Flinux.git maple tree: Support lockdep validation of external locks Signed-off-by: Matthew Wilcox (Oracle) --- diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index 7fc49ad3b34d..23b8b6dc658e 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -160,7 +160,12 @@ enum maple_type { #define MAPLE_RESERVED_RANGE 4096 struct maple_tree { - spinlock_t ma_lock; + union { + spinlock_t ma_lock; +#ifdef CONFIG_LOCKDEP + struct lockdep_map *ma_external_lock; +#endif + }; unsigned int ma_flags; void __rcu *ma_root; }; @@ -172,11 +177,27 @@ struct maple_tree { .ma_root = NULL, \ } +#ifdef CONFIG_LOCKDEP +#define MTREE_INIT_EXT(name, flags, lock) { \ + .ma_external_lock = &(lock).dep_map, \ + .ma_flags = flags, \ + .ma_root = NULL, \ +} +#else +#define MTREE_INIT_EXT(name, flags, lock) MTREE_INIT(name, flags) +#endif + #define DEFINE_MTREE(name) \ struct maple_tree name = MTREE_INIT(name, 0) #define mtree_lock(mt) spin_lock((&(mt)->ma_lock)) #define mtree_unlock(mt) spin_unlock((&(mt)->ma_lock)) +#ifdef CONFIG_LOCKDEP +#define mt_set_external_lock(mt, lock) \ + (mt)->ma_external_lock = &(lock)->dep_map; +#else +#define mt_set_external_lock(mt, lock) do { } while (0) +#endif struct maple_node { union { @@ -388,22 +409,33 @@ static inline void mas_set(struct ma_state *mas, unsigned long index) mas_set_range(mas, index, index); } +static inline bool mt_external_lock(const struct maple_tree *mt) +{ + return (mt->ma_flags & MT_FLAGS_LOCK_MASK) == MT_FLAGS_LOCK_EXTERN; +} + /** * mt_init_flags() - Initialise an empty maple tree with flags. * @mt: Maple Tree * @flags: maple tree flags. * - * If you need to initialise a Maple Tree with special falgs (eg, an + * If you need to initialise a Maple Tree with special flags (eg, an * allocation tree), use this function. * * Context: Any context. - * */ static inline void mt_init_flags(struct maple_tree *mt, unsigned int flags) { - spin_lock_init(&mt->ma_lock); mt->ma_flags = flags; - mt->ma_root = NULL; + if (mt_external_lock(mt)) +#ifdef CONFIG_LOCKDEP + mt->ma_external_lock = NULL; +#else + do { } while (0); +#endif + else + spin_lock_init(&mt->ma_lock); + rcu_assign_pointer(mt->ma_root, NULL); } /** diff --git a/lib/maple_tree.c b/lib/maple_tree.c index c9dd1ceb5c67..20ed92e86a55 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -747,14 +747,15 @@ static inline void __rcu **ma_slots(struct maple_node *mn, enum maple_type mt) } } -static inline bool mt_external_lock(const struct maple_tree *mt) -{ - return (mt->ma_flags & MT_FLAGS_LOCK_MASK) == MT_FLAGS_LOCK_EXTERN; -} - static inline bool mt_locked(const struct maple_tree *mt) { - return mt_external_lock(mt) || lockdep_is_held(&mt->ma_lock); +#ifdef CONFIG_LOCKDEP + return mt_external_lock(mt) ? + lock_is_held(mt->ma_external_lock) : + lockdep_is_held(&mt->ma_lock); +#else + return true; +#endif } static inline void *mt_slot(const struct maple_tree *mt, @@ -5451,6 +5452,7 @@ static void **mas_dead_walk(struct ma_state *mas, unsigned char offset) return slots; } + static void mt_free_walk(struct rcu_head *head) { void __rcu **slots; @@ -5464,7 +5466,7 @@ static void mt_free_walk(struct rcu_head *head) if (ma_is_leaf(node->type)) goto free_leaf; - mtree_init(&mt, node->ma_flags); + mt_init_flags(&mt, node->ma_flags); mas_lock(&mas); start = node; mas.node = mt_mk_node(node, node->type); @@ -5528,7 +5530,7 @@ static void mt_destroy_walk(struct maple_enode *enode, unsigned char ma_flags, if (mte_is_leaf(enode)) goto free_leaf; - mtree_init(&mt, ma_flags); + mt_init_flags(&mt, ma_flags); mas_lock(&mas); mas.node = start = enode; @@ -5965,19 +5967,6 @@ void __init maple_tree_init(void) SLAB_PANIC, NULL); } -/* - * mtree_init() - Initialize a maple tree. - * @mt: The maple tree - * @ma_flags: The flags to use for the tree. - */ -void mtree_init(struct maple_tree *mt, unsigned int ma_flags) -{ - mt->ma_flags = ma_flags; - spin_lock_init(&mt->ma_lock); - rcu_assign_pointer(mt->ma_root, NULL); -} -EXPORT_SYMBOL(mtree_init); - /* * mtree_load() - Load a value stored in a maple tree * @mt: The maple tree