]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
test_maple_tree: Add testing for maple state handling
authorLiam R. Howlett <Liam.Howlett@oracle.com>
Fri, 10 Feb 2023 21:49:09 +0000 (16:49 -0500)
committerLiam R. Howlett <Liam.Howlett@oracle.com>
Mon, 13 Feb 2023 13:42:05 +0000 (08:42 -0500)
This adds testing for both a tree with multiple entries and a tree with
just one entry at 0 - 0 (single entry tree).

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

index fd50ba0624999220f70bd339aa8e05167f61d120..a9627cea144386fbf6eaa734b9f6782280a43833 100644 (file)
@@ -2675,6 +2675,648 @@ static noinline void __init check_empty_area_window(struct maple_tree *mt)
        rcu_read_unlock();
 }
 
+/*
+ * Check MAS_START, MAS_PAUSE, active (implied), and MAS_NONE transitions.
+ *
+ * The table below shows the single entry tree (0-0 pointer) and normal tree
+ * with nodes.
+ *
+ * Function    ENTRY   Start           Result          index & last
+ *     ┬          ┬       ┬               ┬                ┬
+ *     │          │       │               │                └─ the final range
+ *     │          │       │               └─ The node value after execution
+ *     │          │       └─ The node value before execution
+ *     │          └─ If the entry exists of does not exists (DNE)
+ *     └─ The function name
+ *
+ * Function    ENTRY   Start           Result          index & last
+ * mas_next()
+ *  - after last
+ *                     Single entry tree at 0-0
+ *                     ------------------------
+ *             DNE     MAS_START       MAS_NONE        1 - ULONG_MAX
+ *             DNE     MAS_PAUSE       MAS_NONE        1 - ULONG_MAX
+ *             DNE     MAS_ROOT        MAS_NONE        1 - ULONG_MAX
+ *             DNE     MAS_NONE        MAS_NONE        1 - ULONG_MAX
+ *
+ *                     Normal tree
+ *                     -----------
+ *             exists  MAS_START       active          range
+ *             DNE     MAS_START       MAS_NONE        set to max
+ *             exists  MAS_PAUSE       active          range
+ *             DNE     MAS_PAUSE       MAS_NONE        set to max
+ *             exists  MAS_NONE        active          range
+ *             exists  active          active          range
+ *             DNE     active          MAS_NONE        max
+ *                             --or--
+ *             DNE     active          active          last range (max < last)
+ *
+ * Function    ENTRY   Start           Result          index & last
+ * mas_prev()
+ * - before index
+ *                     Single entry tree at 0-0
+ *                     ------------------------
+ *                             if index > 0
+ *             exists  MAS_START       MAS_ROOT        0 - 0
+ *             exists  MAS_PAUSE       MAS_ROOT        0 - 0
+ *             exists  MAS_NONE        MAS_ROOT        0 - 0
+ *
+ *                             if index == 0
+ *             DNE     MAS_START       MAS_NONE        0 - 0
+ *             DNE     MAS_PAUSE       MAS_NONE        0 - 0
+ *             DNE     MAS_NONE        MAS_NONE        0 - 0
+ *             DNE     MAS_ROOT        MAS_NONE        0 - 0
+ *
+ *                     Normal tree
+ *                     -----------
+ *             exists  MAS_START       active          range
+ *             DNE     MAS_START       MAS_NONE        set to min
+ *             exists  MAS_PAUSE       active          range
+ *             DNE     MAS_PAUSE       active          set to min
+ *             exists  MAS_NONE        active          range
+ *             DNE     MAS_NONE        MAS_NONE        set to min
+ *             any     MAS_ROOT        MAS_NONE        0 - 0
+ *             exists  active          active          range
+ *             DNE     active          MAS_NONE        min
+ *                             --or--
+ *             DNE     active          active          last range (min > index)
+ *
+ * Function    ENTRY   Start           Result          index & last
+ * mas_find()
+ *  - at index or next
+ *                     Single entry tree at 0-0
+ *                     ------------------------
+ *                             if index >  0
+ *             DNE     MAS_START       MAS_NONE        1 - ULONG_MAX
+ *             DNE     MAS_PAUSE       MAS_NONE        1 - ULONG_MAX
+ *             DNE     MAS_ROOT        MAS_NONE        1 - ULONG_MAX
+ *             DNE     MAS_NONE        MAS_NONE        1 - ULONG_MAX
+ *                             if index ==  0
+ *             exists  MAS_START       MAS_ROOT        0 - 0
+ *             exists  MAS_PAUSE       MAS_ROOT        0 - 0
+ *             exists  MAS_NONE        MAS_ROOT        0 - 0
+ *
+ *                     Normal tree
+ *                     -----------
+ *             exists  MAS_START       active          range
+ *             DNE     MAS_START       MAS_NONE        set to max
+ *             exists  MAS_PAUSE       active          range
+ *             DNE     MAS_PAUSE       MAS_NONE        set to max
+ *             exists  MAS_NONE        active          range
+ *             exists  active          active          range
+ *             DNE     active          MAS_NONE        max
+ *                             --or--
+ *             DNE     active          active          last range (max < last)
+ *
+ * Function    ENTRY   Start           Result          index & last
+ * mas_find_rev()
+ *  - at index or before
+ *                     Single entry tree at 0-0
+ *                     ------------------------
+ *                             if index >  0
+ *             exists  MAS_START       MAS_ROOT        0 - 0
+ *             exists  MAS_PAUSE       MAS_ROOT        0 - 0
+ *             exists  MAS_NONE        MAS_ROOT        0 - 0
+ *                             if index ==  0
+ *             DNE     MAS_START       MAS_NONE        0 - 0
+ *             DNE     MAS_PAUSE       MAS_NONE        0 - 0
+ *             DNE     MAS_NONE        MAS_NONE        0 - 0
+ *             DNE     MAS_ROOT        MAS_NONE        0 - 0
+ *
+ *                     Normal tree
+ *                     -----------
+ *             exists  MAS_START       active          range
+ *             DNE     MAS_START       MAS_NONE        set to min
+ *             exists  MAS_PAUSE       active          range
+ *             DNE     MAS_PAUSE       MAS_NONE        set to min
+ *             exists  MAS_NONE        active          range
+ *             DNE     MAS_NONE        MAS_NONE        set to min
+ *             exists  active          active          range
+ *             DNE     active          MAS_NONE        min
+ *                             --or--
+ *             DNE     active          active          last range (min > index)
+ *
+ * Function    ENTRY   Start           Result          index & last
+ * mas_walk()
+ * - Look up index
+ *                     Single entry tree at 0-0
+ *                     ------------------------
+ *                             if index >  0
+ *             DNE     MAS_START       MAS_ROOT        1 - ULONG_MAX
+ *             DNE     MAS_PAUSE       MAS_ROOT        1 - ULONG_MAX
+ *             DNE     MAS_NONE        MAS_ROOT        1 - ULONG_MAX
+ *             DNE     MAS_ROOT        MAS_ROOT        1 - ULONG_MAX
+ *                             if index ==  0
+ *             exists  MAS_START       MAS_ROOT        0 - 0
+ *             exists  MAS_PAUSE       MAS_ROOT        0 - 0
+ *             exists  MAS_NONE        MAS_ROOT        0 - 0
+ *             exists  MAS_ROOT        MAS_ROOT        0 - 0
+ *
+ *                     Normal tree
+ *                     -----------
+ *             exists  MAS_START       active          range
+ *             DNE     MAS_START       active          range of NULL
+ *             exists  MAS_PAUSE       active          range
+ *             DNE     MAS_PAUSE       active          range of NULL
+ *             exists  MAS_NONE        active          range
+ *             DNE     MAS_NONE        active          unchanged
+ *             exists  active          active          range
+ *             DNE     active          active          range of NULL
+ */
+static noinline void __init check_state_handling(struct maple_tree *mt)
+{
+       MA_STATE(mas, mt, 0, 0);
+       void *entry, *ptr = (void *) 0x1234500;
+       void *ptr2 = &ptr;
+       void *ptr3 = &ptr2;
+
+       /* Check MAS_ROOT First */
+       mtree_store_range(mt, 0, 0, ptr, GFP_KERNEL);
+
+       mas_lock(&mas);
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       mas_set(&mas, 10);
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+
+       mas_set(&mas, 10);
+       mas_pause(&mas);
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+
+       mas_set(&mas, 0);
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       mas_set(&mas, 10);
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       mas_set(&mas, 0);
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       mas_set(&mas, 10);
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 0);
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       mas_set(&mas, 10);
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 10);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 10);
+       mas_pause(&mas);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 10);
+       mas.node = MAS_NONE;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 0);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 0);
+       mas_pause(&mas);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas.node = MAS_NONE;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_set(&mas, 10);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 1);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas.index = mas.last = 0;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_ROOT);
+
+       mas_unlock(&mas);
+
+       /* Check when there is an actual node */
+       mtree_store_range(mt, 0, 0, NULL, GFP_KERNEL);
+       mtree_store_range(mt, 0x1000, 0x1500, ptr, GFP_KERNEL);
+       mtree_store_range(mt, 0x2000, 0x2500, ptr2, GFP_KERNEL);
+       mtree_store_range(mt, 0x3000, 0x3500, ptr3, GFP_KERNEL);
+
+       mas_lock(&mas);
+
+       /* next: start ->active */
+       mas_set(&mas, 0);
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* next: pause ->active */
+       mas_set(&mas, 0);
+       mas_pause(&mas);
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* next: none ->active */
+       mas.index = mas.last = 0;
+       mas.offset = 0;
+       mas.node = MAS_NONE;
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* next:active ->active */
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr2);
+       MAS_BUG_ON(&mas, mas.index != 0x2000);
+       MAS_BUG_ON(&mas, mas.last != 0x2500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* next:active -> none */
+       entry = mas_next(&mas, 0x2999);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x2999);
+       MAS_BUG_ON(&mas, mas.last != 0x2999);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+       /* Continue after none */
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr3);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* next:active -> none */
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       /* next: none ->active, skip value at location */
+       mas_set(&mas, 0);
+       entry = mas_next(&mas, ULONG_MAX);
+       mas.node = MAS_NONE;
+       mas.offset = 0;
+       entry = mas_next(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr2);
+       MAS_BUG_ON(&mas, mas.index != 0x2000);
+       MAS_BUG_ON(&mas, mas.last != 0x2500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* prev:active ->active */
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* prev:active -> none */
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       /* prev: pause ->active */
+       mas_set(&mas, 0x3600);
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr3);
+       mas_pause(&mas);
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr2);
+       MAS_BUG_ON(&mas, mas.index != 0x2000);
+       MAS_BUG_ON(&mas, mas.last != 0x2500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* prev:active -> none */
+       entry = mas_prev(&mas, 0x1600);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x1600);
+       MAS_BUG_ON(&mas, mas.last != 0x1600);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       /* prev: none ->active */
+       entry = mas_prev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find: start ->active */
+       mas_set(&mas, 0);
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find: pause ->active */
+       mas_set(&mas, 0);
+       mas_pause(&mas);
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find: start ->active on value */;
+       mas_set(&mas, 1200);
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find:active ->active */
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != ptr2);
+       MAS_BUG_ON(&mas, mas.index != 0x2000);
+       MAS_BUG_ON(&mas, mas.last != 0x2500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+
+       /* find:active -> none */
+       entry = mas_find(&mas, 0x2700);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x2700);
+       MAS_BUG_ON(&mas, mas.last != 0x2700);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       /* find: none ->active */
+       entry = mas_find(&mas, 0x5000);
+       MAS_BUG_ON(&mas, entry != ptr3);
+       MAS_BUG_ON(&mas, mas.index != 0x3000);
+       MAS_BUG_ON(&mas, mas.last != 0x3500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find:active -> none */
+       entry = mas_find(&mas, ULONG_MAX);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.last != ULONG_MAX);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       /* find_rev: none ->active */
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr3);
+       MAS_BUG_ON(&mas, mas.index != 0x3000);
+       MAS_BUG_ON(&mas, mas.last != 0x3500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find_rev:active ->active */
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr2);
+       MAS_BUG_ON(&mas, mas.index != 0x2000);
+       MAS_BUG_ON(&mas, mas.last != 0x2500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find_rev: pause ->active */
+       mas_pause(&mas);
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* find_rev:active -> none */
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0);
+       MAS_BUG_ON(&mas, mas.last != 0);
+       MAS_BUG_ON(&mas, mas.node != MAS_NONE);
+
+       /* find_rev: start ->active */
+       mas_set(&mas, 0x1200);
+       entry = mas_find_rev(&mas, 0);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk start ->active */
+       mas_set(&mas, 0x1200);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk start ->active */
+       mas_set(&mas, 0x1600);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x1501);
+       MAS_BUG_ON(&mas, mas.last != 0x1fff);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk pause ->active */
+       mas_set(&mas, 0x1200);
+       mas_pause(&mas);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk pause -> active */
+       mas_set(&mas, 0x1600);
+       mas_pause(&mas);
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x1501);
+       MAS_BUG_ON(&mas, mas.last != 0x1fff);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk none -> active */
+       mas_set(&mas, 0x1200);
+       mas.node = MAS_NONE;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk none -> active */
+       mas_set(&mas, 0x1600);
+       mas.node = MAS_NONE;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x1501);
+       MAS_BUG_ON(&mas, mas.last != 0x1fff);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk active -> active */
+       mas.index = 0x1200;
+       mas.last = 0x1200;
+       mas.offset = 0;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != ptr);
+       MAS_BUG_ON(&mas, mas.index != 0x1000);
+       MAS_BUG_ON(&mas, mas.last != 0x1500);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       /* mas_walk active -> active */
+       mas.index = 0x1600;
+       mas.last = 0x1600;
+       entry = mas_walk(&mas);
+       MAS_BUG_ON(&mas, entry != NULL);
+       MAS_BUG_ON(&mas, mas.index != 0x1501);
+       MAS_BUG_ON(&mas, mas.last != 0x1fff);
+       MAS_BUG_ON(&mas, mas.node == MAS_PAUSE);
+       MAS_BUG_ON(&mas, mas.node == MAS_NONE);
+       MAS_BUG_ON(&mas, mas.node == MAS_START);
+
+       mas_unlock(&mas);
+}
+
 static DEFINE_MTREE(tree);
 static int __init maple_tree_seed(void)
 {
@@ -2931,6 +3573,10 @@ static int __init maple_tree_seed(void)
        check_empty_area_window(&tree);
        mtree_destroy(&tree);
 
+       mt_init_flags(&tree, MT_FLAGS_ALLOC_RANGE);
+       check_state_handling(&tree);
+       mtree_destroy(&tree);
+
 #if defined(BENCH)
 skip:
 #endif