aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/radix-tree.h36
-rw-r--r--lib/radix-tree.c29
-rw-r--r--mm/filemap.c4
3 files changed, 54 insertions, 15 deletions
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 23241c2fecce..b7edf8251455 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -39,7 +39,15 @@
39 * when it is shrunk, before we rcu free the node. See shrink code for 39 * when it is shrunk, before we rcu free the node. See shrink code for
40 * details. 40 * details.
41 */ 41 */
42#define RADIX_TREE_INDIRECT_PTR 1 42#define RADIX_TREE_INDIRECT_PTR 1
43/*
44 * A common use of the radix tree is to store pointers to struct pages;
45 * but shmem/tmpfs needs also to store swap entries in the same tree:
46 * those are marked as exceptional entries to distinguish them.
47 * EXCEPTIONAL_ENTRY tests the bit, EXCEPTIONAL_SHIFT shifts content past it.
48 */
49#define RADIX_TREE_EXCEPTIONAL_ENTRY 2
50#define RADIX_TREE_EXCEPTIONAL_SHIFT 2
43 51
44#define radix_tree_indirect_to_ptr(ptr) \ 52#define radix_tree_indirect_to_ptr(ptr) \
45 radix_tree_indirect_to_ptr((void __force *)(ptr)) 53 radix_tree_indirect_to_ptr((void __force *)(ptr))
@@ -174,6 +182,28 @@ static inline int radix_tree_deref_retry(void *arg)
174} 182}
175 183
176/** 184/**
185 * radix_tree_exceptional_entry - radix_tree_deref_slot gave exceptional entry?
186 * @arg: value returned by radix_tree_deref_slot
187 * Returns: 0 if well-aligned pointer, non-0 if exceptional entry.
188 */
189static inline int radix_tree_exceptional_entry(void *arg)
190{
191 /* Not unlikely because radix_tree_exception often tested first */
192 return (unsigned long)arg & RADIX_TREE_EXCEPTIONAL_ENTRY;
193}
194
195/**
196 * radix_tree_exception - radix_tree_deref_slot returned either exception?
197 * @arg: value returned by radix_tree_deref_slot
198 * Returns: 0 if well-aligned pointer, non-0 if either kind of exception.
199 */
200static inline int radix_tree_exception(void *arg)
201{
202 return unlikely((unsigned long)arg &
203 (RADIX_TREE_INDIRECT_PTR | RADIX_TREE_EXCEPTIONAL_ENTRY));
204}
205
206/**
177 * radix_tree_replace_slot - replace item in a slot 207 * radix_tree_replace_slot - replace item in a slot
178 * @pslot: pointer to slot, returned by radix_tree_lookup_slot 208 * @pslot: pointer to slot, returned by radix_tree_lookup_slot
179 * @item: new item to store in the slot. 209 * @item: new item to store in the slot.
@@ -194,8 +224,8 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
194unsigned int 224unsigned int
195radix_tree_gang_lookup(struct radix_tree_root *root, void **results, 225radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
196 unsigned long first_index, unsigned int max_items); 226 unsigned long first_index, unsigned int max_items);
197unsigned int 227unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root,
198radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results, 228 void ***results, unsigned long *indices,
199 unsigned long first_index, unsigned int max_items); 229 unsigned long first_index, unsigned int max_items);
200unsigned long radix_tree_next_hole(struct radix_tree_root *root, 230unsigned long radix_tree_next_hole(struct radix_tree_root *root,
201 unsigned long index, unsigned long max_scan); 231 unsigned long index, unsigned long max_scan);
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 7ea2e033d715..348eaefbed74 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -823,8 +823,8 @@ unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
823EXPORT_SYMBOL(radix_tree_prev_hole); 823EXPORT_SYMBOL(radix_tree_prev_hole);
824 824
825static unsigned int 825static unsigned int
826__lookup(struct radix_tree_node *slot, void ***results, unsigned long index, 826__lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices,
827 unsigned int max_items, unsigned long *next_index) 827 unsigned long index, unsigned int max_items, unsigned long *next_index)
828{ 828{
829 unsigned int nr_found = 0; 829 unsigned int nr_found = 0;
830 unsigned int shift, height; 830 unsigned int shift, height;
@@ -857,12 +857,16 @@ __lookup(struct radix_tree_node *slot, void ***results, unsigned long index,
857 857
858 /* Bottom level: grab some items */ 858 /* Bottom level: grab some items */
859 for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) { 859 for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
860 index++;
861 if (slot->slots[i]) { 860 if (slot->slots[i]) {
862 results[nr_found++] = &(slot->slots[i]); 861 results[nr_found] = &(slot->slots[i]);
863 if (nr_found == max_items) 862 if (indices)
863 indices[nr_found] = index;
864 if (++nr_found == max_items) {
865 index++;
864 goto out; 866 goto out;
867 }
865 } 868 }
869 index++;
866 } 870 }
867out: 871out:
868 *next_index = index; 872 *next_index = index;
@@ -918,8 +922,8 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
918 922
919 if (cur_index > max_index) 923 if (cur_index > max_index)
920 break; 924 break;
921 slots_found = __lookup(node, (void ***)results + ret, cur_index, 925 slots_found = __lookup(node, (void ***)results + ret, NULL,
922 max_items - ret, &next_index); 926 cur_index, max_items - ret, &next_index);
923 nr_found = 0; 927 nr_found = 0;
924 for (i = 0; i < slots_found; i++) { 928 for (i = 0; i < slots_found; i++) {
925 struct radix_tree_node *slot; 929 struct radix_tree_node *slot;
@@ -944,6 +948,7 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
944 * radix_tree_gang_lookup_slot - perform multiple slot lookup on radix tree 948 * radix_tree_gang_lookup_slot - perform multiple slot lookup on radix tree
945 * @root: radix tree root 949 * @root: radix tree root
946 * @results: where the results of the lookup are placed 950 * @results: where the results of the lookup are placed
951 * @indices: where their indices should be placed (but usually NULL)
947 * @first_index: start the lookup from this key 952 * @first_index: start the lookup from this key
948 * @max_items: place up to this many items at *results 953 * @max_items: place up to this many items at *results
949 * 954 *
@@ -958,7 +963,8 @@ EXPORT_SYMBOL(radix_tree_gang_lookup);
958 * protection, radix_tree_deref_slot may fail requiring a retry. 963 * protection, radix_tree_deref_slot may fail requiring a retry.
959 */ 964 */
960unsigned int 965unsigned int
961radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results, 966radix_tree_gang_lookup_slot(struct radix_tree_root *root,
967 void ***results, unsigned long *indices,
962 unsigned long first_index, unsigned int max_items) 968 unsigned long first_index, unsigned int max_items)
963{ 969{
964 unsigned long max_index; 970 unsigned long max_index;
@@ -974,6 +980,8 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
974 if (first_index > 0) 980 if (first_index > 0)
975 return 0; 981 return 0;
976 results[0] = (void **)&root->rnode; 982 results[0] = (void **)&root->rnode;
983 if (indices)
984 indices[0] = 0;
977 return 1; 985 return 1;
978 } 986 }
979 node = indirect_to_ptr(node); 987 node = indirect_to_ptr(node);
@@ -987,8 +995,9 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
987 995
988 if (cur_index > max_index) 996 if (cur_index > max_index)
989 break; 997 break;
990 slots_found = __lookup(node, results + ret, cur_index, 998 slots_found = __lookup(node, results + ret,
991 max_items - ret, &next_index); 999 indices ? indices + ret : NULL,
1000 cur_index, max_items - ret, &next_index);
992 ret += slots_found; 1001 ret += slots_found;
993 if (next_index == 0) 1002 if (next_index == 0)
994 break; 1003 break;
diff --git a/mm/filemap.c b/mm/filemap.c
index 867d40222ec7..b83aebfd0a00 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -840,7 +840,7 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
840 rcu_read_lock(); 840 rcu_read_lock();
841restart: 841restart:
842 nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree, 842 nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
843 (void ***)pages, start, nr_pages); 843 (void ***)pages, NULL, start, nr_pages);
844 ret = 0; 844 ret = 0;
845 for (i = 0; i < nr_found; i++) { 845 for (i = 0; i < nr_found; i++) {
846 struct page *page; 846 struct page *page;
@@ -903,7 +903,7 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
903 rcu_read_lock(); 903 rcu_read_lock();
904restart: 904restart:
905 nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree, 905 nr_found = radix_tree_gang_lookup_slot(&mapping->page_tree,
906 (void ***)pages, index, nr_pages); 906 (void ***)pages, NULL, index, nr_pages);
907 ret = 0; 907 ret = 0;
908 for (i = 0; i < nr_found; i++) { 908 for (i = 0; i < nr_found; i++) {
909 struct page *page; 909 struct page *page;