mm: clarify the radix_tree exceptional cases

Make the radix_tree exceptional cases, mostly in filemap.c, clearer.

It's hard to devise a suitable snappy name that illuminates the use by
shmem/tmpfs for swap, while keeping filemap/pagecache/radix_tree
generality.  And akpm points out that /* radix_tree_deref_retry(page) */
comments look like calls that have been commented out for unknown
reason.

Skirt the naming difficulty by rearranging these blocks to handle the
transient radix_tree_deref_retry(page) case first; then just explain the
remaining shmem/tmpfs swap case in a comment.

Signed-off-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Hugh Dickins 2011-08-03 16:21:28 -07:00 committed by Linus Torvalds
parent e504f3fdd6
commit 8079b1c859
3 changed files with 53 additions and 26 deletions

View File

@ -700,10 +700,14 @@ struct page *find_get_page(struct address_space *mapping, pgoff_t offset)
if (unlikely(!page))
goto out;
if (radix_tree_exception(page)) {
if (radix_tree_exceptional_entry(page))
goto out;
/* radix_tree_deref_retry(page) */
goto repeat;
if (radix_tree_deref_retry(page))
goto repeat;
/*
* Otherwise, shmem/tmpfs must be storing a swap entry
* here as an exceptional entry: so return it without
* attempting to raise page count.
*/
goto out;
}
if (!page_cache_get_speculative(page))
goto repeat;
@ -838,15 +842,21 @@ unsigned find_get_pages(struct address_space *mapping, pgoff_t start,
continue;
if (radix_tree_exception(page)) {
if (radix_tree_exceptional_entry(page))
continue;
if (radix_tree_deref_retry(page)) {
/*
* Transient condition which can only trigger
* when entry at index 0 moves out of or back
* to root: none yet gotten, safe to restart.
*/
WARN_ON(start | i);
goto restart;
}
/*
* radix_tree_deref_retry(page):
* can only trigger when entry at index 0 moves out of
* or back to root: none yet gotten, safe to restart.
* Otherwise, shmem/tmpfs must be storing a swap entry
* here as an exceptional entry: so skip over it -
* we only reach this from invalidate_mapping_pages().
*/
WARN_ON(start | i);
goto restart;
continue;
}
if (!page_cache_get_speculative(page))
@ -904,14 +914,20 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t index,
continue;
if (radix_tree_exception(page)) {
if (radix_tree_exceptional_entry(page))
break;
if (radix_tree_deref_retry(page)) {
/*
* Transient condition which can only trigger
* when entry at index 0 moves out of or back
* to root: none yet gotten, safe to restart.
*/
goto restart;
}
/*
* radix_tree_deref_retry(page):
* can only trigger when entry at index 0 moves out of
* or back to root: none yet gotten, safe to restart.
* Otherwise, shmem/tmpfs must be storing a swap entry
* here as an exceptional entry: so stop looking for
* contiguous pages.
*/
goto restart;
break;
}
if (!page_cache_get_speculative(page))
@ -973,13 +989,19 @@ unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
continue;
if (radix_tree_exception(page)) {
BUG_ON(radix_tree_exceptional_entry(page));
if (radix_tree_deref_retry(page)) {
/*
* Transient condition which can only trigger
* when entry at index 0 moves out of or back
* to root: none yet gotten, safe to restart.
*/
goto restart;
}
/*
* radix_tree_deref_retry(page):
* can only trigger when entry at index 0 moves out of
* or back to root: none yet gotten, safe to restart.
* This function is never used on a shmem/tmpfs
* mapping, so a swap entry won't be found here.
*/
goto restart;
BUG();
}
if (!page_cache_get_speculative(page))

View File

@ -72,6 +72,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
*/
page = find_get_page(mapping, pgoff);
#ifdef CONFIG_SWAP
/* shmem/tmpfs may return swap: account for swapcache page too. */
if (radix_tree_exceptional_entry(page)) {
swp_entry_t swap = radix_to_swp_entry(page);
page = find_get_page(&swapper_space, swap.val);

View File

@ -332,10 +332,14 @@ static unsigned shmem_find_get_pages_and_swap(struct address_space *mapping,
if (unlikely(!page))
continue;
if (radix_tree_exception(page)) {
if (radix_tree_exceptional_entry(page))
goto export;
/* radix_tree_deref_retry(page) */
goto restart;
if (radix_tree_deref_retry(page))
goto restart;
/*
* Otherwise, we must be storing a swap entry
* here as an exceptional entry: so return it
* without attempting to raise page count.
*/
goto export;
}
if (!page_cache_get_speculative(page))
goto repeat;