Commit 7f46774c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mm-compaction-5.1-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mel/linux

Pull mm/compaction fixes from Mel Gorman:
 "The merge window for 5.1 introduced a number of compaction-related
  patches. with intermittent reports of corruption and functional
  issues. The bugs are due to sloopy checking of zone boundaries and a
  corner case where invalid indexes are used to access the free lists.

  Reports are not common but at least two users and 0-day have tripped
  over them. There is a chance that one of the syzbot reports are
  related but it has not been confirmed properly.

  The normal submission path is with Andrew but there have been some
  delays and I consider them urgent enough that they should be picked up
  before RC4 to avoid duplicate reports.

  All of these have been successfully tested on older RC windows. This
  will make this branch look like a rebase but in fact, they've simply
  been lifted again from Andrew's tree and placed on a fresh branch.
  I've no reason to believe that this has invalidated the testing given
  the lack of change in compaction and the nature of the fixes"

* tag 'mm-compaction-5.1-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mel/linux:
  mm/compaction.c: abort search if isolation fails
  mm/compaction.c: correct zone boundary handling when resetting pageblock skip hints
parents c7084edc 5b56d996
...@@ -242,6 +242,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, ...@@ -242,6 +242,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source,
bool check_target) bool check_target)
{ {
struct page *page = pfn_to_online_page(pfn); struct page *page = pfn_to_online_page(pfn);
struct page *block_page;
struct page *end_page; struct page *end_page;
unsigned long block_pfn; unsigned long block_pfn;
...@@ -267,20 +268,26 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, ...@@ -267,20 +268,26 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source,
get_pageblock_migratetype(page) != MIGRATE_MOVABLE) get_pageblock_migratetype(page) != MIGRATE_MOVABLE)
return false; return false;
/* Ensure the start of the pageblock or zone is online and valid */
block_pfn = pageblock_start_pfn(pfn);
block_page = pfn_to_online_page(max(block_pfn, zone->zone_start_pfn));
if (block_page) {
page = block_page;
pfn = block_pfn;
}
/* Ensure the end of the pageblock or zone is online and valid */
block_pfn += pageblock_nr_pages;
block_pfn = min(block_pfn, zone_end_pfn(zone) - 1);
end_page = pfn_to_online_page(block_pfn);
if (!end_page)
return false;
/* /*
* Only clear the hint if a sample indicates there is either a * Only clear the hint if a sample indicates there is either a
* free page or an LRU page in the block. One or other condition * free page or an LRU page in the block. One or other condition
* is necessary for the block to be a migration source/target. * is necessary for the block to be a migration source/target.
*/ */
block_pfn = pageblock_start_pfn(pfn);
pfn = max(block_pfn, zone->zone_start_pfn);
page = pfn_to_page(pfn);
if (zone != page_zone(page))
return false;
pfn = block_pfn + pageblock_nr_pages;
pfn = min(pfn, zone_end_pfn(zone));
end_page = pfn_to_page(pfn);
do { do {
if (pfn_valid_within(pfn)) { if (pfn_valid_within(pfn)) {
if (check_source && PageLRU(page)) { if (check_source && PageLRU(page)) {
...@@ -309,7 +316,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source, ...@@ -309,7 +316,7 @@ __reset_isolation_pfn(struct zone *zone, unsigned long pfn, bool check_source,
static void __reset_isolation_suitable(struct zone *zone) static void __reset_isolation_suitable(struct zone *zone)
{ {
unsigned long migrate_pfn = zone->zone_start_pfn; unsigned long migrate_pfn = zone->zone_start_pfn;
unsigned long free_pfn = zone_end_pfn(zone); unsigned long free_pfn = zone_end_pfn(zone) - 1;
unsigned long reset_migrate = free_pfn; unsigned long reset_migrate = free_pfn;
unsigned long reset_free = migrate_pfn; unsigned long reset_free = migrate_pfn;
bool source_set = false; bool source_set = false;
...@@ -1363,7 +1370,7 @@ fast_isolate_freepages(struct compact_control *cc) ...@@ -1363,7 +1370,7 @@ fast_isolate_freepages(struct compact_control *cc)
count_compact_events(COMPACTISOLATED, nr_isolated); count_compact_events(COMPACTISOLATED, nr_isolated);
} else { } else {
/* If isolation fails, abort the search */ /* If isolation fails, abort the search */
order = -1; order = cc->search_order + 1;
page = NULL; page = NULL;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment