Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
[linux-2.6-microblaze.git] / mm / memory_hotplug.c
index 929d420..55ac23e 100644 (file)
@@ -598,11 +598,6 @@ int restore_online_page_callback(online_page_callback_t callback)
 }
 EXPORT_SYMBOL_GPL(restore_online_page_callback);
 
-void __online_page_set_limits(struct page *page)
-{
-}
-EXPORT_SYMBOL_GPL(__online_page_set_limits);
-
 void generic_online_page(struct page *page, unsigned int order)
 {
        kernel_map_pages(page, 1 << order, 1);
@@ -1187,7 +1182,8 @@ static bool is_pageblock_removable_nolock(unsigned long pfn)
        if (!zone_spans_pfn(zone, pfn))
                return false;
 
-       return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE, SKIP_HWPOISON);
+       return !has_unmovable_pages(zone, page, 0, MIGRATE_MOVABLE,
+                                   MEMORY_OFFLINE);
 }
 
 /* Checks if this range of memory is likely to be hot-removable. */
@@ -1402,7 +1398,8 @@ static int
 check_pages_isolated_cb(unsigned long start_pfn, unsigned long nr_pages,
                        void *data)
 {
-       return test_pages_isolated(start_pfn, start_pfn + nr_pages, true);
+       return test_pages_isolated(start_pfn, start_pfn + nr_pages,
+                                  MEMORY_OFFLINE);
 }
 
 static int __init cmdline_parse_movable_node(char *p)
@@ -1483,10 +1480,19 @@ static void node_states_clear_node(int node, struct memory_notify *arg)
                node_clear_state(node, N_MEMORY);
 }
 
+static int count_system_ram_pages_cb(unsigned long start_pfn,
+                                    unsigned long nr_pages, void *data)
+{
+       unsigned long *nr_system_ram_pages = data;
+
+       *nr_system_ram_pages += nr_pages;
+       return 0;
+}
+
 static int __ref __offline_pages(unsigned long start_pfn,
                  unsigned long end_pfn)
 {
-       unsigned long pfn, nr_pages;
+       unsigned long pfn, nr_pages = 0;
        unsigned long offlined_pages = 0;
        int ret, node, nr_isolate_pageblock;
        unsigned long flags;
@@ -1497,6 +1503,22 @@ static int __ref __offline_pages(unsigned long start_pfn,
 
        mem_hotplug_begin();
 
+       /*
+        * Don't allow to offline memory blocks that contain holes.
+        * Consequently, memory blocks with holes can never get onlined
+        * via the hotplug path - online_pages() - as hotplugged memory has
+        * no holes. This way, we e.g., don't have to worry about marking
+        * memory holes PG_reserved, don't need pfn_valid() checks, and can
+        * avoid using walk_system_ram_range() later.
+        */
+       walk_system_ram_range(start_pfn, end_pfn - start_pfn, &nr_pages,
+                             count_system_ram_pages_cb);
+       if (nr_pages != end_pfn - start_pfn) {
+               ret = -EINVAL;
+               reason = "memory holes";
+               goto failed_removal;
+       }
+
        /* This makes hotplug much easier...and readable.
           we assume this for now. .*/
        if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
@@ -1508,12 +1530,11 @@ static int __ref __offline_pages(unsigned long start_pfn,
 
        zone = page_zone(pfn_to_page(valid_start));
        node = zone_to_nid(zone);
-       nr_pages = end_pfn - start_pfn;
 
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn,
                                       MIGRATE_MOVABLE,
-                                      SKIP_HWPOISON | REPORT_FAILURE);
+                                      MEMORY_OFFLINE | REPORT_FAILURE);
        if (ret < 0) {
                reason = "failure to isolate range";
                goto failed_removal;