From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754574Ab2EAIop (ORCPT ); Tue, 1 May 2012 04:44:45 -0400 Received: from zene.cmpxchg.org ([85.214.230.12]:43904 "EHLO zene.cmpxchg.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753891Ab2EAInW (ORCPT ); Tue, 1 May 2012 04:43:22 -0400 From: Johannes Weiner To: linux-mm@kvack.org Cc: Rik van Riel , Andrea Arcangeli , Peter Zijlstra , Mel Gorman , Andrew Morton , Minchan Kim , Hugh Dickins , KOSAKI Motohiro , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [patch 1/5] mm: readahead: move radix tree hole searching here Date: Tue, 1 May 2012 10:41:49 +0200 Message-Id: <1335861713-4573-2-git-send-email-hannes@cmpxchg.org> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1335861713-4573-1-git-send-email-hannes@cmpxchg.org> References: <1335861713-4573-1-git-send-email-hannes@cmpxchg.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The readahead code searches the page cache for non-present pages, or holes, to get a picture of the area surrounding a fault e.g. For this it sufficed to rely on the radix tree definition of holes, which is "empty tree slot". This is about to change, though, because shadow page descriptors will be stored in the page cache when the real pages get evicted from memory. Fortunately, nobody outside the readahead code uses these functions and they have no internal knowledge of the radix tree structures, so just move them over to mm/readahead.c where they can later be adapted to handle the new definition of "page cache hole". Signed-off-by: Johannes Weiner --- include/linux/radix-tree.h | 4 -- lib/radix-tree.c | 75 -------------------------------------------- mm/readahead.c | 36 ++++++++++++++++++++- 3 files changed, 34 insertions(+), 81 deletions(-) diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 07e360b..73e49c4 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -224,10 +224,6 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned int 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 radix_tree_next_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan); -unsigned long radix_tree_prev_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan); int radix_tree_preload(gfp_t gfp_mask); void radix_tree_init(void); void *radix_tree_tag_set(struct radix_tree_root *root, diff --git a/lib/radix-tree.c b/lib/radix-tree.c index dc63d08..89b5f6a 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -742,81 +742,6 @@ next: } EXPORT_SYMBOL(radix_tree_range_tag_if_tagged); - -/** - * radix_tree_next_hole - find the next hole (not-present entry) - * @root: tree root - * @index: index key - * @max_scan: maximum range to search - * - * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest - * indexed hole. - * - * Returns: the index of the hole if found, otherwise returns an index - * outside of the set specified (in which case 'return - index >= max_scan' - * will be true). In rare cases of index wrap-around, 0 will be returned. - * - * radix_tree_next_hole may be called under rcu_read_lock. However, like - * radix_tree_gang_lookup, this will not atomically search a snapshot of - * the tree at a single point in time. For example, if a hole is created - * at index 5, then subsequently a hole is created at index 10, - * radix_tree_next_hole covering both indexes may return 10 if called - * under rcu_read_lock. - */ -unsigned long radix_tree_next_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan) -{ - unsigned long i; - - for (i = 0; i < max_scan; i++) { - if (!radix_tree_lookup(root, index)) - break; - index++; - if (index == 0) - break; - } - - return index; -} -EXPORT_SYMBOL(radix_tree_next_hole); - -/** - * radix_tree_prev_hole - find the prev hole (not-present entry) - * @root: tree root - * @index: index key - * @max_scan: maximum range to search - * - * Search backwards in the range [max(index-max_scan+1, 0), index] - * for the first hole. - * - * Returns: the index of the hole if found, otherwise returns an index - * outside of the set specified (in which case 'index - return >= max_scan' - * will be true). In rare cases of wrap-around, ULONG_MAX will be returned. - * - * radix_tree_next_hole may be called under rcu_read_lock. However, like - * radix_tree_gang_lookup, this will not atomically search a snapshot of - * the tree at a single point in time. For example, if a hole is created - * at index 10, then subsequently a hole is created at index 5, - * radix_tree_prev_hole covering both indexes may return 5 if called under - * rcu_read_lock. - */ -unsigned long radix_tree_prev_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan) -{ - unsigned long i; - - for (i = 0; i < max_scan; i++) { - if (!radix_tree_lookup(root, index)) - break; - index--; - if (index == ULONG_MAX) - break; - } - - return index; -} -EXPORT_SYMBOL(radix_tree_prev_hole); - static unsigned int __lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices, unsigned long index, unsigned int max_items, unsigned long *next_index) diff --git a/mm/readahead.c b/mm/readahead.c index cbcbb02..0d1f1aa 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -336,6 +336,38 @@ static unsigned long get_next_ra_size(struct file_ra_state *ra, * it approaches max_readhead. */ +static unsigned long page_cache_next_hole(struct address_space *mapping, + pgoff_t index, unsigned long max_scan) +{ + unsigned long i; + + for (i = 0; i < max_scan; i++) { + if (!radix_tree_lookup(&mapping->page_tree, index)) + break; + index++; + if (index == 0) + break; + } + + return index; +} + +static unsigned long page_cache_prev_hole(struct address_space *mapping, + pgoff_t index, unsigned long max_scan) +{ + unsigned long i; + + for (i = 0; i < max_scan; i++) { + if (!radix_tree_lookup(&mapping->page_tree, index)) + break; + index--; + if (index == ULONG_MAX) + break; + } + + return index; +} + /* * Count contiguously cached pages from @offset-1 to @offset-@max, * this count is a conservative estimation of @@ -349,7 +381,7 @@ static pgoff_t count_history_pages(struct address_space *mapping, pgoff_t head; rcu_read_lock(); - head = radix_tree_prev_hole(&mapping->page_tree, offset - 1, max); + head = page_cache_prev_hole(mapping, offset - 1, max); rcu_read_unlock(); return offset - 1 - head; @@ -428,7 +460,7 @@ ondemand_readahead(struct address_space *mapping, pgoff_t start; rcu_read_lock(); - start = radix_tree_next_hole(&mapping->page_tree, offset+1,max); + start = page_cache_next_hole(mapping, offset + 1, max); rcu_read_unlock(); if (!start || start - offset > max) -- 1.7.7.6 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Johannes Weiner Subject: [patch 1/5] mm: readahead: move radix tree hole searching here Date: Tue, 1 May 2012 10:41:49 +0200 Message-ID: <1335861713-4573-2-git-send-email-hannes@cmpxchg.org> References: <1335861713-4573-1-git-send-email-hannes@cmpxchg.org> Cc: Rik van Riel , Andrea Arcangeli , Peter Zijlstra , Mel Gorman , Andrew Morton , Minchan Kim , Hugh Dickins , KOSAKI Motohiro , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org To: linux-mm@kvack.org Return-path: In-Reply-To: <1335861713-4573-1-git-send-email-hannes@cmpxchg.org> Sender: owner-linux-mm@kvack.org List-Id: linux-fsdevel.vger.kernel.org The readahead code searches the page cache for non-present pages, or holes, to get a picture of the area surrounding a fault e.g. For this it sufficed to rely on the radix tree definition of holes, which is "empty tree slot". This is about to change, though, because shadow page descriptors will be stored in the page cache when the real pages get evicted from memory. Fortunately, nobody outside the readahead code uses these functions and they have no internal knowledge of the radix tree structures, so just move them over to mm/readahead.c where they can later be adapted to handle the new definition of "page cache hole". Signed-off-by: Johannes Weiner --- include/linux/radix-tree.h | 4 -- lib/radix-tree.c | 75 -------------------------------------------- mm/readahead.c | 36 ++++++++++++++++++++- 3 files changed, 34 insertions(+), 81 deletions(-) diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 07e360b..73e49c4 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -224,10 +224,6 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned int 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 radix_tree_next_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan); -unsigned long radix_tree_prev_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan); int radix_tree_preload(gfp_t gfp_mask); void radix_tree_init(void); void *radix_tree_tag_set(struct radix_tree_root *root, diff --git a/lib/radix-tree.c b/lib/radix-tree.c index dc63d08..89b5f6a 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -742,81 +742,6 @@ next: } EXPORT_SYMBOL(radix_tree_range_tag_if_tagged); - -/** - * radix_tree_next_hole - find the next hole (not-present entry) - * @root: tree root - * @index: index key - * @max_scan: maximum range to search - * - * Search the set [index, min(index+max_scan-1, MAX_INDEX)] for the lowest - * indexed hole. - * - * Returns: the index of the hole if found, otherwise returns an index - * outside of the set specified (in which case 'return - index >= max_scan' - * will be true). In rare cases of index wrap-around, 0 will be returned. - * - * radix_tree_next_hole may be called under rcu_read_lock. However, like - * radix_tree_gang_lookup, this will not atomically search a snapshot of - * the tree at a single point in time. For example, if a hole is created - * at index 5, then subsequently a hole is created at index 10, - * radix_tree_next_hole covering both indexes may return 10 if called - * under rcu_read_lock. - */ -unsigned long radix_tree_next_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan) -{ - unsigned long i; - - for (i = 0; i < max_scan; i++) { - if (!radix_tree_lookup(root, index)) - break; - index++; - if (index == 0) - break; - } - - return index; -} -EXPORT_SYMBOL(radix_tree_next_hole); - -/** - * radix_tree_prev_hole - find the prev hole (not-present entry) - * @root: tree root - * @index: index key - * @max_scan: maximum range to search - * - * Search backwards in the range [max(index-max_scan+1, 0), index] - * for the first hole. - * - * Returns: the index of the hole if found, otherwise returns an index - * outside of the set specified (in which case 'index - return >= max_scan' - * will be true). In rare cases of wrap-around, ULONG_MAX will be returned. - * - * radix_tree_next_hole may be called under rcu_read_lock. However, like - * radix_tree_gang_lookup, this will not atomically search a snapshot of - * the tree at a single point in time. For example, if a hole is created - * at index 10, then subsequently a hole is created at index 5, - * radix_tree_prev_hole covering both indexes may return 5 if called under - * rcu_read_lock. - */ -unsigned long radix_tree_prev_hole(struct radix_tree_root *root, - unsigned long index, unsigned long max_scan) -{ - unsigned long i; - - for (i = 0; i < max_scan; i++) { - if (!radix_tree_lookup(root, index)) - break; - index--; - if (index == ULONG_MAX) - break; - } - - return index; -} -EXPORT_SYMBOL(radix_tree_prev_hole); - static unsigned int __lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices, unsigned long index, unsigned int max_items, unsigned long *next_index) diff --git a/mm/readahead.c b/mm/readahead.c index cbcbb02..0d1f1aa 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -336,6 +336,38 @@ static unsigned long get_next_ra_size(struct file_ra_state *ra, * it approaches max_readhead. */ +static unsigned long page_cache_next_hole(struct address_space *mapping, + pgoff_t index, unsigned long max_scan) +{ + unsigned long i; + + for (i = 0; i < max_scan; i++) { + if (!radix_tree_lookup(&mapping->page_tree, index)) + break; + index++; + if (index == 0) + break; + } + + return index; +} + +static unsigned long page_cache_prev_hole(struct address_space *mapping, + pgoff_t index, unsigned long max_scan) +{ + unsigned long i; + + for (i = 0; i < max_scan; i++) { + if (!radix_tree_lookup(&mapping->page_tree, index)) + break; + index--; + if (index == ULONG_MAX) + break; + } + + return index; +} + /* * Count contiguously cached pages from @offset-1 to @offset-@max, * this count is a conservative estimation of @@ -349,7 +381,7 @@ static pgoff_t count_history_pages(struct address_space *mapping, pgoff_t head; rcu_read_lock(); - head = radix_tree_prev_hole(&mapping->page_tree, offset - 1, max); + head = page_cache_prev_hole(mapping, offset - 1, max); rcu_read_unlock(); return offset - 1 - head; @@ -428,7 +460,7 @@ ondemand_readahead(struct address_space *mapping, pgoff_t start; rcu_read_lock(); - start = radix_tree_next_hole(&mapping->page_tree, offset+1,max); + start = page_cache_next_hole(mapping, offset + 1, max); rcu_read_unlock(); if (!start || start - offset > max) -- 1.7.7.6 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: email@kvack.org