diff options
-rw-r--r-- | drivers/base/node.c | 2 | ||||
-rw-r--r-- | include/linux/memory.h | 1 | ||||
-rw-r--r-- | mm/memory_hotplug.c | 27 | ||||
-rw-r--r-- | mm/page_alloc.c | 28 | ||||
-rw-r--r-- | mm/sparse.c | 8 |
5 files changed, 28 insertions, 38 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index 92b00a7e6a02..7a3a580821e0 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -407,6 +407,8 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid, | |||
407 | 407 | ||
408 | if (!mem_blk) | 408 | if (!mem_blk) |
409 | return -EFAULT; | 409 | return -EFAULT; |
410 | |||
411 | mem_blk->nid = nid; | ||
410 | if (!node_online(nid)) | 412 | if (!node_online(nid)) |
411 | return 0; | 413 | return 0; |
412 | 414 | ||
diff --git a/include/linux/memory.h b/include/linux/memory.h index 9f8cd856ca1e..31ca3e28b0eb 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h | |||
@@ -33,6 +33,7 @@ struct memory_block { | |||
33 | void *hw; /* optional pointer to fw/hw data */ | 33 | void *hw; /* optional pointer to fw/hw data */ |
34 | int (*phys_callback)(struct memory_block *); | 34 | int (*phys_callback)(struct memory_block *); |
35 | struct device dev; | 35 | struct device dev; |
36 | int nid; /* NID for this memory block */ | ||
36 | }; | 37 | }; |
37 | 38 | ||
38 | int arch_get_memory_phys_device(unsigned long start_pfn); | 39 | int arch_get_memory_phys_device(unsigned long start_pfn); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 477e183a4ac7..6a9ba14e18ed 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
@@ -250,7 +250,6 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn, | |||
250 | struct vmem_altmap *altmap, bool want_memblock) | 250 | struct vmem_altmap *altmap, bool want_memblock) |
251 | { | 251 | { |
252 | int ret; | 252 | int ret; |
253 | int i; | ||
254 | 253 | ||
255 | if (pfn_valid(phys_start_pfn)) | 254 | if (pfn_valid(phys_start_pfn)) |
256 | return -EEXIST; | 255 | return -EEXIST; |
@@ -259,23 +258,6 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn, | |||
259 | if (ret < 0) | 258 | if (ret < 0) |
260 | return ret; | 259 | return ret; |
261 | 260 | ||
262 | /* | ||
263 | * Make all the pages reserved so that nobody will stumble over half | ||
264 | * initialized state. | ||
265 | * FIXME: We also have to associate it with a node because page_to_nid | ||
266 | * relies on having page with the proper node. | ||
267 | */ | ||
268 | for (i = 0; i < PAGES_PER_SECTION; i++) { | ||
269 | unsigned long pfn = phys_start_pfn + i; | ||
270 | struct page *page; | ||
271 | if (!pfn_valid(pfn)) | ||
272 | continue; | ||
273 | |||
274 | page = pfn_to_page(pfn); | ||
275 | set_page_node(page, nid); | ||
276 | SetPageReserved(page); | ||
277 | } | ||
278 | |||
279 | if (!want_memblock) | 261 | if (!want_memblock) |
280 | return 0; | 262 | return 0; |
281 | 263 | ||
@@ -908,8 +890,15 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages, int online_typ | |||
908 | int nid; | 890 | int nid; |
909 | int ret; | 891 | int ret; |
910 | struct memory_notify arg; | 892 | struct memory_notify arg; |
893 | struct memory_block *mem; | ||
894 | |||
895 | /* | ||
896 | * We can't use pfn_to_nid() because nid might be stored in struct page | ||
897 | * which is not yet initialized. Instead, we find nid from memory block. | ||
898 | */ | ||
899 | mem = find_memory_block(__pfn_to_section(pfn)); | ||
900 | nid = mem->nid; | ||
911 | 901 | ||
912 | nid = pfn_to_nid(pfn); | ||
913 | /* associate pfn range with the zone */ | 902 | /* associate pfn range with the zone */ |
914 | zone = move_pfn_range(online_type, nid, pfn, nr_pages); | 903 | zone = move_pfn_range(online_type, nid, pfn, nr_pages); |
915 | 904 | ||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 3183eb2f579c..a3e2ba4f76bb 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1143,10 +1143,9 @@ static void free_one_page(struct zone *zone, | |||
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | static void __meminit __init_single_page(struct page *page, unsigned long pfn, | 1145 | static void __meminit __init_single_page(struct page *page, unsigned long pfn, |
1146 | unsigned long zone, int nid, bool zero) | 1146 | unsigned long zone, int nid) |
1147 | { | 1147 | { |
1148 | if (zero) | 1148 | mm_zero_struct_page(page); |
1149 | mm_zero_struct_page(page); | ||
1150 | set_page_links(page, zone, nid, pfn); | 1149 | set_page_links(page, zone, nid, pfn); |
1151 | init_page_count(page); | 1150 | init_page_count(page); |
1152 | page_mapcount_reset(page); | 1151 | page_mapcount_reset(page); |
@@ -1160,12 +1159,6 @@ static void __meminit __init_single_page(struct page *page, unsigned long pfn, | |||
1160 | #endif | 1159 | #endif |
1161 | } | 1160 | } |
1162 | 1161 | ||
1163 | static void __meminit __init_single_pfn(unsigned long pfn, unsigned long zone, | ||
1164 | int nid, bool zero) | ||
1165 | { | ||
1166 | return __init_single_page(pfn_to_page(pfn), pfn, zone, nid, zero); | ||
1167 | } | ||
1168 | |||
1169 | #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT | 1162 | #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT |
1170 | static void __meminit init_reserved_page(unsigned long pfn) | 1163 | static void __meminit init_reserved_page(unsigned long pfn) |
1171 | { | 1164 | { |
@@ -1184,7 +1177,7 @@ static void __meminit init_reserved_page(unsigned long pfn) | |||
1184 | if (pfn >= zone->zone_start_pfn && pfn < zone_end_pfn(zone)) | 1177 | if (pfn >= zone->zone_start_pfn && pfn < zone_end_pfn(zone)) |
1185 | break; | 1178 | break; |
1186 | } | 1179 | } |
1187 | __init_single_pfn(pfn, zid, nid, true); | 1180 | __init_single_page(pfn_to_page(pfn), pfn, zid, nid); |
1188 | } | 1181 | } |
1189 | #else | 1182 | #else |
1190 | static inline void init_reserved_page(unsigned long pfn) | 1183 | static inline void init_reserved_page(unsigned long pfn) |
@@ -1501,7 +1494,7 @@ static unsigned long __init deferred_init_pages(int nid, int zid, | |||
1501 | } else { | 1494 | } else { |
1502 | page++; | 1495 | page++; |
1503 | } | 1496 | } |
1504 | __init_single_page(page, pfn, zid, nid, true); | 1497 | __init_single_page(page, pfn, zid, nid); |
1505 | nr_pages++; | 1498 | nr_pages++; |
1506 | } | 1499 | } |
1507 | return (nr_pages); | 1500 | return (nr_pages); |
@@ -5434,6 +5427,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
5434 | pg_data_t *pgdat = NODE_DATA(nid); | 5427 | pg_data_t *pgdat = NODE_DATA(nid); |
5435 | unsigned long pfn; | 5428 | unsigned long pfn; |
5436 | unsigned long nr_initialised = 0; | 5429 | unsigned long nr_initialised = 0; |
5430 | struct page *page; | ||
5437 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP | 5431 | #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP |
5438 | struct memblock_region *r = NULL, *tmp; | 5432 | struct memblock_region *r = NULL, *tmp; |
5439 | #endif | 5433 | #endif |
@@ -5486,6 +5480,11 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
5486 | #endif | 5480 | #endif |
5487 | 5481 | ||
5488 | not_early: | 5482 | not_early: |
5483 | page = pfn_to_page(pfn); | ||
5484 | __init_single_page(page, pfn, zone, nid); | ||
5485 | if (context == MEMMAP_HOTPLUG) | ||
5486 | SetPageReserved(page); | ||
5487 | |||
5489 | /* | 5488 | /* |
5490 | * Mark the block movable so that blocks are reserved for | 5489 | * Mark the block movable so that blocks are reserved for |
5491 | * movable at startup. This will force kernel allocations | 5490 | * movable at startup. This will force kernel allocations |
@@ -5502,15 +5501,8 @@ not_early: | |||
5502 | * because this is done early in sparse_add_one_section | 5501 | * because this is done early in sparse_add_one_section |
5503 | */ | 5502 | */ |
5504 | if (!(pfn & (pageblock_nr_pages - 1))) { | 5503 | if (!(pfn & (pageblock_nr_pages - 1))) { |
5505 | struct page *page = pfn_to_page(pfn); | ||
5506 | |||
5507 | __init_single_page(page, pfn, zone, nid, | ||
5508 | context != MEMMAP_HOTPLUG); | ||
5509 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); | 5504 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); |
5510 | cond_resched(); | 5505 | cond_resched(); |
5511 | } else { | ||
5512 | __init_single_pfn(pfn, zone, nid, | ||
5513 | context != MEMMAP_HOTPLUG); | ||
5514 | } | 5506 | } |
5515 | } | 5507 | } |
5516 | } | 5508 | } |
diff --git a/mm/sparse.c b/mm/sparse.c index 58cab483e81b..62eef264a7bd 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -779,7 +779,13 @@ int __meminit sparse_add_one_section(struct pglist_data *pgdat, | |||
779 | goto out; | 779 | goto out; |
780 | } | 780 | } |
781 | 781 | ||
782 | memset(memmap, 0, sizeof(struct page) * PAGES_PER_SECTION); | 782 | #ifdef CONFIG_DEBUG_VM |
783 | /* | ||
784 | * Poison uninitialized struct pages in order to catch invalid flags | ||
785 | * combinations. | ||
786 | */ | ||
787 | memset(memmap, PAGE_POISON_PATTERN, sizeof(struct page) * PAGES_PER_SECTION); | ||
788 | #endif | ||
783 | 789 | ||
784 | section_mark_present(ms); | 790 | section_mark_present(ms); |
785 | 791 | ||