]> Pileus Git - ~andy/linux/blobdiff - mm/compaction.c
mm: dump page when hitting a VM_BUG_ON using VM_BUG_ON_PAGE
[~andy/linux] / mm / compaction.c
index cc46db36e7089956977d549298424622d3ec3c42..e0ab02d70f13434059d1f05442285e0773189a1c 100644 (file)
@@ -459,6 +459,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
        unsigned long flags;
        bool locked = false;
        struct page *page = NULL, *valid_page = NULL;
+       bool skipped_async_unsuitable = false;
 
        /*
         * Ensure that there are not too many pages isolated from the LRU
@@ -534,6 +535,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
                if (!cc->sync && last_pageblock_nr != pageblock_nr &&
                    !migrate_async_suitable(get_pageblock_migratetype(page))) {
                        cc->finished_update_migrate = true;
+                       skipped_async_unsuitable = true;
                        goto next_pageblock;
                }
 
@@ -599,7 +601,7 @@ isolate_migratepages_range(struct zone *zone, struct compact_control *cc,
                if (__isolate_lru_page(page, mode) != 0)
                        continue;
 
-               VM_BUG_ON(PageTransCompound(page));
+               VM_BUG_ON_PAGE(PageTransCompound(page), page);
 
                /* Successfully isolated */
                cc->finished_update_migrate = true;
@@ -627,8 +629,13 @@ next_pageblock:
        if (locked)
                spin_unlock_irqrestore(&zone->lru_lock, flags);
 
-       /* Update the pageblock-skip if the whole pageblock was scanned */
-       if (low_pfn == end_pfn)
+       /*
+        * Update the pageblock-skip information and cached scanner pfn,
+        * if the whole pageblock was scanned without isolating any page.
+        * This is not done when pageblock was skipped due to being unsuitable
+        * for async compaction, so that eventual sync compaction can try.
+        */
+       if (low_pfn == end_pfn && !skipped_async_unsuitable)
                update_pageblock_skip(cc, valid_page, nr_isolated, true);
 
        trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
@@ -844,6 +851,10 @@ static int compact_finished(struct zone *zone,
 
        /* Compaction run completes if the migrate and free scanner meet */
        if (cc->free_pfn <= cc->migrate_pfn) {
+               /* Let the next compaction start anew. */
+               zone->compact_cached_migrate_pfn = zone->zone_start_pfn;
+               zone->compact_cached_free_pfn = zone_end_pfn(zone);
+
                /*
                 * Mark that the PG_migrate_skip information should be cleared
                 * by kswapd when it goes to sleep. kswapd does not set the