aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2014-04-03 17:47:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-03 19:21:00 -0400
commite7b563bb2a6f4d974208da46200784b9c5b5a47e (patch)
treeef98603b01ab3f029db5228a99506e6c843b1352 /mm
parent6dbaf22ce1f1dfba33313198eb5bd989ae76dd87 (diff)
mm: filemap: move radix tree hole searching here
The radix tree hole searching code is only used for page cache, for example the readahead code trying to get a a picture of the area surrounding a fault. It sufficed to rely on the radix tree definition of holes, which is "empty tree slot". But this is about to change, though, as shadow page descriptors will be stored in the page cache after the actual pages get evicted from memory. Move the functions over to mm/filemap.c and make them native page cache operations, where they can later be adapted to handle the new definition of "page cache hole". Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Rik van Riel <riel@redhat.com> Reviewed-by: Minchan Kim <minchan@kernel.org> Acked-by: Mel Gorman <mgorman@suse.de> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Bob Liu <bob.liu@oracle.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Dave Chinner <david@fromorbit.com> Cc: Greg Thelen <gthelen@google.com> Cc: Hugh Dickins <hughd@google.com> Cc: Jan Kara <jack@suse.cz> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Luigi Semenzato <semenzato@google.com> Cc: Metin Doslu <metin@citusdata.com> Cc: Michel Lespinasse <walken@google.com> Cc: Ozgun Erdogan <ozgun@citusdata.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Roman Gushchin <klamm@yandex-team.ru> Cc: Ryan Mallon <rmallon@gmail.com> Cc: Tejun Heo <tj@kernel.org> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/filemap.c76
-rw-r--r--mm/readahead.c4
2 files changed, 78 insertions, 2 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 068cd2a63d32..40115c6c0791 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -686,6 +686,82 @@ int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
686} 686}
687 687
688/** 688/**
689 * page_cache_next_hole - find the next hole (not-present entry)
690 * @mapping: mapping
691 * @index: index
692 * @max_scan: maximum range to search
693 *
694 * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the
695 * lowest indexed hole.
696 *
697 * Returns: the index of the hole if found, otherwise returns an index
698 * outside of the set specified (in which case 'return - index >=
699 * max_scan' will be true). In rare cases of index wrap-around, 0 will
700 * be returned.
701 *
702 * page_cache_next_hole may be called under rcu_read_lock. However,
703 * like radix_tree_gang_lookup, this will not atomically search a
704 * snapshot of the tree at a single point in time. For example, if a
705 * hole is created at index 5, then subsequently a hole is created at
706 * index 10, page_cache_next_hole covering both indexes may return 10
707 * if called under rcu_read_lock.
708 */
709pgoff_t page_cache_next_hole(struct address_space *mapping,
710 pgoff_t index, unsigned long max_scan)
711{
712 unsigned long i;
713
714 for (i = 0; i < max_scan; i++) {
715 if (!radix_tree_lookup(&mapping->page_tree, index))
716 break;
717 index++;
718 if (index == 0)
719 break;
720 }
721
722 return index;
723}
724EXPORT_SYMBOL(page_cache_next_hole);
725
726/**
727 * page_cache_prev_hole - find the prev hole (not-present entry)
728 * @mapping: mapping
729 * @index: index
730 * @max_scan: maximum range to search
731 *
732 * Search backwards in the range [max(index-max_scan+1, 0), index] for
733 * the first hole.
734 *
735 * Returns: the index of the hole if found, otherwise returns an index
736 * outside of the set specified (in which case 'index - return >=
737 * max_scan' will be true). In rare cases of wrap-around, ULONG_MAX
738 * will be returned.
739 *
740 * page_cache_prev_hole may be called under rcu_read_lock. However,
741 * like radix_tree_gang_lookup, this will not atomically search a
742 * snapshot of the tree at a single point in time. For example, if a
743 * hole is created at index 10, then subsequently a hole is created at
744 * index 5, page_cache_prev_hole covering both indexes may return 5 if
745 * called under rcu_read_lock.
746 */
747pgoff_t page_cache_prev_hole(struct address_space *mapping,
748 pgoff_t index, unsigned long max_scan)
749{
750 unsigned long i;
751
752 for (i = 0; i < max_scan; i++) {
753 if (!radix_tree_lookup(&mapping->page_tree, index))
754 break;
755 index--;
756 if (index == ULONG_MAX)
757 break;
758 }
759
760 return index;
761}
762EXPORT_SYMBOL(page_cache_prev_hole);
763
764/**
689 * find_get_page - find and get a page reference 765 * find_get_page - find and get a page reference
690 * @mapping: the address_space to search 766 * @mapping: the address_space to search
691 * @offset: the page index 767 * @offset: the page index
diff --git a/mm/readahead.c b/mm/readahead.c
index 0de2360d65f3..c62d85ace0cc 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -347,7 +347,7 @@ static pgoff_t count_history_pages(struct address_space *mapping,
347 pgoff_t head; 347 pgoff_t head;
348 348
349 rcu_read_lock(); 349 rcu_read_lock();
350 head = radix_tree_prev_hole(&mapping->page_tree, offset - 1, max); 350 head = page_cache_prev_hole(mapping, offset - 1, max);
351 rcu_read_unlock(); 351 rcu_read_unlock();
352 352
353 return offset - 1 - head; 353 return offset - 1 - head;
@@ -427,7 +427,7 @@ ondemand_readahead(struct address_space *mapping,
427 pgoff_t start; 427 pgoff_t start;
428 428
429 rcu_read_lock(); 429 rcu_read_lock();
430 start = radix_tree_next_hole(&mapping->page_tree, offset+1,max); 430 start = page_cache_next_hole(mapping, offset + 1, max);
431 rcu_read_unlock(); 431 rcu_read_unlock();
432 432
433 if (!start || start - offset > max) 433 if (!start || start - offset > max)