]> www.infradead.org Git - users/willy/linux.git/commitdiff
maple tree: Support lockdep validation of external locks
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 20 Oct 2021 12:49:48 +0000 (08:49 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 20 Oct 2021 19:19:22 +0000 (15:19 -0400)
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
include/linux/maple_tree.h
lib/maple_tree.c

index 7fc49ad3b34da71c86a9c1ca1c955d6fd6ac5b1a..23b8b6dc658eca9e6364205525d83b534017c247 100644 (file)
@@ -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);
 }
 
 /**
index c9dd1ceb5c6744a2e2e750467279afae65ff56b0..20ed92e86a55b66c42c62d6696865b3aa9613f4a 100644 (file)
@@ -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