diff options
author | Nick Piggin <npiggin@kernel.dk> | 2011-01-14 00:45:51 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 02:32:32 +0100 |
commit | 9cbb4cb21b19fff46cf1174d0ed699ef710e641c (patch) | |
tree | 56480b1f4082d6158f077378db36c99d6d3ff209 /mm/filemap.c | |
parent | vmscan: factor out kswapd sleeping logic from kswapd() (diff) | |
download | linux-9cbb4cb21b19fff46cf1174d0ed699ef710e641c.tar.xz linux-9cbb4cb21b19fff46cf1174d0ed699ef710e641c.zip |
mm: find_get_pages_contig fixlet
Testing ->mapping and ->index without a ref is not stable as the page
may have been reused at this point.
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Reviewed-by: Wu Fengguang <fengguang.wu@intel.com>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/filemap.c')
-rw-r--r-- | mm/filemap.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/mm/filemap.c b/mm/filemap.c index ca389394fa2a..1a3dd5914726 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -837,9 +837,6 @@ repeat: if (radix_tree_deref_retry(page)) goto restart; - if (page->mapping == NULL || page->index != index) - break; - if (!page_cache_get_speculative(page)) goto repeat; @@ -849,6 +846,16 @@ repeat: goto repeat; } + /* + * must check mapping and index after taking the ref. + * otherwise we can get both false positives and false + * negatives, which is just confusing to the caller. + */ + if (page->mapping == NULL || page->index != index) { + page_cache_release(page); + break; + } + pages[ret] = page; ret++; index++; |