diff options
author | Mel Gorman <mgorman@suse.de> | 2012-12-06 14:01:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-06 14:17:33 -0500 |
commit | 60177d31d215bc2b4c5a7aa6f742800e04fa0a92 (patch) | |
tree | c45e15fc9b97b3ebffb6f7876512d35fe1d7aa46 /mm/compaction.c | |
parent | 04c5decdc0aecde43bf44860484f26ee0691335f (diff) |
mm: compaction: validate pfn range passed to isolate_freepages_block
Commit 0bf380bc70ec ("mm: compaction: check pfn_valid when entering a
new MAX_ORDER_NR_PAGES block during isolation for migration") added a
check for pfn_valid() when isolating pages for migration as the scanner
does not necessarily start pageblock-aligned.
Since commit c89511ab2f8f ("mm: compaction: Restart compaction from near
where it left off"), the free scanner has the same problem. This patch
makes sure that the pfn range passed to isolate_freepages_block() is
within the same block so that pfn_valid() checks are unnecessary.
In answer to Henrik's wondering why others have not reported this:
reproducing this requires a large enough hole with the right aligment to
have compaction walk into a PFN range with no memmap. Size and
alignment depends in the memory model - 4M for FLATMEM and 128M for
SPARSEMEM on x86. It needs a "lucky" machine.
Reported-by: Henrik Rydberg <rydberg@euromail.se>
Signed-off-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/compaction.c')
-rw-r--r-- | mm/compaction.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index 9eef55838fca..694eaabaaebd 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -713,7 +713,15 @@ static void isolate_freepages(struct zone *zone, | |||
713 | 713 | ||
714 | /* Found a block suitable for isolating free pages from */ | 714 | /* Found a block suitable for isolating free pages from */ |
715 | isolated = 0; | 715 | isolated = 0; |
716 | end_pfn = min(pfn + pageblock_nr_pages, zone_end_pfn); | 716 | |
717 | /* | ||
718 | * As pfn may not start aligned, pfn+pageblock_nr_page | ||
719 | * may cross a MAX_ORDER_NR_PAGES boundary and miss | ||
720 | * a pfn_valid check. Ensure isolate_freepages_block() | ||
721 | * only scans within a pageblock | ||
722 | */ | ||
723 | end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); | ||
724 | end_pfn = min(end_pfn, zone_end_pfn); | ||
717 | isolated = isolate_freepages_block(cc, pfn, end_pfn, | 725 | isolated = isolate_freepages_block(cc, pfn, end_pfn, |
718 | freelist, false); | 726 | freelist, false); |
719 | nr_freepages += isolated; | 727 | nr_freepages += isolated; |