mm/compaction: speed up pageblock_pfn_to_page() when zone is contiguous
[linux-2.6-block.git] / mm / memory_hotplug.c
index 4af58a3a8ffa345c16fe190be76ba9f9e83113d4..24ea06393816c58b43a857bb5e1cc05dbdfc4712 100644 (file)
@@ -77,6 +77,9 @@ static struct {
 #define memhp_lock_acquire()      lock_map_acquire(&mem_hotplug.dep_map)
 #define memhp_lock_release()      lock_map_release(&mem_hotplug.dep_map)
 
+bool memhp_auto_online;
+EXPORT_SYMBOL_GPL(memhp_auto_online);
+
 void get_online_mems(void)
 {
        might_sleep();
@@ -138,7 +141,7 @@ static struct resource *register_memory_resource(u64 start, u64 size)
        res->name = "System RAM";
        res->start = start;
        res->end = start + size - 1;
-       res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+       res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
        if (request_resource(&iomem_resource, res) < 0) {
                pr_debug("System RAM resource %pR cannot be added\n", res);
                kfree(res);
@@ -509,6 +512,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
        int start_sec, end_sec;
        struct vmem_altmap *altmap;
 
+       clear_zone_contiguous(zone);
+
        /* during initialize mem_map, align hot-added range to section */
        start_sec = pfn_to_section_nr(phys_start_pfn);
        end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1);
@@ -521,7 +526,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
                if (altmap->base_pfn != phys_start_pfn
                                || vmem_altmap_offset(altmap) > nr_pages) {
                        pr_warn_once("memory add fail, invalid altmap\n");
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto out;
                }
                altmap->alloc = 0;
        }
@@ -539,7 +545,8 @@ int __ref __add_pages(int nid, struct zone *zone, unsigned long phys_start_pfn,
                err = 0;
        }
        vmemmap_populate_print_last();
-
+out:
+       set_zone_contiguous(zone);
        return err;
 }
 EXPORT_SYMBOL_GPL(__add_pages);
@@ -811,6 +818,8 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                }
        }
 
+       clear_zone_contiguous(zone);
+
        /*
         * We can only remove entire sections
         */
@@ -826,6 +835,9 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
                if (ret)
                        break;
        }
+
+       set_zone_contiguous(zone);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(__remove_pages);
@@ -1261,8 +1273,13 @@ int zone_for_memory(int nid, u64 start, u64 size, int zone_default,
        return zone_default;
 }
 
+static int online_memory_block(struct memory_block *mem, void *arg)
+{
+       return memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
+}
+
 /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
-int __ref add_memory_resource(int nid, struct resource *res)
+int __ref add_memory_resource(int nid, struct resource *res, bool online)
 {
        u64 start, size;
        pg_data_t *pgdat = NULL;
@@ -1322,6 +1339,11 @@ int __ref add_memory_resource(int nid, struct resource *res)
        /* create new memmap entry */
        firmware_map_add_hotplug(start, start + size, "System RAM");
 
+       /* online pages if requested */
+       if (online)
+               walk_memory_range(PFN_DOWN(start), PFN_UP(start + size - 1),
+                                 NULL, online_memory_block);
+
        goto out;
 
 error:
@@ -1345,7 +1367,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
        if (IS_ERR(res))
                return PTR_ERR(res);
 
-       ret = add_memory_resource(nid, res);
+       ret = add_memory_resource(nid, res, memhp_auto_online);
        if (ret < 0)
                release_memory_resource(res);
        return ret;