]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
maple tree test: Iterate over a partially deleted tree
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 16 Oct 2019 20:03:18 +0000 (16:03 -0400)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Wed, 16 Oct 2019 20:03:18 +0000 (16:03 -0400)
Move mas_reset() to the header file and add mas_retry() to mirror
xas_retry().  Fix a few minor typos too.  Each time we delete an
entry from the tree, iterate over the tree to be sure we can still
do that correctly.  It fails once we've deleted the first node.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
include/linux/maple_tree.h
lib/maple_tree.c
lib/test_maple_tree.c

index b956d3724a47b5c89be656f9088689bf1213061b..7044673725097914b5d3e148cbc461c8481a1841 100644 (file)
@@ -304,6 +304,47 @@ bool mas_nomem(struct ma_state *mas, gfp_t gfp);
 void mas_pause(struct ma_state *mas);
 void maple_tree_init(void);
 
+/**
+ * mas_reset() - Reset a Maple Tree operation state.
+ * @mas: Maple Tree operation state.
+ *
+ * Resets the error or walk state of the @mas so future walks of the
+ * array will start from the root.  Use this if you have dropped the
+ * lock and want to reuse the ma_state.
+ *
+ * Context: Any context.
+ */
+static inline void mas_reset(struct ma_state *mas)
+{
+       mas->node = MAS_START;
+}
+
+/**
+ * mas_retry() - Retry the operation if appropriate.
+ * @mas: Maple Tree operation state.
+ * @entry: Entry from tree.
+ *
+ * The advanced functions may sometimes return an internal entry, such as
+ * a retry entry or a zero entry.  This function sets up the @mas to restart
+ * the walk from the head of the array if needed.
+ *
+ * Context: Any context.
+ * Return: true if the operation needs to be retried.
+ */
+static inline bool mas_retry(struct ma_state *mas, const void *entry)
+{
+       if (xa_is_skip(entry))
+               return true;
+       if (xa_is_deleted(entry))
+               return true;
+       if (xa_is_zero(entry))
+               return true;
+       if (!xa_is_retry(entry))
+               return false;
+       mas_reset(mas);
+       return true;
+}
+
 /**
  * mas_for_each() - Iterate over a range of the maple tree.
  * @mas: Maple Tree operation state (maple_state)
@@ -331,9 +372,10 @@ void maple_tree_init(void);
 #define mt_for_each(tree, entry, index, max) \
        for (entry = mt_find(mt, index, max); \
             entry; entry = mt_find_after(mt, &index, max))
+
 /**
  * mas_set_range() - Set up Maple Tree operation state for a different index.
- * @xas: Maple Tree operation state.
+ * @mas: Maple Tree operation state.
  * @start: New start of range in the Maple Tree.
  * @last: New end of range in the Maple Tree.
  *
@@ -351,7 +393,7 @@ static inline void mas_set_range(struct ma_state *mas, unsigned long start,
 
 /**
  * mas_set() - Set up Maple Tree operation state for a different index.
- * @xas: Maple Tree operation state.
+ * @mas: Maple Tree operation state.
  * @index: New index into the Maple Tree.
  *
  * Move the operation state to refer to a different index.  This will
@@ -362,5 +404,4 @@ static inline void mas_set(struct ma_state *mas, unsigned long index)
 {
        mas_set_range(mas, index, index);
 }
-
 #endif
index 4f31c361eff9f0b628d3f7b7ab8a9814a5ec499a..dd0360f634f935352b70862f26206dd034e09bcf 100644 (file)
@@ -178,11 +178,6 @@ static inline bool mas_is_start(struct ma_state *mas)
        return mas->node == MAS_START;
 }
 
-void mas_reset(struct ma_state *mas)
-{
-       mas->node = MAS_START;
-}
-
 static inline struct maple_node *mte_to_node(const struct maple_enode *entry)
 {
        return (struct maple_node *)((unsigned long)entry & ~127);
index 594d012c8376747e9e1a4c2f81a2855b121225c8..d50834174993b09ff37d91744649d478dc903211 100644 (file)
@@ -495,6 +495,17 @@ static noinline void check_find_2(struct maple_tree *mt)
 
        for (i = 0; i < 256; i++) {
                mtree_erase_index(mt, i);
+               j = i + 1;
+               mas_set(&mas, 0);
+               rcu_read_lock();
+               mas_for_each(&mas, entry, ULONG_MAX) {
+                       if (mas_retry(&mas, entry))
+                               continue;
+                       MT_BUG_ON(mt, entry != xa_mk_value(j));
+                       j++;
+               }
+               rcu_read_unlock();
+               MT_BUG_ON(mt, j != 256);
        }
 
        MT_BUG_ON(mt, !mtree_empty(mt));