maple_tree: add debug BUG_ON and WARN_ON variants
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Thu, 18 May 2023 14:55:15 +0000 (10:55 -0400)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 9 Jun 2023 23:25:28 +0000 (16:25 -0700)
Add debug macros to dump the maple state and/or the tree for both warning
and bug_on calls.

Link: https://lkml.kernel.org/r/20230518145544.1722059-7-Liam.Howlett@oracle.com
Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Cc: David Binderman <dcb314@hotmail.com>
Cc: Peng Zhang <zhangpeng.00@bytedance.com>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: Vernon Yang <vernon2gm@gmail.com>
Cc: Wei Yang <richard.weiyang@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/maple_tree.h
lib/maple_tree.c

index 140fb271be4a4afcc1eb11273b23b733f1da55b3..204d7941a39ec2dbd6052d0c604bcd81baf5d653 100644 (file)
@@ -482,13 +482,13 @@ static inline void mas_init(struct ma_state *mas, struct maple_tree *tree,
 }
 
 /* Checks if a mas has not found anything */
-static inline bool mas_is_none(struct ma_state *mas)
+static inline bool mas_is_none(const struct ma_state *mas)
 {
        return mas->node == MAS_NONE;
 }
 
 /* Checks if a mas has been paused */
-static inline bool mas_is_paused(struct ma_state *mas)
+static inline bool mas_is_paused(const struct ma_state *mas)
 {
        return mas->node == MAS_PAUSE;
 }
@@ -679,6 +679,8 @@ extern atomic_t maple_tree_tests_run;
 extern atomic_t maple_tree_tests_passed;
 
 void mt_dump(const struct maple_tree *mt, enum mt_dump_format format);
+void mas_dump(const struct ma_state *mas);
+void mas_wr_dump(const struct ma_wr_state *wr_mas);
 void mt_validate(struct maple_tree *mt);
 void mt_cache_shrink(void);
 #define MT_BUG_ON(__tree, __x) do {                                    \
@@ -695,8 +697,100 @@ void mt_cache_shrink(void);
                atomic_inc(&maple_tree_tests_passed);                   \
        }                                                               \
 } while (0)
+
+#define MAS_BUG_ON(__mas, __x) do {                                    \
+       atomic_inc(&maple_tree_tests_run);                              \
+       if (__x) {                                                      \
+               pr_info("BUG at %s:%d (%u)\n",                          \
+               __func__, __LINE__, __x);                               \
+               mas_dump(__mas);                                        \
+               mt_dump((__mas)->tree, mt_dump_hex);                    \
+               pr_info("Pass: %u Run:%u\n",                            \
+                       atomic_read(&maple_tree_tests_passed),          \
+                       atomic_read(&maple_tree_tests_run));            \
+               dump_stack();                                           \
+       } else {                                                        \
+               atomic_inc(&maple_tree_tests_passed);                   \
+       }                                                               \
+} while (0)
+
+#define MAS_WR_BUG_ON(__wrmas, __x) do {                               \
+       atomic_inc(&maple_tree_tests_run);                              \
+       if (__x) {                                                      \
+               pr_info("BUG at %s:%d (%u)\n",                          \
+               __func__, __LINE__, __x);                               \
+               mas_wr_dump(__wrmas);                                   \
+               mas_dump((__wrmas)->mas);                               \
+               mt_dump((__wrmas)->mas->tree, mt_dump_hex);             \
+               pr_info("Pass: %u Run:%u\n",                            \
+                       atomic_read(&maple_tree_tests_passed),          \
+                       atomic_read(&maple_tree_tests_run));            \
+               dump_stack();                                           \
+       } else {                                                        \
+               atomic_inc(&maple_tree_tests_passed);                   \
+       }                                                               \
+} while (0)
+
+#define MT_WARN_ON(__tree, __x)  ({                                    \
+       int ret = !!(__x);                                              \
+       atomic_inc(&maple_tree_tests_run);                              \
+       if (ret) {                                                      \
+               pr_info("WARN at %s:%d (%u)\n",                         \
+               __func__, __LINE__, __x);                               \
+               mt_dump(__tree, mt_dump_hex);                           \
+               pr_info("Pass: %u Run:%u\n",                            \
+                       atomic_read(&maple_tree_tests_passed),          \
+                       atomic_read(&maple_tree_tests_run));            \
+               dump_stack();                                           \
+       } else {                                                        \
+               atomic_inc(&maple_tree_tests_passed);                   \
+       }                                                               \
+       unlikely(ret);                                                  \
+})
+
+#define MAS_WARN_ON(__mas, __x) ({                                     \
+       int ret = !!(__x);                                              \
+       atomic_inc(&maple_tree_tests_run);                              \
+       if (ret) {                                                      \
+               pr_info("WARN at %s:%d (%u)\n",                         \
+               __func__, __LINE__, __x);                               \
+               mas_dump(__mas);                                        \
+               mt_dump((__mas)->tree, mt_dump_hex);                    \
+               pr_info("Pass: %u Run:%u\n",                            \
+                       atomic_read(&maple_tree_tests_passed),          \
+                       atomic_read(&maple_tree_tests_run));            \
+               dump_stack();                                           \
+       } else {                                                        \
+               atomic_inc(&maple_tree_tests_passed);                   \
+       }                                                               \
+       unlikely(ret);                                                  \
+})
+
+#define MAS_WR_WARN_ON(__wrmas, __x) ({                                        \
+       int ret = !!(__x);                                              \
+       atomic_inc(&maple_tree_tests_run);                              \
+       if (ret) {                                                      \
+               pr_info("WARN at %s:%d (%u)\n",                         \
+               __func__, __LINE__, __x);                               \
+               mas_wr_dump(__wrmas);                                   \
+               mas_dump((__wrmas)->mas);                               \
+               mt_dump((__wrmas)->mas->tree, mt_dump_hex);             \
+               pr_info("Pass: %u Run:%u\n",                            \
+                       atomic_read(&maple_tree_tests_passed),          \
+                       atomic_read(&maple_tree_tests_run));            \
+               dump_stack();                                           \
+       } else {                                                        \
+               atomic_inc(&maple_tree_tests_passed);                   \
+       }                                                               \
+       unlikely(ret);                                                  \
+})
 #else
