shmem: Convert find_swap_entry to XArray
authorMatthew Wilcox <willy@infradead.org>
Wed, 22 Nov 2017 13:36:00 +0000 (08:36 -0500)
committerMatthew Wilcox <willy@infradead.org>
Sun, 21 Oct 2018 14:46:39 +0000 (10:46 -0400)
This is a 1:1 conversion.  The major part of this patch is converting
the test framework from userspace to kernel space and mirroring the
algorithm now used in find_swap_entry().

Signed-off-by: Matthew Wilcox <willy@infradead.org>
lib/test_xarray.c
mm/shmem.c
tools/testing/radix-tree/main.c
tools/testing/radix-tree/test.c
tools/testing/radix-tree/test.h

index 128c648..815daff 100644 (file)
@@ -631,6 +631,61 @@ static noinline void check_find(struct xarray *xa)
        check_multi_find_2(xa);
 }
 
+/* See find_swap_entry() in mm/shmem.c */
+static noinline unsigned long xa_find_entry(struct xarray *xa, void *item)
+{
+       XA_STATE(xas, xa, 0);
+       unsigned int checked = 0;
+       void *entry;
+
+       rcu_read_lock();
+       xas_for_each(&xas, entry, ULONG_MAX) {
+               if (xas_retry(&xas, entry))
+                       continue;
+               if (entry == item)
+                       break;
+               checked++;
+               if ((checked % 4) != 0)
+                       continue;
+               xas_pause(&xas);
+       }
+       rcu_read_unlock();
+
+       return entry ? xas.xa_index : -1;
+}
+
+static noinline void check_find_entry(struct xarray *xa)
+{
+#ifdef CONFIG_XARRAY_MULTI
+       unsigned int order;
+       unsigned long offset, index;
+
+       for (order = 0; order < 20; order++) {
+               for (offset = 0; offset < (1UL << (order + 3));
+                    offset += (1UL << order)) {
+                       for (index = 0; index < (1UL << (order + 5));
+                            index += (1UL << order)) {
+                               xa_store_order(xa, index, order,
+                                               xa_mk_value(index), GFP_KERNEL);
+                               XA_BUG_ON(xa, xa_load(xa, index) !=
+                                               xa_mk_value(index));
+                               XA_BUG_ON(xa, xa_find_entry(xa,
+                                               xa_mk_value(index)) != index);
+                       }
+                       XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1);
+                       xa_destroy(xa);
+               }
+       }
+#endif
+
+       XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1);
+       xa_store_index(xa, ULONG_MAX, GFP_KERNEL);
+       XA_BUG_ON(xa, xa_find_entry(xa, xa) != -1);
+       XA_BUG_ON(xa, xa_find_entry(xa, xa_mk_value(LONG_MAX)) != -1);
+       xa_erase_index(xa, ULONG_MAX);
+       XA_BUG_ON(xa, !xa_empty(xa));
+}
+
 static noinline void check_move_small(struct xarray *xa, unsigned long idx)
 {
        XA_STATE(xas, xa, 0);
@@ -972,6 +1027,7 @@ static int xarray_checks(void)
        check_multi_store(&array);
        check_xa_alloc();
        check_find(&array);
+       check_find_entry(&array);
        check_destroy(&array);
        check_move(&array);
        check_create_range(&array);
index ce91569..a305529 100644 (file)
@@ -1100,34 +1100,27 @@ static void shmem_evict_inode(struct inode *inode)
        clear_inode(inode);
 }
 
