Linux 4.6-rc7
[deliverable/linux.git] / mm / memory_hotplug.c
index 24ea06393816c58b43a857bb5e1cc05dbdfc4712..aa34431c3f31769b05a43820aca0a75c6975e8a3 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/hugetlb.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>
+#include <linux/compaction.h>
 
 #include <asm/tlbflush.h>
 
@@ -166,7 +167,7 @@ void get_page_bootmem(unsigned long info,  struct page *page,
        page->lru.next = (struct list_head *) type;
        SetPagePrivate(page);
        set_page_private(page, info);
-       atomic_inc(&page->_count);
+       page_ref_inc(page);
 }
 
 void put_page_bootmem(struct page *page)
@@ -177,7 +178,7 @@ void put_page_bootmem(struct page *page)
        BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
               type > MEMORY_HOTPLUG_MAX_BOOTMEM_TYPE);
 
-       if (atomic_dec_return(&page->_count) == 1) {
+       if (page_ref_dec_return(page) == 1) {
                ClearPagePrivate(page);
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
@@ -1054,14 +1055,13 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        arg.nr_pages = nr_pages;
        node_states_check_changes_online(nr_pages, zone, &arg);
 
-       nid = pfn_to_nid(pfn);
+       nid = zone_to_nid(zone);
 
        ret = memory_notify(MEM_GOING_ONLINE, &arg);
        ret = notifier_to_errno(ret);
-       if (ret) {
-               memory_notify(MEM_CANCEL_ONLINE, &arg);
-               return ret;
-       }
+       if (ret)
+               goto failed_addition;
+
        /*
         * If this zone is not populated, then it is not in zonelist.
         * This means the page allocator ignores this zone.
@@ -1079,12 +1079,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
                if (need_zonelists_rebuild)
                        zone_pcp_reset(zone);
                mutex_unlock(&zonelists_mutex);
-               printk(KERN_DEBUG "online_pages [mem %#010llx-%#010llx] failed\n",
-                      (unsigned long long) pfn << PAGE_SHIFT,
-                      (((unsigned long long) pfn + nr_pages)
-                           << PAGE_SHIFT) - 1);
-               memory_notify(MEM_CANCEL_ONLINE, &arg);
-               return ret;
+               goto failed_addition;
        }
 
        zone->present_pages += onlined_pages;
@@ -1094,7 +1089,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        pgdat_resize_unlock(zone->zone_pgdat, &flags);
 
        if (onlined_pages) {
-               node_states_set_node(zone_to_nid(zone), &arg);
+               node_states_set_node(nid, &arg);
                if (need_zonelists_rebuild)
                        build_all_zonelists(NULL, NULL);
                else
@@ -1105,8 +1100,10 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
 
        init_per_zone_wmark_min();
 
-       if (onlined_pages)
-               kswapd_run(zone_to_nid(zone));
+       if (onlined_pages) {
+               kswapd_run(nid);
+               kcompactd_run(nid);
+       }
 
        vm_total_pages = nr_free_pagecache_pages();
 
@@ -1115,6 +1112,13 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ
        if (onlined_pages)
                memory_notify(MEM_ONLINE, &arg);
        return 0;
+
+failed_addition:
+       pr_debug("online_pages [mem %#010llx-%#010llx] failed\n",
+                (unsigned long long) pfn << PAGE_SHIFT,
+                (((unsigned long long) pfn + nr_pages) << PAGE_SHIFT) - 1);
+       memory_notify(MEM_CANCEL_ONLINE, &arg);
+       return ret;
 }
 #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
 
@@ -1526,8 +1530,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 
                } else {
 #ifdef CONFIG_DEBUG_VM
-                       printk(KERN_ALERT "removing pfn %lx from LRU failed\n",
-                              pfn);
+                       pr_alert("removing pfn %lx from LRU failed\n", pfn);
                        dump_page(page, "failed to remove from LRU");
 #endif
                        put_page(page);
@@ -1855,7 +1858,7 @@ repeat:
                ret = -EBUSY;
                goto failed_removal;
        }
-       printk(KERN_INFO "Offlined Pages %ld\n", offlined_pages);
+       pr_info("Offlined Pages %ld\n", offlined_pages);
        /* Ok, all of our target is isolated.
           We cannot do rollback at this point. */
        offline_isolated_pages(start_pfn, end_pfn);
@@ -1880,8 +1883,10 @@ repeat:
                zone_pcp_update(zone);
 
        node_states_clear_node(node, &arg);
-       if (arg.status_change_nid >= 0)
+       if (arg.status_change_nid >= 0) {
                kswapd_stop(node);
+               kcompactd_stop(node);
+       }
 
        vm_total_pages = nr_free_pagecache_pages();
        writeback_set_ratelimit();
@@ -1890,9 +1895,9 @@ repeat:
        return 0;
 
 failed_removal:
-       printk(KERN_INFO "memory offlining [mem %#010llx-%#010llx] failed\n",
-              (unsigned long long) start_pfn << PAGE_SHIFT,
-              ((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
+       pr_debug("memory offlining [mem %#010llx-%#010llx] failed\n",
+                (unsigned long long) start_pfn << PAGE_SHIFT,
+                ((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
        memory_notify(MEM_CANCEL_OFFLINE, &arg);
        /* pushback to free area */
        undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
@@ -1965,8 +1970,7 @@ static int check_memblock_offlined_cb(struct memory_block *mem, void *arg)
 
                beginpa = PFN_PHYS(section_nr_to_pfn(mem->start_section_nr));
                endpa = PFN_PHYS(section_nr_to_pfn(mem->end_section_nr + 1))-1;
-               pr_warn("removing memory fails, because memory "
-                       "[%pa-%pa] is onlined\n",
+               pr_warn("removing memory fails, because memory [%pa-%pa] is onlined\n",
                        &beginpa, &endpa);
        }
 
This page took 0.040921 seconds and 5 git commands to generate.