Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-2.6-microblaze.git] / mm / memory_hotplug.c
index 2b6cc42..af41fb9 100644 (file)
@@ -596,8 +596,7 @@ void generic_online_page(struct page *page, unsigned int order)
         * so we should map it first. This is better than introducing a special
         * case in page freeing fast path.
         */
         * so we should map it first. This is better than introducing a special
         * case in page freeing fast path.
         */
-       if (debug_pagealloc_enabled_static())
-               kernel_map_pages(page, 1 << order, 1);
+       debug_pagealloc_map_pages(page, 1 << order);
        __free_pages_core(page, order);
        totalram_pages_add(1UL << order);
 #ifdef CONFIG_HIGHMEM
        __free_pages_core(page, order);
        totalram_pages_add(1UL << order);
 #ifdef CONFIG_HIGHMEM
@@ -1304,7 +1303,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                        if (WARN_ON(PageLRU(page)))
                                isolate_lru_page(page);
                        if (page_mapped(page))
                        if (WARN_ON(PageLRU(page)))
                                isolate_lru_page(page);
                        if (page_mapped(page))
-                               try_to_unmap(page, TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS);
+                               try_to_unmap(page, TTU_IGNORE_MLOCK);
                        continue;
                }
 
                        continue;
                }
 
@@ -1492,13 +1491,19 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages)
        }
        node = zone_to_nid(zone);
 
        }
        node = zone_to_nid(zone);
 
+       /*
+        * Disable pcplists so that page isolation cannot race with freeing
+        * in a way that pages from isolated pageblock are left on pcplists.
+        */
+       zone_pcp_disable(zone);
+
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn,
                                       MIGRATE_MOVABLE,
                                       MEMORY_OFFLINE | REPORT_FAILURE);
        if (ret) {
                reason = "failure to isolate range";
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn,
                                       MIGRATE_MOVABLE,
                                       MEMORY_OFFLINE | REPORT_FAILURE);
        if (ret) {
                reason = "failure to isolate range";
-               goto failed_removal;
+               goto failed_removal_pcplists_disabled;
        }
 
        arg.start_pfn = start_pfn;
        }
 
        arg.start_pfn = start_pfn;
@@ -1550,26 +1555,13 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages)
                        goto failed_removal_isolated;
                }
 
                        goto failed_removal_isolated;
                }
 
-               /*
-                * per-cpu pages are drained in start_isolate_page_range, but if
-                * there are still pages that are not free, make sure that we
-                * drain again, because when we isolated range we might
-                * have raced with another thread that was adding pages to pcp
-                * list.
-                *
-                * Forward progress should be still guaranteed because
-                * pages on the pcp list can only belong to MOVABLE_ZONE
-                * because has_unmovable_pages explicitly checks for
-                * PageBuddy on freed pages on other zones.
-                */
                ret = test_pages_isolated(start_pfn, end_pfn, MEMORY_OFFLINE);
                ret = test_pages_isolated(start_pfn, end_pfn, MEMORY_OFFLINE);
-               if (ret)
-                       drain_all_pages(zone);
+
        } while (ret);
 
        /* Mark all sections offline and remove free pages from the buddy. */
        __offline_isolated_pages(start_pfn, end_pfn);
        } while (ret);
 
        /* Mark all sections offline and remove free pages from the buddy. */
        __offline_isolated_pages(start_pfn, end_pfn);
-       pr_info("Offlined Pages %ld\n", nr_pages);
+       pr_debug("Offlined Pages %ld\n", nr_pages);
 
        /*
         * The memory sections are marked offline, and the pageblock flags
 
        /*
         * The memory sections are marked offline, and the pageblock flags
@@ -1580,6 +1572,8 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages)
        zone->nr_isolate_pageblock -= nr_pages / pageblock_nr_pages;
        spin_unlock_irqrestore(&zone->lock, flags);
 
        zone->nr_isolate_pageblock -= nr_pages / pageblock_nr_pages;
        spin_unlock_irqrestore(&zone->lock, flags);
 
+       zone_pcp_enable(zone);
+
        /* removal success */
        adjust_managed_page_count(pfn_to_page(start_pfn), -nr_pages);
        zone->present_pages -= nr_pages;
        /* removal success */
        adjust_managed_page_count(pfn_to_page(start_pfn), -nr_pages);
        zone->present_pages -= nr_pages;
@@ -1612,6 +1606,8 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages)
 failed_removal_isolated:
        undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
        memory_notify(MEM_CANCEL_OFFLINE, &arg);
 failed_removal_isolated:
        undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
        memory_notify(MEM_CANCEL_OFFLINE, &arg);
+failed_removal_pcplists_disabled:
+       zone_pcp_enable(zone);
 failed_removal:
        pr_debug("memory offlining [mem %#010llx-%#010llx] failed due to %s\n",
                 (unsigned long long) start_pfn << PAGE_SHIFT,
 failed_removal:
        pr_debug("memory offlining [mem %#010llx-%#010llx] failed due to %s\n",
                 (unsigned long long) start_pfn << PAGE_SHIFT,