]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Skip multiple deletes in split calculation.
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Wed, 6 May 2020 18:04:47 +0000 (14:04 -0400)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Fri, 30 Oct 2020 19:04:41 +0000 (15:04 -0400)
When splitting, do not split within consecutive NULL entries.  Doing so
would cause separated gaps.

Also reset mas->node before walking in two other places which could
potentially cause issue.

Signed-off-by: Liam R. Howlett <Liam.Howlett@Oracle.com>
lib/maple_tree.c
lib/test_maple_tree.c

index f2125125c91b6f2572e70256b1ff2d2421f37935..88a04fec52ef7ef9b96e7626af70ad1c5c52c5a5 100644 (file)
@@ -1505,11 +1505,16 @@ static inline unsigned char mas_append_calc_split(struct ma_state *mas,
 
 done:
        if (ret < max) {
+               bool null = false;
                if (piv == ULONG_MAX)
                        ret++;
 
+               if (mt_is_empty(mas_get_rcu_slot(mas, ret)))
+                   null = true;
+
                while((ret < max) && // Skip deletes and retries.
-                     (piv == mas_get_safe_pivot(mas, ret + 1)))
+                     ((piv == mas_get_safe_pivot(mas, ret + 1)) ||
+                      (null && mt_is_empty(mas_get_rcu_slot(mas, ret + 1)))))
                      ret++;
        }
 
@@ -4064,6 +4069,7 @@ static inline void mas_rebalance(struct ma_state *mas)
        mas_rebalance_gaps(mas);
        if (mas_is_err(mas))
                return;
+       mas->node = MAS_START;
        _mas_walk(mas); // return to the updated location in the tree.
 }
 
@@ -4486,6 +4492,7 @@ static inline int mas_dead_node(struct ma_state *mas, unsigned long index)
                return 0;
 
        mas->index = index;
+       mas->node = MAS_START;
        _mas_walk(mas);
        return 1;
 }
index 4a6f3aa53aface160950b9edf49c60d36bcf4284..20b91a01e80f6d649c0a61443d113d35319b0fb9 100644 (file)
@@ -22233,6 +22233,31 @@ SNULL, 140249682087935, 140249710600191,
 STORE, 140249652703232, 140249682087935,
 STORE, 140249682087936, 140249710600191,
        };
+       unsigned long set26[] = {
+STORE, 140737488347136, 140737488351231,
+STORE, 140729464770560, 140737488351231,
+SNULL, 140729464774655, 140737488351231,
+STORE, 140729464770560, 140729464774655,
+STORE, 140729464639488, 140729464774655,
+STORE, 4194304, 5066751,
+STORE, 7159808, 7172095,
+STORE, 7172096, 7180287,
+STORE, 140729465114624, 140729465118719,
+STORE, 140729465102336, 140729465114623,
+STORE, 30867456, 30875647,
+STORE, 30867456, 31010815,
+STORE, 140109040988160, 140109042671615,
+STORE, 140109040959488, 140109040988159,
+STORE, 140109040943104, 140109040959487,
+ERASE, 140109040943104, 140109040959487,
+STORE, 140109040840704, 140109040959487,
+ERASE, 140109040840704, 140109040959487,
+STORE, 140109040951296, 140109040959487,
+ERASE, 140109040951296, 140109040959487,
+STORE, 140109040955392, 140109040959487,
+ERASE, 140109040955392, 140109040959487,
+       };
+
        int cnt = 0;
        void *ptr = NULL;
        MA_STATE(mas, mt, 0, 0);
@@ -22413,12 +22438,14 @@ STORE, 140249682087936, 140249710600191,
        mt_validate(mt);
        ptr = mtree_load(mt, 140551363362816);
        MT_BUG_ON(mt, ptr == mtree_load(mt, 140551363420159));
+       mt_set_non_kernel(0);
        mtree_destroy(mt);
 
        mt_set_non_kernel(99);
        mtree_init(mt, MAPLE_ALLOC_RANGE);
        check_erase2_testset(mt, set23, ARRAY_SIZE(set23));
        rcu_barrier();
+       mt_set_non_kernel(0);
        mt_validate(mt);
        mtree_destroy(mt);
 
@@ -22427,16 +22454,30 @@ STORE, 140249682087936, 140249710600191,
        mtree_init(mt, MAPLE_ALLOC_RANGE);
        check_erase2_testset(mt, set24, ARRAY_SIZE(set24));
        rcu_barrier();
+       mt_set_non_kernel(0);
        mt_validate(mt);
        mtree_destroy(mt);
 
-
        mt_set_non_kernel(99);
        mtree_init(mt, MAPLE_ALLOC_RANGE);
        check_erase2_testset(mt, set25, ARRAY_SIZE(set25));
        rcu_barrier();
+       mt_set_non_kernel(0);
        mt_validate(mt);
        mtree_destroy(mt);
+
+       // Split on NULL followed by delete - causes gap issues.
+       mt_set_non_kernel(99);
+       mas_reset(&mas);
+       mtree_init(mt, MAPLE_ALLOC_RANGE);
+       check_erase2_testset(mt, set26, ARRAY_SIZE(set26));
+       rcu_barrier();
+       mas_get_unmapped_area_rev(&mas, 4096, 140109042671616, 409600);
+       MT_BUG_ON(mt, mas.index != 140109040549888);
+       mt_set_non_kernel(0);
+       mt_validate(mt);
+       mtree_destroy(mt);
+       exit(0);
 }
 
 static noinline void check_alloc_rev_range(struct maple_tree *mt)
@@ -23065,15 +23106,15 @@ static noinline void check_gap_combining(struct maple_tree *mt)
        rcu_read_unlock();
        mt_validate(mt);
        mtree_destroy(mt);
-#if 0
+
        mt_set_non_kernel(99);
        mtree_init(mt, MAPLE_ALLOC_RANGE);
        check_seq(mt, 400, false);
        mtree_test_store_range(mt, 376, 391, NULL);
        mt_dump(mt);
-       mt_set_non_kernel(1);
+       mt_set_non_kernel(0);
        mtree_destroy(mt);
-#endif
+
        mtree_init(mt, MAPLE_ALLOC_RANGE);
        check_seq(mt, 400, false);
        mt_set_non_kernel(50);
@@ -23249,6 +23290,7 @@ static int maple_tree_seed(void)
 
        mtree_init(&tree, MAPLE_ALLOC_RANGE);
        check_prev_entry(&tree);
+
        mtree_init(&tree, 0);
        check_erase2_sets(&tree);
        mtree_destroy(&tree);