]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple_tree: Fix data_end calculation and root expansion.
authorLiam R. Howlett <Liam.Howlett@Oracle.com>
Thu, 3 Jan 2019 18:30:57 +0000 (13:30 -0500)
committerLiam R. Howlett <Liam.Howlett@Oracle.com>
Wed, 31 Jul 2019 14:52:34 +0000 (10:52 -0400)
Root expansion needs to set the pivot to the empty value if there is no
zero for the append to function correctly.

In append, we know the data end will always be at least 1, so take two
off the idx when checking the previous pivot value (since we also add 1
to the end for the new termination).

Append will need to be altered to cover off the overflow possibility in
the future.

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

index 7710b71941df25274b9d8f9b6a02533bb611b5ce..56980807b96739319f13c48901aae74b1e43c28d 100644 (file)
@@ -234,28 +234,30 @@ static void *mas_start(struct ma_state *ms)
        return entry;
 }
 
-short ma_data_end_r64(const struct ma_state *ms)
+unsigned char ma_data_end_r64(const struct ma_state *ms)
 {
        struct maple_range_64 *mr64 = &ms->node->mr64;
-       short data_end = 0;
+       unsigned char data_end = 0;
+       unsigned long last = ms->max;
 
        for (data_end = 0; data_end < MAPLE_RANGE64_SLOTS - 1; data_end++) {
-               if (mr64->pivot[data_end] == 0 ||
-                   mr64->pivot[data_end] == ms->max)
+               last = mr64->pivot[data_end];
+               if (last == 0 && data_end > 0)
                        return data_end;
        }
 
-       if (mr64->slot[data_end+1] != NULL)
+       if (mr64->slot[data_end + 1] != NULL)
                data_end++;
 
        return data_end;
 }
+
 static void ma_append(struct ma_state *ms, void *entry)
 {
-       short idx = ma_data_end_r64(ms) + 2;
+       short idx = ma_data_end_r64(ms) + 1;
        struct maple_range_64 *mr64 = &ms->node->mr64;
 
-       if ((ms->index - 1 != mr64->pivot[idx - 1]) ||
+       if ((ms->index - 1 != mr64->pivot[idx - 2]) ||
           (ms->index != ms->last))
                idx++;
 
@@ -263,13 +265,10 @@ static void ma_append(struct ma_state *ms, void *entry)
                printk("Split this node\n");
 
        /* zero the new end */
-       mr64->pivot[idx] = 0;
-       RCU_INIT_POINTER(mr64->slot[idx], NULL);
-       idx--;
+       mr64->pivot[idx--] = 0;
        /* Set the entry value */
        RCU_INIT_POINTER(mr64->slot[idx], entry);
-       mr64->pivot[idx] = ms->last;
-       idx--;
+       mr64->pivot[idx--] = ms->last;
 
        /* Create a NULL gap, if necessary */
        if ((ms->index - 1 != mr64->pivot[idx - 1]) ||
@@ -278,6 +277,7 @@ static void ma_append(struct ma_state *ms, void *entry)
                mr64->pivot[idx] = ms->index - 1;
        }
 }
+
 static void ma_root_expand(struct ma_state *ms, void *entry)
 {
        void *r_entry = ms->tree->ma_root;  // root entry
@@ -292,18 +292,12 @@ static void ma_root_expand(struct ma_state *ms, void *entry)
        mn->parent = (struct maple_node*)
                      ((unsigned long)ms->tree | MA_ROOT_PARENT);
 
+       /* Assign the old entry to slot 0, or set it to null. */
+       RCU_INIT_POINTER(mn->mr64.slot[0], r_entry);
+       if (!r_entry)
+               mn->mr64.pivot[0] = ms->index - 1;
 
-       /*
-        * Insert the existing entry into the new node
-        * rcu_assign is not necessary as readers are not able to access this
-        * node.
-        */
-       if (r_entry != NULL) {
-               RCU_INIT_POINTER(mn->mr64.slot[0], r_entry);
-               mn->mr64.pivot[0] = 0;
-       }
        ma_append(ms, entry);
-
        /* swap the new root into the tree */
        rcu_assign_pointer(ms->tree->ma_root, mt_mk_node(mn, maple_leaf_64));
 }
@@ -337,7 +331,6 @@ static unsigned char mas_walk_r64(struct ma_state *ms, unsigned long val)
                        break;
        } while (i++ < MAPLE_RANGE64_SLOTS - 1);
 
-       ms_update_limits(ms, i);
        ms->node = rcu_dereference(mr64->slot[i]);
        return i;
 }
@@ -362,6 +355,7 @@ void *ma_insert(struct ma_state *ms, void *entry)
        do {
                ms->node = mt_to_node(e_entry);
                p_entry = ms->node;
+               ms_update_limits(ms, slot);
                slot = mas_walk_r64(ms, ms->index);
                e_entry = ms->node;
        } while (xa_is_node(e_entry));
@@ -392,6 +386,7 @@ exists:
 void *mas_walk(struct ma_state *ms)
 {
        void *entry = mas_start(ms);
+       unsigned char slot;
 
        /* Outside this nodes range, it doesn't exist. */
        if (ms->min > ms->index ||
@@ -400,13 +395,14 @@ void *mas_walk(struct ma_state *ms)
 
        while (xa_is_node(entry)) {
                ms->node = mt_to_node(entry);
-               mas_walk_r64(ms, ms->index);
+               ms_update_limits(ms, slot);
+               slot = mas_walk_r64(ms, ms->index);
                entry = ms->node;
        }
        return entry;
 }
 
-void *ma_destroy_walk(struct ma_state *mas)
+void ma_destroy_walk(struct ma_state *mas)
 {
        struct maple_node *mn = mas->node;
        unsigned int type = mt_node_type(mas->node);