Commit 71a5b801344ae1f03e2fb6ddad600c554f243257

Authored by Vlastimil Babka
Committed by Jiri Slaby
1 parent 5e4084a627

mm/compaction: avoid rescanning pageblocks in isolate_freepages

commit e9ade569910a82614ff5f2c2cea2b65a8d785da4 upstream.

The compaction free scanner in isolate_freepages() currently remembers PFN
of the highest pageblock where it successfully isolates, to be used as the
starting pageblock for the next invocation.  The rationale behind this is
that page migration might return free pages to the allocator when
migration fails and we don't want to skip them if the compaction
continues.

Since migration now returns free pages back to compaction code where they
can be reused, this is no longer a concern.  This patch changes
isolate_freepages() so that the PFN for restarting is updated with each
pageblock where isolation is attempted.  Using stress-highalloc from
mmtests, this resulted in 10% reduction of the pages scanned by the free
scanner.

Note that the somewhat similar functionality that records highest
successful pageblock in zone->compact_cached_free_pfn, remains unchanged.
This cache is used when the whole compaction is restarted, not for
multiple invocations of the free scanner during single compaction.

Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Rik van Riel <riel@redhat.com>
Acked-by: David Rientjes <rientjes@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>

Showing 1 changed file with 7 additions and 15 deletions Side-by-side Diff

... ... @@ -686,7 +686,6 @@
686 686 unsigned long block_start_pfn; /* start of current pageblock */
687 687 unsigned long block_end_pfn; /* end of current pageblock */
688 688 unsigned long low_pfn; /* lowest pfn scanner is able to scan */
689   - unsigned long next_free_pfn; /* start pfn for scaning at next round */
690 689 int nr_freepages = cc->nr_freepages;
691 690 struct list_head *freelist = &cc->freepages;
692 691  
... ... @@ -707,12 +706,6 @@
707 706 low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages);
708 707  
709 708 /*
710   - * If no pages are isolated, the block_start_pfn < low_pfn check
711   - * will kick in.
712   - */
713   - next_free_pfn = 0;
714   -
715   - /*
716 709 * Isolate free pages until enough are available to migrate the
717 710 * pages on cc->migratepages. We stop searching if the migrate
718 711 * and free page scanners meet or enough free pages are isolated.
719 712  
720 713  
721 714  
... ... @@ -752,19 +745,19 @@
752 745 continue;
753 746  
754 747 /* Found a block suitable for isolating free pages from */
  748 + cc->free_pfn = block_start_pfn;
755 749 isolated = isolate_freepages_block(cc, block_start_pfn,
756 750 block_end_pfn, freelist, false);
757 751 nr_freepages += isolated;
758 752  
759 753 /*
760   - * Record the highest PFN we isolated pages from. When next
761   - * looking for free pages, the search will restart here as
762   - * page migration may have returned some pages to the allocator
  754 + * Set a flag that we successfully isolated in this pageblock.
  755 + * In the next loop iteration, zone->compact_cached_free_pfn
  756 + * will not be updated and thus it will effectively contain the
  757 + * highest pageblock we isolated pages from.
763 758 */
764   - if (isolated && next_free_pfn == 0) {
  759 + if (isolated)
765 760 cc->finished_update_free = true;
766   - next_free_pfn = block_start_pfn;
767   - }
768 761 }
769 762  
770 763 /* split_free_page does not map the pages */
771 764  
... ... @@ -775,9 +768,8 @@
775 768 * so that compact_finished() may detect this
776 769 */
777 770 if (block_start_pfn < low_pfn)
778   - next_free_pfn = cc->migrate_pfn;
  771 + cc->free_pfn = cc->migrate_pfn;
779 772  
780   - cc->free_pfn = next_free_pfn;
781 773 cc->nr_freepages = nr_freepages;
782 774 }
783 775