Commit 3e252fa7 authored by Ross Zwisler's avatar Ross Zwisler Committed by Linus Torvalds

radix tree test suite: add item_delete_rcu()

Currently the lifetime of "struct item" entries in the radix tree are
not controlled by RCU, but are instead deleted inline as they are
removed from the tree.

In the following patches we add a test which has threads iterating over
items pulled from the tree and verifying them in an
rcu_read_lock()/rcu_read_unlock() section.  This means that though an
item has been removed from the tree it could still be being worked on by
other threads until the RCU grace period expires.  So, we need to
actually free the "struct item" structures at the end of the grace
period, just as we do with "struct radix_tree_node" items.

Link: http://lkml.kernel.org/r/20180503192430.7582-4-ross.zwisler@linux.intel.comSigned-off-by: default avatarRoss Zwisler <ross.zwisler@linux.intel.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: CR, Sapthagirish <sapthagirish.cr@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Matthew Wilcox <willy@infradead.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent dcbbf25a
...@@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index) ...@@ -75,6 +75,25 @@ int item_delete(struct radix_tree_root *root, unsigned long index)
return 0; return 0;
} }
static void item_free_rcu(struct rcu_head *head)
{
struct item *item = container_of(head, struct item, rcu_head);
free(item);
}
int item_delete_rcu(struct radix_tree_root *root, unsigned long index)
{
struct item *item = radix_tree_delete(root, index);
if (item) {
item_sanity(item, index);
call_rcu(&item->rcu_head, item_free_rcu);
return 1;
}
return 0;
}
void item_check_present(struct radix_tree_root *root, unsigned long index) void item_check_present(struct radix_tree_root *root, unsigned long index)
{ {
struct item *item; struct item *item;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
struct item { struct item {
struct rcu_head rcu_head;
unsigned long index; unsigned long index;
unsigned int order; unsigned int order;
}; };
...@@ -15,6 +16,7 @@ int item_insert(struct radix_tree_root *root, unsigned long index); ...@@ -15,6 +16,7 @@ int item_insert(struct radix_tree_root *root, unsigned long index);
int item_insert_order(struct radix_tree_root *root, unsigned long index, int item_insert_order(struct radix_tree_root *root, unsigned long index,
unsigned order); unsigned order);
int item_delete(struct radix_tree_root *root, unsigned long index); int item_delete(struct radix_tree_root *root, unsigned long index);
int item_delete_rcu(struct radix_tree_root *root, unsigned long index);
struct item *item_lookup(struct radix_tree_root *root, unsigned long index); struct item *item_lookup(struct radix_tree_root *root, unsigned long index);
void item_check_present(struct radix_tree_root *root, unsigned long index); void item_check_present(struct radix_tree_root *root, unsigned long index);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment