Commit 478922e2 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

radix-tree: delete radix_tree_locate_item()

This rather complicated function can be better implemented as an
iterator.  It has only one caller, so move the functionality to the only
place that needs it.  Update the test suite to follow the same pattern.

Link: http://lkml.kernel.org/r/1480369871-5271-56-git-send-email-mawilcox@linuxonhyperv.comSigned-off-by: default avatarMatthew Wilcox <mawilcox@microsoft.com>
Acked-by: default avatarKonstantin Khlebnikov <koct9i@gmail.com>
Tested-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Matthew Wilcox <mawilcox@microsoft.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 148deab2
...@@ -296,7 +296,6 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root, ...@@ -296,7 +296,6 @@ unsigned long radix_tree_range_tag_if_tagged(struct radix_tree_root *root,
unsigned long nr_to_tag, unsigned long nr_to_tag,
unsigned int fromtag, unsigned int totag); unsigned int fromtag, unsigned int totag);
int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag); int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item);
static inline void radix_tree_preload_end(void) static inline void radix_tree_preload_end(void)
{ {
......
...@@ -1579,105 +1579,6 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results, ...@@ -1579,105 +1579,6 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
} }
EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot); EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot);
#if defined(CONFIG_SHMEM) && defined(CONFIG_SWAP)
#include <linux/sched.h> /* for cond_resched() */
struct locate_info {
unsigned long found_index;
bool stop;
};
/*
* This linear search is at present only useful to shmem_unuse_inode().
*/
static unsigned long __locate(struct radix_tree_node *slot, void *item,
unsigned long index, struct locate_info *info)
{
unsigned long i;
do {
unsigned int shift = slot->shift;
for (i = (index >> shift) & RADIX_TREE_MAP_MASK;
i < RADIX_TREE_MAP_SIZE;
i++, index += (1UL << shift)) {
struct radix_tree_node *node =
rcu_dereference_raw(slot->slots[i]);
if (node == RADIX_TREE_RETRY)
goto out;
if (!radix_tree_is_internal_node(node)) {
if (node == item) {
info->found_index = index;
info->stop = true;
goto out;
}
continue;
}
node = entry_to_node(node);
if (is_sibling_entry(slot, node))
continue;
slot = node;
break;
}
} while (i < RADIX_TREE_MAP_SIZE);
out:
if ((index == 0) && (i == RADIX_TREE_MAP_SIZE))
info->stop = true;
return index;
}
/**
* radix_tree_locate_item - search through radix tree for item
* @root: radix tree root
* @item: item to be found
*
* Returns index where item was found, or -1 if not found.
* Caller must hold no lock (since this time-consuming function needs
* to be preemptible), and must check afterwards if item is still there.
*/
unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
{
struct radix_tree_node *node;
unsigned long max_index;
unsigned long cur_index = 0;
struct locate_info info = {
.found_index = -1,
.stop = false,
};
do {
rcu_read_lock();
node = rcu_dereference_raw(root->rnode);
if (!radix_tree_is_internal_node(node)) {
rcu_read_unlock();
if (node == item)
info.found_index = 0;
break;
}
node = entry_to_node(node);
max_index = node_maxindex(node);
if (cur_index > max_index) {
rcu_read_unlock();
break;
}
cur_index = __locate(node, item, cur_index, &info);
rcu_read_unlock();
cond_resched();
} while (!info.stop && cur_index <= max_index);
return info.found_index;
}
#else
unsigned long radix_tree_locate_item(struct radix_tree_root *root, void *item)
{
return -1;
}
#endif /* CONFIG_SHMEM && CONFIG_SWAP */
/** /**
* __radix_tree_delete_node - try to free node after clearing a slot * __radix_tree_delete_node - try to free node after clearing a slot
* @root: radix tree root * @root: radix tree root
......
...@@ -1049,6 +1049,30 @@ static void shmem_evict_inode(struct inode *inode) ...@@ -1049,6 +1049,30 @@ static void shmem_evict_inode(struct inode *inode)
clear_inode(inode); clear_inode(inode);
} }
static unsigned long find_swap_entry(struct radix_tree_root *root, void *item)
{
struct radix_tree_iter iter;
void **slot;
unsigned long found = -1;
unsigned int checked = 0;
rcu_read_lock();
radix_tree_for_each_slot(slot, root, &iter, 0) {
if (*slot == item) {
found = iter.index;
break;
}
checked++;
if ((checked % 4096) != 0)
continue;
slot = radix_tree_iter_resume(slot, &iter);
cond_resched_rcu();
}
rcu_read_unlock();
return found;
}
/* /*
* If swap found in inode, free it and move page from swapcache to filecache. * If swap found in inode, free it and move page from swapcache to filecache.
*/ */
...@@ -1062,7 +1086,7 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, ...@@ -1062,7 +1086,7 @@ static int shmem_unuse_inode(struct shmem_inode_info *info,
int error = 0; int error = 0;
radswap = swp_to_radix_entry(swap); radswap = swp_to_radix_entry(swap);
index = radix_tree_locate_item(&mapping->page_tree, radswap); index = find_swap_entry(&mapping->page_tree, radswap);
if (index == -1) if (index == -1)
return -EAGAIN; /* tell shmem_unuse we found nothing */ return -EAGAIN; /* tell shmem_unuse we found nothing */
......
...@@ -239,7 +239,7 @@ static void __locate_check(struct radix_tree_root *tree, unsigned long index, ...@@ -239,7 +239,7 @@ static void __locate_check(struct radix_tree_root *tree, unsigned long index,
item_insert_order(tree, index, order); item_insert_order(tree, index, order);
item = item_lookup(tree, index); item = item_lookup(tree, index);
index2 = radix_tree_locate_item(tree, item); index2 = find_item(tree, item);
if (index != index2) { if (index != index2) {
printf("index %ld order %d inserted; found %ld\n", printf("index %ld order %d inserted; found %ld\n",
index, order, index2); index, order, index2);
...@@ -273,17 +273,17 @@ static void locate_check(void) ...@@ -273,17 +273,17 @@ static void locate_check(void)
index += (1UL << order)) { index += (1UL << order)) {
__locate_check(&tree, index + offset, order); __locate_check(&tree, index + offset, order);
} }
if (radix_tree_locate_item(&tree, &tree) != -1) if (find_item(&tree, &tree) != -1)
abort(); abort();
item_kill_tree(&tree); item_kill_tree(&tree);
} }
} }
if (radix_tree_locate_item(&tree, &tree) != -1) if (find_item(&tree, &tree) != -1)
abort(); abort();
__locate_check(&tree, -1, 0); __locate_check(&tree, -1, 0);
if (radix_tree_locate_item(&tree, &tree) != -1) if (find_item(&tree, &tree) != -1)
abort(); abort();
item_kill_tree(&tree); item_kill_tree(&tree);
} }
......
...@@ -151,6 +151,28 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start, ...@@ -151,6 +151,28 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
assert(nfound == 0); assert(nfound == 0);
} }
/* 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, static int verify_node(struct radix_tree_node *slot, unsigned int tag,
int tagged) int tagged)
{ {
......
...@@ -25,6 +25,8 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start, ...@@ -25,6 +25,8 @@ void item_full_scan(struct radix_tree_root *root, unsigned long start,
unsigned long nr, int chunk); unsigned long nr, int chunk);
void item_kill_tree(struct radix_tree_root *root); void item_kill_tree(struct radix_tree_root *root);
unsigned long find_item(struct radix_tree_root *, void *item);
void tag_check(void); void tag_check(void);
void multiorder_checks(void); void multiorder_checks(void);
void iteration_test(void); void iteration_test(void);
......
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