*/
        if (time_before(jiffies, zone->compact_blockskip_expire))
                return;
+
+       zone->compact_cached_migrate_pfn = start_pfn;
+       zone->compact_cached_free_pfn = end_pfn;
        zone->compact_blockskip_expire = jiffies + (HZ * 5);
 
        /* Walk the zone and mark every pageblock as suitable for isolation */
  * If no pages were isolated then mark this pageblock to be skipped in the
  * future. The information is later cleared by reset_isolation_suitable().
  */
-static void update_pageblock_skip(struct page *page, unsigned long nr_isolated)
+static void update_pageblock_skip(struct compact_control *cc,
+                       struct page *page, unsigned long nr_isolated,
+                       bool migrate_scanner)
 {
+       struct zone *zone = cc->zone;
        if (!page)
                return;
 
-       if (!nr_isolated)
+       if (!nr_isolated) {
+               unsigned long pfn = page_to_pfn(page);
                set_pageblock_skip(page);
+
+               /* Update where compaction should restart */
+               if (migrate_scanner) {
+                       if (!cc->finished_update_migrate &&
+                           pfn > zone->compact_cached_migrate_pfn)
+                               zone->compact_cached_migrate_pfn = pfn;
+               } else {
+                       if (!cc->finished_update_free &&
+                           pfn < zone->compact_cached_free_pfn)
+                               zone->compact_cached_free_pfn = pfn;
+               }
+       }
 }
 #else
 static inline bool isolation_suitable(struct compact_control *cc,
        return true;
 }
 
-static void update_pageblock_skip(struct page *page, unsigned long nr_isolated)
+static void update_pageblock_skip(struct compact_control *cc,
+                       struct page *page, unsigned long nr_isolated,
+                       bool migrate_scanner)
 {
 }
 #endif /* CONFIG_COMPACTION */
 
        /* Update the pageblock-skip if the whole pageblock was scanned */
        if (blockpfn == end_pfn)
-               update_pageblock_skip(valid_page, total_isolated);
+               update_pageblock_skip(cc, valid_page, total_isolated, false);
 
        return total_isolated;
 }
                 */
                if (!cc->sync && last_pageblock_nr != pageblock_nr &&
                    !migrate_async_suitable(get_pageblock_migratetype(page))) {
+                       cc->finished_update_migrate = true;
                        goto next_pageblock;
                }
 
                VM_BUG_ON(PageTransCompound(page));
 
                /* Successfully isolated */
+               cc->finished_update_migrate = true;
                del_page_from_lru_list(page, lruvec, page_lru(page));
                list_add(&page->lru, migratelist);
                cc->nr_migratepages++;
 
        /* Update the pageblock-skip if the whole pageblock was scanned */
        if (low_pfn == end_pfn)
-               update_pageblock_skip(valid_page, nr_isolated);
+               update_pageblock_skip(cc, valid_page, nr_isolated, true);
 
        trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
 
                 * looking for free pages, the search will restart here as
                 * page migration may have returned some pages to the allocator
                 */
-               if (isolated)
+               if (isolated) {
+                       cc->finished_update_free = true;
                        high_pfn = max(high_pfn, pfn);
+               }
        }
 
        /* split_free_page does not map the pages */
 static int compact_zone(struct zone *zone, struct compact_control *cc)
 {
        int ret;
+       unsigned long start_pfn = zone->zone_start_pfn;
+       unsigned long end_pfn = zone->zone_start_pfn + zone->spanned_pages;
 
        ret = compaction_suitable(zone, cc->order);
        switch (ret) {
                ;
        }
 
-       /* Setup to move all movable pages to the end of the zone */
-       cc->migrate_pfn = zone->zone_start_pfn;
-       cc->free_pfn = cc->migrate_pfn + zone->spanned_pages;
-       cc->free_pfn &= ~(pageblock_nr_pages-1);
+       /*
+        * Setup to move all movable pages to the end of the zone. Used cached
+        * information on where the scanners should start but check that it
+        * is initialised by ensuring the values are within zone boundaries.
+        */
+       cc->migrate_pfn = zone->compact_cached_migrate_pfn;
+       cc->free_pfn = zone->compact_cached_free_pfn;
+       if (cc->free_pfn < start_pfn || cc->free_pfn > end_pfn) {
+               cc->free_pfn = end_pfn & ~(pageblock_nr_pages-1);
+               zone->compact_cached_free_pfn = cc->free_pfn;
+       }
+       if (cc->migrate_pfn < start_pfn || cc->migrate_pfn > end_pfn) {
+               cc->migrate_pfn = start_pfn;
+               zone->compact_cached_migrate_pfn = cc->migrate_pfn;
+       }
 
        /* Clear pageblock skip if there are numerous alloc failures */
        if (zone->compact_defer_shift == COMPACT_MAX_DEFER_SHIFT)