squash mm: Export migrate_page_... : also make it non-static
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / mm / compaction.c
index 05ccb4cc0bdb984dc2613461703587ec199804cd..eeaaa929d1debf611c1cd87adb3e949c701580bb 100644 (file)
@@ -134,6 +134,10 @@ static void update_pageblock_skip(struct compact_control *cc,
                        bool migrate_scanner)
 {
        struct zone *zone = cc->zone;
+
+       if (cc->ignore_skip_hint)
+               return;
+
        if (!page)
                return;
 
@@ -248,7 +252,6 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 {
        int nr_scanned = 0, total_isolated = 0;
        struct page *cursor, *valid_page = NULL;
-       unsigned long nr_strict_required = end_pfn - blockpfn;
        unsigned long flags;
        bool locked = false;
 
@@ -261,11 +264,12 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 
                nr_scanned++;
                if (!pfn_valid_within(blockpfn))
-                       continue;
+                       goto isolate_fail;
+
                if (!valid_page)
                        valid_page = page;
                if (!PageBuddy(page))
-                       continue;
+                       goto isolate_fail;
 
                /*
                 * The zone lock must be held to isolate freepages.
@@ -286,12 +290,10 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
 
                /* Recheck this is a buddy page under lock */
                if (!PageBuddy(page))
-                       continue;
+                       goto isolate_fail;
 
                /* Found a free page, break it into order-0 pages */
                isolated = split_free_page(page);
-               if (!isolated && strict)
-                       break;
                total_isolated += isolated;
                for (i = 0; i < isolated; i++) {
                        list_add(&page->lru, freelist);
@@ -302,7 +304,15 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
                if (isolated) {
                        blockpfn += isolated - 1;
                        cursor += isolated - 1;
+                       continue;
                }
+
+isolate_fail:
+               if (strict)
+                       break;
+               else
+                       continue;
+
        }
 
        trace_mm_compaction_isolate_freepages(nr_scanned, total_isolated);
@@ -312,7 +322,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
         * pages requested were isolated. If there were any failures, 0 is
         * returned and CMA will fail.
         */
-       if (strict && nr_strict_required > total_isolated)
+       if (strict && blockpfn < end_pfn)
                total_isolated = 0;
 
        if (locked)
@@ -647,17 +657,21 @@ static void isolate_freepages(struct zone *zone,
                                struct compact_control *cc)
 {
        struct page *page;
-       unsigned long high_pfn, low_pfn, pfn, z_end_pfn, end_pfn;
+       unsigned long high_pfn, low_pfn, pfn, z_end_pfn;
        int nr_freepages = cc->nr_freepages;
        struct list_head *freelist = &cc->freepages;
 
        /*
         * Initialise the free scanner. The starting point is where we last
-        * scanned from (or the end of the zone if starting). The low point
-        * is the end of the pageblock the migration scanner is using.
+        * successfully isolated from, zone-cached value, or the end of the
+        * zone when isolating for the first time. We need this aligned to
+        * the pageblock boundary, because we do pfn -= pageblock_nr_pages
+        * in the for loop.
+        * The low boundary is the end of the pageblock the migration scanner
+        * is using.
         */
-       pfn = cc->free_pfn;
-       low_pfn = cc->migrate_pfn + pageblock_nr_pages;
+       pfn = cc->free_pfn & ~(pageblock_nr_pages-1);
+       low_pfn = ALIGN(cc->migrate_pfn + 1, pageblock_nr_pages);
 
        /*
         * Take care that if the migration scanner is at the end of the zone
@@ -673,9 +687,10 @@ static void isolate_freepages(struct zone *zone,
         * pages on cc->migratepages. We stop searching if the migrate
         * and free page scanners meet or enough free pages are isolated.
         */
-       for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
+       for (; pfn >= low_pfn && cc->nr_migratepages > nr_freepages;
                                        pfn -= pageblock_nr_pages) {
                unsigned long isolated;
+               unsigned long end_pfn;
 
                if (!pfn_valid(pfn))
                        continue;
@@ -703,13 +718,10 @@ static void isolate_freepages(struct zone *zone,
                isolated = 0;
 
                /*
-                * As pfn may not start aligned, pfn+pageblock_nr_page
-                * may cross a MAX_ORDER_NR_PAGES boundary and miss
-                * a pfn_valid check. Ensure isolate_freepages_block()
-                * only scans within a pageblock
+                * Take care when isolating in last pageblock of a zone which
+                * ends in the middle of a pageblock.
                 */
-               end_pfn = ALIGN(pfn + 1, pageblock_nr_pages);
-               end_pfn = min(end_pfn, z_end_pfn);
+               end_pfn = min(pfn + pageblock_nr_pages, z_end_pfn);
                isolated = isolate_freepages_block(cc, pfn, end_pfn,
                                                   freelist, false);
                nr_freepages += isolated;
@@ -728,7 +740,14 @@ static void isolate_freepages(struct zone *zone,
        /* split_free_page does not map the pages */
        map_pages(freelist);
 
-       cc->free_pfn = high_pfn;
+       /*
+        * If we crossed the migrate scanner, we want to keep it that way
+        * so that compact_finished() may detect this
+        */
+       if (pfn < low_pfn)
+               cc->free_pfn = max(pfn, zone->zone_start_pfn);
+       else
+               cc->free_pfn = high_pfn;
        cc->nr_freepages = nr_freepages;
 }
 
@@ -862,7 +881,7 @@ static int compact_finished(struct zone *zone,
                        return COMPACT_PARTIAL;
 
                /* Job done if allocation would set block type */
-               if (cc->order >= pageblock_order && area->nr_free)
+               if (order >= pageblock_order && area->nr_free)
                        return COMPACT_PARTIAL;
        }
 
@@ -936,6 +955,14 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                ;
        }
 
+       /*
+        * Clear pageblock skip if there were failures recently and compaction
+        * is about to be retried after being deferred. kswapd does not do
+        * this reset as it'll reset the cached information when going to sleep.
+        */
+       if (compaction_restarting(zone, cc->order) && !current_is_kswapd())
+               __reset_isolation_suitable(zone);
+
        /*
         * 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
@@ -952,14 +979,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                zone->compact_cached_migrate_pfn = cc->migrate_pfn;
        }
 
-       /*
-        * Clear pageblock skip if there were failures recently and compaction
-        * is about to be retried after being deferred. kswapd does not do
-        * this reset as it'll reset the cached information when going to sleep.
-        */
-       if (compaction_restarting(zone, cc->order) && !current_is_kswapd())
-               __reset_isolation_suitable(zone);
-
        migrate_prep_local();
 
        while ((ret = compact_finished(zone, cc)) == COMPACT_CONTINUE) {
@@ -993,7 +1012,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                if (err) {
                        putback_movable_pages(&cc->migratepages);
                        cc->nr_migratepages = 0;
-                       if (err == -ENOMEM) {
+                       /*
+                        * migrate_pages() may return -ENOMEM when scanners meet
+                        * and we want compact_finished() to detect it
+                        */
+                       if (err == -ENOMEM && cc->free_pfn > cc->migrate_pfn) {
                                ret = COMPACT_PARTIAL;
                                goto out;
                        }