It's useful if we can run only over a specific index range of radix trees, which this patch does. This patch changes only radix_tree_for_each_slot() and radix_tree_for_each_tagged(), because we need it only for them for now. Signed-off-by: Naoya Horiguchi <n-horiguchi@xxxxxxxxxxxxx> --- drivers/gpu/drm/qxl/qxl_ttm.c | 2 +- include/linux/radix-tree.h | 27 ++++++++++++++++++++------- kernel/irq/irqdomain.c | 2 +- lib/radix-tree.c | 8 ++++---- mm/filemap.c | 4 ++-- mm/shmem.c | 2 +- 6 files changed, 29 insertions(+), 16 deletions(-) diff --git v3.14-rc6.orig/drivers/gpu/drm/qxl/qxl_ttm.c v3.14-rc6/drivers/gpu/drm/qxl/qxl_ttm.c index c7e7e6590c2b..ad477307e732 100644 --- v3.14-rc6.orig/drivers/gpu/drm/qxl/qxl_ttm.c +++ v3.14-rc6/drivers/gpu/drm/qxl/qxl_ttm.c @@ -398,7 +398,7 @@ static int qxl_sync_obj_wait(void *sync_obj, struct radix_tree_iter iter; int release_id; - radix_tree_for_each_slot(slot, &qfence->tree, &iter, 0) { + radix_tree_for_each_slot(slot, &qfence->tree, &iter, 0, ~0UL) { struct qxl_release *release; release_id = iter.index; diff --git v3.14-rc6.orig/include/linux/radix-tree.h v3.14-rc6/include/linux/radix-tree.h index 403940787be1..6e14a8e06105 100644 --- v3.14-rc6.orig/include/linux/radix-tree.h +++ v3.14-rc6/include/linux/radix-tree.h @@ -265,6 +265,7 @@ static inline void radix_tree_preload_end(void) * @index: index of current slot * @next_index: next-to-last index for this chunk * @tags: bit-mask for tag-iterating + * @end_index: last index to be scanned * * This radix tree iterator works in terms of "chunks" of slots. A chunk is a * subinterval of slots contained within one radix tree leaf node. It is @@ -277,6 +278,7 @@ struct radix_tree_iter { unsigned long index; unsigned long next_index; unsigned long tags; + unsigned long end_index; }; #define RADIX_TREE_ITER_TAG_MASK 0x00FF /* tag index in lower byte */ @@ -288,10 +290,12 @@ struct radix_tree_iter { * * @iter: pointer to iterator state * @start: iteration starting index + * @end: iteration ending index * Returns: NULL */ static __always_inline void ** -radix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start) +radix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start, + unsigned long end) { /* * Leave iter->tags uninitialized. radix_tree_next_chunk() will fill it @@ -303,6 +307,7 @@ radix_tree_iter_init(struct radix_tree_iter *iter, unsigned long start) */ iter->index = 0; iter->next_index = start; + iter->end_index = end; return NULL; } @@ -352,6 +357,8 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) iter->tags >>= 1; if (likely(iter->tags & 1ul)) { iter->index++; + if (iter->index > iter->end_index) + return NULL; return slot + 1; } if (!(flags & RADIX_TREE_ITER_CONTIG) && likely(iter->tags)) { @@ -359,6 +366,8 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) iter->tags >>= offset; iter->index += offset + 1; + if (iter->index > iter->end_index) + return NULL; return slot + offset + 1; } } else { @@ -367,6 +376,8 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) while (size--) { slot++; iter->index++; + if (iter->index > iter->end_index) + return NULL; if (likely(*slot)) return slot; if (flags & RADIX_TREE_ITER_CONTIG) { @@ -391,7 +402,7 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) * Locks can be released and reacquired between iterations. */ #define radix_tree_for_each_chunk(slot, root, iter, start, flags) \ - for (slot = radix_tree_iter_init(iter, start) ; \ + for (slot = radix_tree_iter_init(iter, start, ~0UL) ; \ (slot = radix_tree_next_chunk(root, iter, flags)) ;) /** @@ -414,11 +425,12 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) * @root: the struct radix_tree_root pointer * @iter: the struct radix_tree_iter pointer * @start: iteration starting index + * @end: iteration ending index * * @slot points to radix tree slot, @iter->index contains its index. */ -#define radix_tree_for_each_slot(slot, root, iter, start) \ - for (slot = radix_tree_iter_init(iter, start) ; \ +#define radix_tree_for_each_slot(slot, root, iter, start, end) \ + for (slot = radix_tree_iter_init(iter, start, end) ; \ slot || (slot = radix_tree_next_chunk(root, iter, 0)) ; \ slot = radix_tree_next_slot(slot, iter, 0)) @@ -433,7 +445,7 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) * @slot points to radix tree slot, @iter->index contains its index. */ #define radix_tree_for_each_contig(slot, root, iter, start) \ - for (slot = radix_tree_iter_init(iter, start) ; \ + for (slot = radix_tree_iter_init(iter, start, ~0UL) ; \ slot || (slot = radix_tree_next_chunk(root, iter, \ RADIX_TREE_ITER_CONTIG)) ; \ slot = radix_tree_next_slot(slot, iter, \ @@ -446,12 +458,13 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) * @root: the struct radix_tree_root pointer * @iter: the struct radix_tree_iter pointer * @start: iteration starting index + * @end: iteration ending index * @tag: tag index * * @slot points to radix tree slot, @iter->index contains its index. */ -#define radix_tree_for_each_tagged(slot, root, iter, start, tag) \ - for (slot = radix_tree_iter_init(iter, start) ; \ +#define radix_tree_for_each_tagged(slot, root, iter, start, end, tag) \ + for (slot = radix_tree_iter_init(iter, start, end) ; \ slot || (slot = radix_tree_next_chunk(root, iter, \ RADIX_TREE_ITER_TAGGED | tag)) ; \ slot = radix_tree_next_slot(slot, iter, \ diff --git v3.14-rc6.orig/kernel/irq/irqdomain.c v3.14-rc6/kernel/irq/irqdomain.c index f14033700c25..55fc49b412e1 100644 --- v3.14-rc6.orig/kernel/irq/irqdomain.c +++ v3.14-rc6/kernel/irq/irqdomain.c @@ -571,7 +571,7 @@ static int virq_debug_show(struct seq_file *m, void *private) mutex_lock(&irq_domain_mutex); list_for_each_entry(domain, &irq_domain_list, link) { int count = 0; - radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0) + radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0, ~0UL) count++; seq_printf(m, "%c%-16s %6u %10u %10u %s\n", domain == irq_default_domain ? '*' : ' ', domain->name, diff --git v3.14-rc6.orig/lib/radix-tree.c v3.14-rc6/lib/radix-tree.c index bd4a8dfdf0b8..487ba9c403d2 100644 --- v3.14-rc6.orig/lib/radix-tree.c +++ v3.14-rc6/lib/radix-tree.c @@ -1051,7 +1051,7 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, if (unlikely(!max_items)) return 0; - radix_tree_for_each_slot(slot, root, &iter, first_index) { + radix_tree_for_each_slot(slot, root, &iter, first_index, ~0UL) { results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot)); if (!results[ret]) continue; @@ -1093,7 +1093,7 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root, if (unlikely(!max_items)) return 0; - radix_tree_for_each_slot(slot, root, &iter, first_index) { + radix_tree_for_each_slot(slot, root, &iter, first_index, ~0UL) { results[ret] = slot; if (indices) indices[ret] = iter.index; @@ -1130,7 +1130,7 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results, if (unlikely(!max_items)) return 0; - radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) { + radix_tree_for_each_tagged(slot, root, &iter, first_index, ~0UL, tag) { results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot)); if (!results[ret]) continue; @@ -1167,7 +1167,7 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results, if (unlikely(!max_items)) return 0; - radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) { + radix_tree_for_each_tagged(slot, root, &iter, first_index, ~0UL, tag) { results[ret] = slot; if (++ret == max_items) break; diff --git v3.14-rc6.orig/mm/filemap.c v3.14-rc6/mm/filemap.c index 7a13f6ac5421..8c24eda539d8 100644 --- v3.14-rc6.orig/mm/filemap.c +++ v3.14-rc6/mm/filemap.c @@ -841,7 +841,7 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start, rcu_read_lock(); restart: - radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { + radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start, ~0UL) { struct page *page; repeat: page = radix_tree_deref_slot(slot); @@ -985,7 +985,7 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, rcu_read_lock(); restart: radix_tree_for_each_tagged(slot, &mapping->page_tree, - &iter, *index, tag) { + &iter, *index, ~0UL, tag) { struct page *page; repeat: page = radix_tree_deref_slot(slot); diff --git v3.14-rc6.orig/mm/shmem.c v3.14-rc6/mm/shmem.c index 1f18c9d0d93e..973caa10fe1e 100644 --- v3.14-rc6.orig/mm/shmem.c +++ v3.14-rc6/mm/shmem.c @@ -346,7 +346,7 @@ static unsigned shmem_find_get_pages_and_swap(struct address_space *mapping, rcu_read_lock(); restart: - radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start) { + radix_tree_for_each_slot(slot, &mapping->page_tree, &iter, start, ~0UL) { struct page *page; repeat: page = radix_tree_deref_slot(slot); -- 1.8.5.3 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>