ksm: rmap_walk to remove_migation_ptes
[safe/jmp/linux-2.6] / mm / memory_hotplug.c
index 380aef4..bc5a081 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/migrate.h>
 #include <linux/page-isolation.h>
 #include <linux/pfn.h>
+#include <linux/suspend.h>
+#include <linux/mm_inline.h>
 
 #include <asm/tlbflush.h>
 
@@ -485,14 +487,18 @@ int __ref add_memory(int nid, u64 start, u64 size)
        struct resource *res;
        int ret;
 
+       lock_system_sleep();
+
        res = register_memory_resource(start, size);
+       ret = -EEXIST;
        if (!res)
-               return -EEXIST;
+               goto out;
 
        if (!node_online(nid)) {
                pgdat = hotadd_new_pgdat(nid, start);
+               ret = -ENOMEM;
                if (!pgdat)
-                       return -ENOMEM;
+                       goto out;
                new_pgdat = 1;
        }
 
@@ -515,7 +521,8 @@ int __ref add_memory(int nid, u64 start, u64 size)
                BUG_ON(ret);
        }
 
-       return ret;
+       goto out;
+
 error:
        /* rollback pgdat allocation and others */
        if (new_pgdat)
@@ -523,6 +530,8 @@ error:
        if (res)
                release_memory_resource(res);
 
+out:
+       unlock_system_sleep();
        return ret;
 }
 EXPORT_SYMBOL_GPL(add_memory);
@@ -664,6 +673,9 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                if (!ret) { /* Success */
                        list_add_tail(&page->lru, &source);
                        move_pages--;
+                       inc_zone_page_state(page, NR_ISOLATED_ANON +
+                                           page_is_file_cache(page));
+
                } else {
                        /* Becasue we don't have big zone->lock. we should
                           check this again here. */
@@ -759,6 +771,8 @@ int offline_pages(unsigned long start_pfn,
        if (!test_pages_in_a_zone(start_pfn, end_pfn))
                return -EINVAL;
 
+       lock_system_sleep();
+
        zone = page_zone(pfn_to_page(start_pfn));
        node = zone_to_nid(zone);
        nr_pages = end_pfn - start_pfn;
@@ -766,7 +780,7 @@ int offline_pages(unsigned long start_pfn,
        /* set above range as isolated */
        ret = start_isolate_page_range(start_pfn, end_pfn);
        if (ret)
-               return ret;
+               goto out;
 
        arg.start_pfn = start_pfn;
        arg.nr_pages = nr_pages;
@@ -839,11 +853,16 @@ repeat:
 
        setup_per_zone_wmarks();
        calculate_zone_inactive_ratio(zone);
+       if (!node_present_pages(node)) {
+               node_clear_state(node, N_HIGH_MEMORY);
+               kswapd_stop(node);
+       }
 
        vm_total_pages = nr_free_pagecache_pages();
        writeback_set_ratelimit();
 
        memory_notify(MEM_OFFLINE, &arg);
+       unlock_system_sleep();
        return 0;
 
 failed_removal:
@@ -853,6 +872,8 @@ failed_removal:
        /* pushback to free area */
        undo_isolate_page_range(start_pfn, end_pfn);
 
+out:
+       unlock_system_sleep();
        return ret;
 }