mm/memory_hotplug: MEMHP_MERGE_RESOURCE -> MHP_MERGE_RESOURCE
[sfrench/cifs-2.6.git] / mm / memory_hotplug.c
index 02378f11e2d67c347d589dae8ed58d607acacd7c..6a02c3f42717e3864a86e46e56acc9440f2c8789 100644 (file)
@@ -67,17 +67,17 @@ void put_online_mems(void)
 bool movable_node_enabled = false;
 
 #ifndef CONFIG_MEMORY_HOTPLUG_DEFAULT_ONLINE
-int memhp_default_online_type = MMOP_OFFLINE;
+int mhp_default_online_type = MMOP_OFFLINE;
 #else
-int memhp_default_online_type = MMOP_ONLINE;
+int mhp_default_online_type = MMOP_ONLINE;
 #endif
 
 static int __init setup_memhp_default_state(char *str)
 {
-       const int online_type = memhp_online_type_from_str(str);
+       const int online_type = mhp_online_type_from_str(str);
 
        if (online_type >= 0)
-               memhp_default_online_type = online_type;
+               mhp_default_online_type = online_type;
 
        return 1;
 }
@@ -308,6 +308,7 @@ static int check_hotplug_memory_addressable(unsigned long pfn,
 struct page *pfn_to_online_page(unsigned long pfn)
 {
        unsigned long nr = pfn_to_section_nr(pfn);
+       struct dev_pagemap *pgmap;
        struct mem_section *ms;
 
        if (nr >= NR_MEM_SECTIONS)
@@ -327,6 +328,22 @@ struct page *pfn_to_online_page(unsigned long pfn)
        if (!pfn_section_valid(ms, pfn))
                return NULL;
 
+       if (!online_device_section(ms))
+               return pfn_to_page(pfn);
+
+       /*
+        * Slowpath: when ZONE_DEVICE collides with
+        * ZONE_{NORMAL,MOVABLE} within the same section some pfns in
+        * the section may be 'offline' but 'valid'. Only
+        * get_dev_pagemap() can determine sub-section online status.
+        */
+       pgmap = get_dev_pagemap(pfn, NULL);
+       put_dev_pagemap(pgmap);
+
+       /* The presence of a pgmap indicates ZONE_DEVICE offline pfn */
+       if (pgmap)
+               return NULL;
+
        return pfn_to_page(pfn);
 }
 EXPORT_SYMBOL_GPL(pfn_to_online_page);
@@ -709,6 +726,14 @@ static void __meminit resize_pgdat_range(struct pglist_data *pgdat, unsigned lon
        pgdat->node_spanned_pages = max(start_pfn + nr_pages, old_end_pfn) - pgdat->node_start_pfn;
 
 }
+
+static void section_taint_zone_device(unsigned long pfn)
+{
+       struct mem_section *ms = __pfn_to_section(pfn);
+
+       ms->section_mem_map |= SECTION_TAINT_ZONE_DEVICE;
+}
+
 /*
  * Associate the pfn range with the given zone, initializing the memmaps
  * and resizing the pgdat/zone data to span the added pages. After this
@@ -738,6 +763,19 @@ void __ref move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
        resize_pgdat_range(pgdat, start_pfn, nr_pages);
        pgdat_resize_unlock(pgdat, &flags);
 
+       /*
+        * Subsection population requires care in pfn_to_online_page().
+        * Set the taint to enable the slow path detection of
+        * ZONE_DEVICE pages in an otherwise  ZONE_{NORMAL,MOVABLE}
+        * section.
+        */
+       if (zone_is_zone_device(zone)) {
+               if (!IS_ALIGNED(start_pfn, PAGES_PER_SECTION))
+                       section_taint_zone_device(start_pfn);
+               if (!IS_ALIGNED(start_pfn + nr_pages, PAGES_PER_SECTION))
+                       section_taint_zone_device(start_pfn + nr_pages);
+       }
+
        /*
         * TODO now we have a visible range of pages which are not associated
         * with their zone properly. Not nice but set_pfnblock_flags_mask
@@ -1038,7 +1076,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;
+       mem->online_type = mhp_default_online_type;
        return device_online(&mem->dev);
 }
 
@@ -1115,11 +1153,11 @@ int __ref add_memory_resource(int nid, struct resource *res, mhp_t mhp_flags)
         * In case we're allowed to merge the resource, flag it and trigger
         * merging now that adding succeeded.
         */
-       if (mhp_flags & MEMHP_MERGE_RESOURCE)
+       if (mhp_flags & MHP_MERGE_RESOURCE)
                merge_system_ram_resource(res);
 
        /* online pages if requested */
-       if (memhp_default_online_type != MMOP_OFFLINE)
+       if (mhp_default_online_type != MMOP_OFFLINE)
                walk_memory_blocks(start, size, NULL, online_memory_block);
 
        return ret;