mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 22:21:21 +00:00
radix_tree: exceptional entries and indices
A patchset to extend tmpfs to MAX_LFS_FILESIZE by abandoning its peculiar swap vector, instead keeping a file's swap entries in the same radix tree as its struct page pointers: thus saving memory, and simplifying its code and locking. This patch: The radix_tree is used by several subsystems for different purposes. A major use is to store the struct page pointers of a file's pagecache for memory management. But what if mm wanted to store something other than page pointers there too? The low bit of a radix_tree entry is already used to denote an indirect pointer, for internal use, and the unlikely radix_tree_deref_retry() case. Define the next bit as denoting an exceptional entry, and supply inline functions radix_tree_exception() to return non-0 in either unlikely case, and radix_tree_exceptional_entry() to return non-0 in the second case. If a subsystem already uses radix_tree with that bit set, no problem: it does not affect internal workings at all, but is defined for the convenience of those storing well-aligned pointers in the radix_tree. The radix_tree_gang_lookups have an implicit assumption that the caller can deduce the offset of each entry returned e.g. by the page->index of a struct page. But that may not be feasible for some kinds of item to be stored there. radix_tree_gang_lookup_slot() allow for an optional indices argument, output array in which to return those offsets. The same could be added to other radix_tree_gang_lookups, but for now keep it to the only one for which we need it. Signed-off-by: Hugh Dickins <hughd@google.com> Acked-by: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
70d327198a
commit
6328650bb4
3 changed files with 54 additions and 15 deletions
|
@ -823,8 +823,8 @@ unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
|
|||
EXPORT_SYMBOL(radix_tree_prev_hole);
|
||||
|
||||
static unsigned int
|
||||
__lookup(struct radix_tree_node *slot, void ***results, unsigned long index,
|
||||
unsigned int max_items, unsigned long *next_index)
|
||||
__lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices,
|
||||
unsigned long index, unsigned int max_items, unsigned long *next_index)
|
||||
{
|
||||
unsigned int nr_found = 0;
|
||||
unsigned int shift, height;
|
||||
|
@ -857,12 +857,16 @@ __lookup(struct radix_tree_node *slot, void ***results, unsigned long index,
|
|||
|
||||
/* Bottom level: grab some items */
|
||||
for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
|
||||
index++;
|
||||
if (slot->slots[i]) {
|
||||
results[nr_found++] = &(slot->slots[i]);
|
||||
if (nr_found == max_items)
|
||||
results[nr_found] = &(slot->slots[i]);
|
||||
if (indices)
|
||||
indices[nr_found] = index;
|
||||
if (++nr_found == max_items) {
|
||||
index++;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
out:
|
||||
*next_index = index;
|
||||
|
@ -918,8 +922,8 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
|
|||
|
||||
if (cur_index > max_index)
|
||||
break;
|
||||
slots_found = __lookup(node, (void ***)results + ret, cur_index,
|
||||
max_items - ret, &next_index);
|
||||
slots_found = __lookup(node, (void ***)results + ret, NULL,
|
||||
cur_index, max_items - ret, &next_index);
|
||||
nr_found = 0;
|
||||
for (i = 0; i < slots_found; i++) {
|
||||
struct radix_tree_node *slot;
|
||||
|
@ -944,6 +948,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
|
|||
* radix_tree_gang_lookup_slot - perform multiple slot lookup on radix tree
|
||||
* @root: radix tree root
|
||||
* @results: where the results of the lookup are placed
|
||||
* @indices: where their indices should be placed (but usually NULL)
|
||||
* @first_index: start the lookup from this key
|
||||
* @max_items: place up to this many items at *results
|
||||
*
|
||||
|
@ -958,7 +963,8 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
|
|||
* protection, radix_tree_deref_slot may fail requiring a retry.
|
||||
*/
|
||||
unsigned int
|
||||
radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
|
||||
radix_tree_gang_lookup_slot(struct radix_tree_root *root,
|
||||
void ***results, unsigned long *indices,
|
||||
unsigned long first_index, unsigned int max_items)
|
||||
{
|
||||
unsigned long max_index;
|
||||
|
@ -974,6 +980,8 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
|
|||
if (first_index > 0)
|
||||
return 0;
|
||||
results[0] = (void **)&root->rnode;
|
||||
if (indices)
|
||||
indices[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
node = indirect_to_ptr(node);
|
||||
|
@ -987,8 +995,9 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
|
|||
|
||||
if (cur_index > max_index)
|
||||
break;
|
||||
slots_found = __lookup(node, results + ret, cur_index,
|
||||
max_items - ret, &next_index);
|
||||
slots_found = __lookup(node, results + ret,
|
||||
indices ? indices + ret : NULL,
|
||||
cur_index, max_items - ret, &next_index);
|
||||
ret += slots_found;
|
||||
if (next_index == 0)
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue