<= (cc->migrate_pfn >> pageblock_order);
 }
 
-/* Reorder the free list to reduce repeated future searches */
+/*
+ * Used when scanning for a suitable migration target which scans freelists
+ * in reverse. Reorders the list such as the unscanned pages are scanned
+ * first on the next iteration of the free scanner
+ */
+static void
+move_freelist_head(struct list_head *freelist, struct page *freepage)
+{
+       LIST_HEAD(sublist);
+
+       if (!list_is_last(freelist, &freepage->lru)) {
+               list_cut_before(&sublist, freelist, &freepage->lru);
+               if (!list_empty(&sublist))
+                       list_splice_tail(&sublist, freelist);
+       }
+}
+
+/*
+ * Similar to move_freelist_head except used by the migration scanner
+ * when scanning forward. It's possible for these list operations to
+ * move against each other if they search the free list exactly in
+ * lockstep.
+ */
 static void
 move_freelist_tail(struct list_head *freelist, struct page *freepage)
 {
        }
 }
 
+static void
+fast_isolate_around(struct compact_control *cc, unsigned long pfn, unsigned long nr_isolated)
+{
+       unsigned long start_pfn, end_pfn;
+       struct page *page = pfn_to_page(pfn);
+
+       /* Do not search around if there are enough pages already */
+       if (cc->nr_freepages >= cc->nr_migratepages)
+               return;
+
+       /* Minimise scanning during async compaction */
+       if (cc->direct_compaction && cc->mode == MIGRATE_ASYNC)
+               return;
+
+       /* Pageblock boundaries */
+       start_pfn = pageblock_start_pfn(pfn);
+       end_pfn = min(start_pfn + pageblock_nr_pages, zone_end_pfn(cc->zone));
+
+       /* Scan before */
+       if (start_pfn != pfn) {
+               isolate_freepages_block(cc, &start_pfn, pfn, &cc->freepages, false);
+               if (cc->nr_freepages >= cc->nr_migratepages)
+                       return;
+       }
+
+       /* Scan after */
+       start_pfn = pfn + nr_isolated;
+       if (start_pfn != end_pfn)
+               isolate_freepages_block(cc, &start_pfn, end_pfn, &cc->freepages, false);
+
+       /* Skip this pageblock in the future as it's full or nearly full */
+       if (cc->nr_freepages < cc->nr_migratepages)
+               set_pageblock_skip(page);
+}
+
+static unsigned long
+fast_isolate_freepages(struct compact_control *cc)
+{
+       unsigned int limit = min(1U, freelist_scan_limit(cc) >> 1);
+       unsigned int nr_scanned = 0;
+       unsigned long low_pfn, min_pfn, high_pfn = 0, highest = 0;
+       unsigned long nr_isolated = 0;
+       unsigned long distance;
+       struct page *page = NULL;
+       bool scan_start = false;
+       int order;
+
+       /* Full compaction passes in a negative order */
+       if (cc->order <= 0)
+               return cc->free_pfn;
+
+       /*
+        * If starting the scan, use a deeper search and use the highest
+        * PFN found if a suitable one is not found.
+        */
+       if (cc->free_pfn == pageblock_start_pfn(zone_end_pfn(cc->zone) - 1)) {
+               limit = pageblock_nr_pages >> 1;
+               scan_start = true;
+       }
+
+       /*
+        * Preferred point is in the top quarter of the scan space but take
+        * a pfn from the top half if the search is problematic.
+        */
+       distance = (cc->free_pfn - cc->migrate_pfn);
+       low_pfn = pageblock_start_pfn(cc->free_pfn - (distance >> 2));
+       min_pfn = pageblock_start_pfn(cc->free_pfn - (distance >> 1));
+
+       if (WARN_ON_ONCE(min_pfn > low_pfn))
+               low_pfn = min_pfn;
+
+       for (order = cc->order - 1;
+            order >= 0 && !page;
+            order--) {
+               struct free_area *area = &cc->zone->free_area[order];
+               struct list_head *freelist;
+               struct page *freepage;
+               unsigned long flags;
+               unsigned int order_scanned = 0;
+
+               if (!area->nr_free)
+                       continue;
+
+               spin_lock_irqsave(&cc->zone->lock, flags);
+               freelist = &area->free_list[MIGRATE_MOVABLE];
+               list_for_each_entry_reverse(freepage, freelist, lru) {
+                       unsigned long pfn;
+
+                       order_scanned++;
+                       nr_scanned++;
+                       pfn = page_to_pfn(freepage);
+
+                       if (pfn >= highest)
+                               highest = pageblock_start_pfn(pfn);
+
+                       if (pfn >= low_pfn) {
+                               cc->fast_search_fail = 0;
+                               page = freepage;
+                               break;
+                       }
+
+                       if (pfn >= min_pfn && pfn > high_pfn) {
+                               high_pfn = pfn;
+
+                               /* Shorten the scan if a candidate is found */
+                               limit >>= 1;
+                       }
+
+                       if (order_scanned >= limit)
+                               break;
+               }
+
+               /* Use a minimum pfn if a preferred one was not found */
+               if (!page && high_pfn) {
+                       page = pfn_to_page(high_pfn);
+
+                       /* Update freepage for the list reorder below */
+                       freepage = page;
+               }
+
+               /* Reorder to so a future search skips recent pages */
+               move_freelist_head(freelist, freepage);
+
+               /* Isolate the page if available */
+               if (page) {
+                       if (__isolate_free_page(page, order)) {
+                               set_page_private(page, order);
+                               nr_isolated = 1 << order;
+                               cc->nr_freepages += nr_isolated;
+                               list_add_tail(&page->lru, &cc->freepages);
+                               count_compact_events(COMPACTISOLATED, nr_isolated);
+                       } else {
+                               /* If isolation fails, abort the search */
+                               order = -1;
+                               page = NULL;
+                       }
+               }
+
+               spin_unlock_irqrestore(&cc->zone->lock, flags);
+
+               /*
+                * Smaller scan on next order so the total scan ig related
+                * to freelist_scan_limit.
+                */
+               if (order_scanned >= limit)
+                       limit = min(1U, limit >> 1);
+       }
+
+       if (!page) {
+               cc->fast_search_fail++;
+               if (scan_start) {
+                       /*
+                        * Use the highest PFN found above min. If one was
+                        * not found, be pessemistic for direct compaction
+                        * and use the min mark.
+                        */
+                       if (highest) {
+                               page = pfn_to_page(highest);
+                               cc->free_pfn = highest;
+                       } else {
+                               if (cc->direct_compaction) {
+                                       page = pfn_to_page(min_pfn);
+                                       cc->free_pfn = min_pfn;
+                               }
+                       }
+               }
+       }
+
+       if (highest && highest > cc->zone->compact_cached_free_pfn)
+               cc->zone->compact_cached_free_pfn = highest;
+
+       cc->total_free_scanned += nr_scanned;
+       if (!page)
+               return cc->free_pfn;
+
+       low_pfn = page_to_pfn(page);
+       fast_isolate_around(cc, low_pfn, nr_isolated);
+       return low_pfn;
+}
+
 /*
  * Based on information in the current compact_control, find blocks
  * suitable for isolating free pages from and then isolate them.
        unsigned long low_pfn;       /* lowest pfn scanner is able to scan */
        struct list_head *freelist = &cc->freepages;
 
+       /* Try a small search of the free lists for a candidate */
+       isolate_start_pfn = fast_isolate_freepages(cc);
+       if (cc->nr_freepages)
+               goto splitmap;
+
        /*
         * Initialise the free scanner. The starting point is where we last
         * successfully isolated from, zone-cached value, or the end of the
         * is using.
         */
        isolate_start_pfn = cc->free_pfn;
-       block_start_pfn = pageblock_start_pfn(cc->free_pfn);
+       block_start_pfn = pageblock_start_pfn(isolate_start_pfn);
        block_end_pfn = min(block_start_pfn + pageblock_nr_pages,
                                                zone_end_pfn(zone));
        low_pfn = pageblock_end_pfn(cc->migrate_pfn);
                }
        }
 
-       /* __isolate_free_page() does not map the pages */
-       split_map_pages(freelist);
-
        /*
         * Record where the free scanner will restart next time. Either we
         * broke from the loop and set isolate_start_pfn based on the last
         * and the loop terminated due to isolate_start_pfn < low_pfn
         */
        cc->free_pfn = isolate_start_pfn;
+
+splitmap:
+       /* __isolate_free_page() does not map the pages */
+       split_map_pages(freelist);
 }
 
 /*