mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-29 14:05:19 +08:00
3e252fa7d4
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.com Signed-off-by: Ross 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
66 lines
2.5 KiB
C
66 lines
2.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#include <linux/gfp.h>
|
|
#include <linux/types.h>
|
|
#include <linux/radix-tree.h>
|
|
#include <linux/rcupdate.h>
|
|
|
|
struct item {
|
|
struct rcu_head rcu_head;
|
|
unsigned long index;
|
|
unsigned int order;
|
|
};
|
|
|
|
struct item *item_create(unsigned long index, unsigned int order);
|
|
int __item_insert(struct radix_tree_root *root, struct item *item);
|
|
int item_insert(struct radix_tree_root *root, unsigned long index);
|
|
int item_insert_order(struct radix_tree_root *root, unsigned long index,
|
|
unsigned order);
|
|
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);
|
|
|
|
void item_check_present(struct radix_tree_root *root, unsigned long index);
|
|
void item_check_absent(struct radix_tree_root *root, unsigned long index);
|
|
void item_gang_check_present(struct radix_tree_root *root,
|
|
unsigned long start, unsigned long nr,
|
|
int chunk, int hop);
|
|
void item_full_scan(struct radix_tree_root *root, unsigned long start,
|
|
unsigned long nr, int chunk);
|
|
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 tag_check(void);
|
|
void multiorder_checks(void);
|
|
void iteration_test(unsigned order, unsigned duration);
|
|
void benchmark(void);
|
|
void idr_checks(void);
|
|
void ida_checks(void);
|
|
void ida_thread_tests(void);
|
|
|
|
struct item *
|
|
item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
|
|
struct item *
|
|
item_tag_clear(struct radix_tree_root *root, unsigned long index, int tag);
|
|
int item_tag_get(struct radix_tree_root *root, unsigned long index, int tag);
|
|
void tree_verify_min_height(struct radix_tree_root *root, int maxindex);
|
|
void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag);
|
|
|
|
extern int nr_allocated;
|
|
|
|
/* Normally private parts of lib/radix-tree.c */
|
|
struct radix_tree_node *entry_to_node(void *ptr);
|
|
void radix_tree_dump(struct radix_tree_root *root);
|
|
int root_tag_get(struct radix_tree_root *root, unsigned int tag);
|
|
unsigned long node_maxindex(struct radix_tree_node *);
|
|
unsigned long shift_maxindex(unsigned int shift);
|
|
int radix_tree_cpu_dead(unsigned int cpu);
|
|
struct radix_tree_preload {
|
|
unsigned nr;
|
|
struct radix_tree_node *nodes;
|
|
};
|
|
extern struct radix_tree_preload radix_tree_preloads;
|