]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Fix nomem bug
authorMatthew Wilcox <willy@infradead.org>
Wed, 5 Dec 2018 19:48:03 +0000 (14:48 -0500)
committerMatthew Wilcox <willy@infradead.org>
Sat, 8 Dec 2018 10:38:41 +0000 (05:38 -0500)
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 <willy@infradead.org>
include/linux/maple_tree.h
lib/maple_tree.c
lib/test_maple_tree.c

index dd7d428db032863e3a8249db2b2a1a4ea33d7c19..00892c978e37926e0a2d7863cd437f7917e1bbcd 100644 (file)
@@ -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
index bdece8c955d3607180ad201c33a56776d8cf6b53..e64bdaf61baa1bd45ef22d3ccdb7807944d37e88 100644 (file)
@@ -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;
 }
 
index 543d3db12ce8dde00353869f8041f5c035c3268a..d7a4ec038575d3e163c29ed38dddc4d8ca5d7911 100644 (file)
@@ -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;
 }