-static unsigned long find_swap_entry(struct radix_tree_root *root, void *item)
+static unsigned long find_swap_entry(struct xarray *xa, void *item)
 {
-       struct radix_tree_iter iter;
-       void __rcu **slot;
-       unsigned long found = -1;
+       XA_STATE(xas, xa, 0);
        unsigned int checked = 0;
+       void *entry;
 
        rcu_read_lock();
-       radix_tree_for_each_slot(slot, root, &iter, 0) {
-               void *entry = radix_tree_deref_slot(slot);
-
-               if (radix_tree_deref_retry(entry)) {
-                       slot = radix_tree_iter_retry(&iter);
+       xas_for_each(&xas, entry, ULONG_MAX) {
+               if (xas_retry(&xas, entry))
                        continue;
-               }
-               if (entry == item) {
-                       found = iter.index;
+               if (entry == item)
                        break;
-               }
                checked++;
-               if ((checked % 4096) != 0)
+               if ((checked % XA_CHECK_SCHED) != 0)
                        continue;
-               slot = radix_tree_iter_resume(slot, &iter);
+               xas_pause(&xas);
                cond_resched_rcu();
        }
-
        rcu_read_unlock();
-       return found;
+
+       return entry ? xas.xa_index : -1;
 }
 
 /*
index 09deaf4..79589ea 100644 (file)
@@ -236,63 +236,6 @@ void copy_tag_check(void)
        item_kill_tree(&tree);
 }
 
-static void __locate_check(struct radix_tree_root *tree, unsigned long index,
-                       unsigned order)
-{
-       struct item *item;
-       unsigned long index2;
-
-       item_insert_order(tree, index, order);
-       item = item_lookup(tree, index);
-       index2 = find_item(tree, item);
-       if (index != index2) {
-               printv(2, "index %ld order %d inserted; found %ld\n",
-                       index, order, index2);
-               abort();
-       }
-}
-
-static void __order_0_locate_check(void)
-{
-       RADIX_TREE(tree, GFP_KERNEL);
-       int i;
-
-       for (i = 0; i < 50; i++)
-               __locate_check(&tree, rand() % INT_MAX, 0);
-
-       item_kill_tree(&tree);
-}
-
-static void locate_check(void)
-{
-       RADIX_TREE(tree, GFP_KERNEL);
-       unsigned order;
-       unsigned long offset, index;
-
-       __order_0_locate_check();
-
-       for (order = 0; order < 20; order++) {
-               for (offset = 0; offset < (1 << (order + 3));
-                    offset += (1UL << order)) {
-                       for (index = 0; index < (1UL << (order + 5));
-                            index += (1UL << order)) {
-                               __locate_check(&tree, index + offset, order);
-                       }
-                       if (find_item(&tree, &tree) != -1)
-                               abort();
-
-                       item_kill_tree(&tree);
-               }
-       }
-
-       if (find_item(&tree, &tree) != -1)
-               abort();
-       __locate_check(&tree, -1, 0);
-       if (find_item(&tree, &tree) != -1)
-               abort();
-       item_kill_tree(&tree);
-}
-
 static void single_thread_tests(bool long_run)
 {
        int i;
@@ -303,10 +246,6 @@ static void single_thread_tests(bool long_run)
        rcu_barrier();
        printv(2, "after multiorder_check: %d allocated, preempt %d\n",
                nr_allocated, preempt_count);
-       locate_check();
-       rcu_barrier();
-       printv(2, "after locate_check: %d allocated, preempt %d\n",
-               nr_allocated, preempt_count);
        tag_check();
        rcu_barrier();
        printv(2, "after tag_check: %d allocated, preempt %d\n",
index 70ddf96..470419b 100644 (file)
@@ -209,28 +209,6 @@ int tag_tagged_items(struct radix_tree_root *root, pthread_mutex_t *lock,
        return tagged;
 }
 
-/* Use the same pattern as find_swap_entry() in mm/shmem.c */
-unsigned long find_item(struct radix_tree_root *root, void *item)
-{
-       struct radix_tree_iter iter;
-       void **slot;
-       unsigned long found = -1;
-       unsigned long checked = 0;
-
-       radix_tree_for_each_slot(slot, root, &iter, 0) {
-               if (*slot == item) {
-                       found = iter.index;
-                       break;
-               }
-               checked++;
-               if ((checked % 4) != 0)
-                       continue;
-               slot = radix_tree_iter_resume(slot, &iter);
-       }
-
-       return found;
-}
-
 static int verify_node(struct radix_tree_node *slot, unsigned int tag,
                        int tagged)
 {
index e3dc7a1..9532c18 100644 (file)
@@ -32,7 +32,6 @@ void item_kill_tree(struct radix_tree_root *root);
 int tag_tagged_items(struct radix_tree_root *, pthread_mutex_t *,
                        unsigned long start, unsigned long end, unsigned batch,
                        unsigned iftag, unsigned thentag);
-unsigned long find_item(struct radix_tree_root *, void *item);
 
 void xarray_tests(void);
 void tag_check(void);