From: Matthew Wilcox Date: Wed, 5 Dec 2018 19:48:03 +0000 (-0500) Subject: maple_tree: Fix nomem bug X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=cf149a320e85b4ca3ad20a8bd00ac395c396fb34;p=users%2Fjedix%2Flinux-maple.git maple_tree: Fix nomem bug Add a pair of tests to check that -ENOMEM works correctly, and fix a bug in __maple_nomem() which was inadvertently clearing the error mark in the case of a second memory allocation failure. Also add an implemenation of mtree_empty(). Signed-off-by: Matthew Wilcox --- diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h index dd7d428db032..00892c978e37 100644 --- a/include/linux/maple_tree.h +++ b/include/linux/maple_tree.h @@ -179,4 +179,16 @@ int mtree_erase(struct maple_tree *mt, unsigned long index); int mtree_destroy(struct maple_tree *mt); +/** + * mtree_empty() - Determine if a tree has any present entries. + * @mt: Maple Tree. + * + * Context: Any context. + * Return: %true if the array contains only NULL pointers. + */ +static inline bool mtree_empty(const struct maple_tree *mt) +{ + return mt->root == NULL; +} + #endif diff --git a/lib/maple_tree.c b/lib/maple_tree.c index bdece8c955d3..e64bdaf61baa 100644 --- a/lib/maple_tree.c +++ b/lib/maple_tree.c @@ -168,9 +168,9 @@ static bool __maple_nomem(struct maple_state *ms, gfp_t gfp) } else { maple_new_node(ms, ma_get_alloc_cnt(ms), gfp); } - ms->node = MAS_START; if (!ma_get_alloc(ms)) return false; + ms->node = MAS_START; return true; } diff --git a/lib/test_maple_tree.c b/lib/test_maple_tree.c index 543d3db12ce8..d7a4ec038575 100644 --- a/lib/test_maple_tree.c +++ b/lib/test_maple_tree.c @@ -30,12 +30,18 @@ void mt_dump(const struct maple_tree *mt) { } } while (0) #endif +static +int mtree_insert_index(struct maple_tree *mt, unsigned long index, gfp_t gfp) +{ + return mtree_insert(mt, index, xa_mk_value(index & LONG_MAX), gfp); +} static int mtree_test_insert(struct maple_tree *mt, unsigned long index, void *ptr) { return mtree_insert(mt, index, ptr, GFP_KERNEL); } + static int mtree_test_insert_range(struct maple_tree *mt, unsigned long start, unsigned long end, void *ptr) { @@ -81,6 +87,18 @@ static noinline void check_load(struct maple_tree *mt, unsigned long index, MT_BUG_ON(mt, ret != ptr); } +static noinline void check_nomem(struct maple_tree *mt) +{ + MT_BUG_ON(mt, !mtree_empty(mt)); + + /* Storing something at 1 requires memory allocation */ + MT_BUG_ON(mt, mtree_insert_index(mt, 1, GFP_ATOMIC) != -ENOMEM); + /* Storing something at 0 does not */ + MT_BUG_ON(mt, mtree_insert_index(mt, 0, GFP_ATOMIC) != 0); + + mtree_destroy(mt); +} + static DEFINE_MAPLE_TREE(tree); static int maple_tree_seed(void) @@ -200,8 +218,8 @@ static int maple_tree_seed(void) check_load(&tree, set[9], &tree); mtree_destroy(&tree); + check_nomem(&tree); - printk("maple_tree: %u of %u tests passed\n", tests_passed, tests_run); return (tests_run == tests_passed) ? 0 : -EINVAL; }