mm/mmap.c: initialize align_offset explicitly for vm_unmapped_area
[linux-2.6-microblaze.git] / mm / memory_hotplug.c
index 19389cd..635e8e2 100644 (file)
@@ -67,18 +67,17 @@ void put_online_mems(void)
 bool movable_node_enabled = false;
 
 #ifndef CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE
-bool memhp_auto_online;
+int memhp_default_online_type = MMOP_OFFLINE;
 #else
-bool memhp_auto_online = true;
+int memhp_default_online_type = MMOP_ONLINE;
 #endif
-EXPORT_SYMBOL_GPL(memhp_auto_online);
 
 static int __init setup_memhp_default_state(char *str)
 {
-       if (!strcmp(str, "online"))
-               memhp_auto_online = true;
-       else if (!strcmp(str, "offline"))
-               memhp_auto_online = false;
+       const int online_type = memhp_online_type_from_str(str);
+
+       if (online_type >= 0)
+               memhp_default_online_type = online_type;
 
        return 1;
 }
@@ -105,7 +104,13 @@ static struct resource *register_memory_resource(u64 start, u64 size)
        unsigned long flags =  IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
        char *resource_name = "System RAM";
 
-       if (start + size > max_mem_size)
+       /*
+        * Make sure value parsed from 'mem=' only restricts memory adding
+        * while booting, so that memory hotplug won't be impacted. Please
+        * refer to document of 'mem=' in kernel-parameters.txt for more
+        * details.
+        */
+       if (start + size > max_mem_size && system_state < SYSTEM_RUNNING)
                return ERR_PTR(-E2BIG);
 
        /*
@@ -301,8 +306,9 @@ static int check_hotplug_memory_addressable(unsigned long pfn,
 int __ref __add_pages(int nid, unsigned long pfn, unsigned long nr_pages,
                struct mhp_restrictions *restrictions)
 {
+       const unsigned long end_pfn = pfn + nr_pages;
+       unsigned long cur_nr_pages;
        int err;
-       unsigned long nr, start_sec, end_sec;
        struct vmem_altmap *altmap = restrictions->altmap;
 
        err = check_hotplug_memory_addressable(pfn, nr_pages);
@@ -325,18 +331,13 @@ int __ref __add_pages(int nid, unsigned long pfn, unsigned long nr_pages,
        if (err)
                return err;
 
-       start_sec = pfn_to_section_nr(pfn);
-       end_sec = pfn_to_section_nr(pfn + nr_pages - 1);
-       for (nr = start_sec; nr <= end_sec; nr++) {
-               unsigned long pfns;
-
-               pfns = min(nr_pages, PAGES_PER_SECTION
-                               - (pfn & ~PAGE_SECTION_MASK));
-               err = sparse_add_section(nid, pfn, pfns, altmap);
+       for (; pfn < end_pfn; pfn += cur_nr_pages) {
+               /* Select all remaining pages up to the next section boundary */
+               cur_nr_pages = min(end_pfn - pfn,
+                                  SECTION_ALIGN_UP(pfn + 1) - pfn);
+               err = sparse_add_section(nid, pfn, cur_nr_pages, altmap);
                if (err)
                        break;
-               pfn += pfns;
-               nr_pages -= pfns;
                cond_resched();
        }
        vmemmap_populate_print_last();
@@ -494,7 +495,7 @@ static void __remove_section(unsigned long pfn, unsigned long nr_pages,
                             unsigned long map_offset,
                             struct vmem_altmap *altmap)
 {
-       struct mem_section *ms = __nr_to_section(pfn_to_section_nr(pfn));
+       struct mem_section *ms = __pfn_to_section(pfn);
 
        if (WARN_ON_ONCE(!valid_section(ms)))
                return;
@@ -528,7 +529,8 @@ void __remove_pages(unsigned long pfn, unsigned long nr_pages,
        for (; pfn < end_pfn; pfn += cur_nr_pages) {
                cond_resched();
                /* Select all remaining pages up to the next section boundary */
-               cur_nr_pages = min(end_pfn - pfn, -(pfn | PAGE_SECTION_MASK));
+               cur_nr_pages = min(end_pfn - pfn,
+                                  SECTION_ALIGN_UP(pfn + 1) - pfn);
                __remove_section(pfn, cur_nr_pages, map_offset, altmap);
                map_offset = 0;
        }
@@ -988,6 +990,7 @@ static int check_hotplug_memory_range(u64 start, u64 size)
 
 static int online_memory_block(struct memory_block *mem, void *arg)
 {
+       mem->online_type = memhp_default_online_type;
        return device_online(&mem->dev);
 }
 
@@ -1060,7 +1063,7 @@ int __ref add_memory_resource(int nid, struct resource *res)
        mem_hotplug_done();
 
        /* online pages if requested */
-       if (memhp_auto_online)
+       if (memhp_default_online_type != MMOP_OFFLINE)
                walk_memory_blocks(start, size, NULL, online_memory_block);
 
        return ret;
@@ -1317,7 +1320,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                        list_add_tail(&page->lru, &source);
                        if (!__PageMovable(page))
                                inc_node_page_state(page, NR_ISOLATED_ANON +
-                                                   page_is_file_cache(page));
+                                                   page_is_file_lru(page));
 
                } else {
                        pr_warn("failed to isolate pfn %lx\n", pfn);