-#define MT_BUG_ON(__tree, __x) BUG_ON(__x)
+#define MT_BUG_ON(__tree, __x)         BUG_ON(__x)
+#define MAS_BUG_ON(__mas, __x)         BUG_ON(__x)
+#define MAS_WR_BUG_ON(__mas, __x)      BUG_ON(__x)
+#define MT_WARN_ON(__tree, __x)                WARN_ON(__x)
+#define MAS_WARN_ON(__mas, __x)                WARN_ON(__x)
+#define MAS_WR_WARN_ON(__mas, __x)     WARN_ON(__x)
 #endif /* CONFIG_DEBUG_MAPLE_TREE */
 
 #endif /*_LINUX_MAPLE_TREE_H */
index dfa0271101d2a25f007a2dbacbbf433bfa665c3a..ff16b6c0ac08c756dc84f1810508b6a267da0f5c 100644 (file)
@@ -240,12 +240,12 @@ static inline void mas_set_err(struct ma_state *mas, long err)
        mas->node = MA_ERROR(err);
 }
 
-static inline bool mas_is_ptr(struct ma_state *mas)
+static inline bool mas_is_ptr(const struct ma_state *mas)
 {
        return mas->node == MAS_ROOT;
 }
 
-static inline bool mas_is_start(struct ma_state *mas)
+static inline bool mas_is_start(const struct ma_state *mas)
 {
        return mas->node == MAS_START;
 }
@@ -7246,4 +7246,34 @@ done:
 }
 EXPORT_SYMBOL_GPL(mt_validate);
 
+void mas_dump(const struct ma_state *mas)
+{
+       pr_err("MAS: tree=%p enode=%p ", mas->tree, mas->node);
+       if (mas_is_none(mas))
+               pr_err("(MAS_NONE) ");
+       else if (mas_is_ptr(mas))
+               pr_err("(MAS_ROOT) ");
+       else if (mas_is_start(mas))
+                pr_err("(MAS_START) ");
+       else if (mas_is_paused(mas))
+               pr_err("(MAS_PAUSED) ");
+
+       pr_err("[%u] index=%lx last=%lx\n", mas->offset, mas->index, mas->last);
+       pr_err("     min=%lx max=%lx alloc=%p, depth=%u, flags=%x\n",
+              mas->min, mas->max, mas->alloc, mas->depth, mas->mas_flags);
+       if (mas->index > mas->last)
+               pr_err("Check index & last\n");
+}
+EXPORT_SYMBOL_GPL(mas_dump);
+
+void mas_wr_dump(const struct ma_wr_state *wr_mas)
+{
+       pr_err("WR_MAS: node=%p r_min=%lx r_max=%lx\n",
+              wr_mas->node, wr_mas->r_min, wr_mas->r_max);
+       pr_err("        type=%u off_end=%u, node_end=%u, end_piv=%lx\n",
+              wr_mas->type, wr_mas->offset_end, wr_mas->node_end,
+              wr_mas->end_piv);
+}
+EXPORT_SYMBOL_GPL(mas_wr_dump);
+
 #endif /* CONFIG_DEBUG_MAPLE_TREE */