Skip to content

Commit

Permalink
mm/memory_hotplug: don't read nid from struct page during hotplug
Browse files Browse the repository at this point in the history
During memory hotplugging the probe routine will leave struct pages
uninitialized, the same as it is currently done during boot.  Therefore,
we do not want to access the inside of struct pages before
__init_single_page() is called during onlining.

Because during hotplug we know that pages in one memory block belong to
the same numa node, we can skip the checking.  We should keep checking
for the boot case.

[[email protected]: s/register_new_memory()/hotplug_memory_register()]
  Link: http://lkml.kernel.org/r/[email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Pavel Tatashin <[email protected]>
Acked-by: Michal Hocko <[email protected]>
Reviewed-by: Ingo Molnar <[email protected]>
Cc: Baoquan He <[email protected]>
Cc: Bharata B Rao <[email protected]>
Cc: Daniel Jordan <[email protected]>
Cc: Dan Williams <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: "H. Peter Anvin" <[email protected]>
Cc: Kirill A. Shutemov <[email protected]>
Cc: Mel Gorman <[email protected]>
Cc: Steven Sistare <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Pavel Tatashin authored and torvalds committed Apr 6, 2018
1 parent b77eab7 commit fc44f7f
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 13 deletions.
4 changes: 2 additions & 2 deletions drivers/base/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ static int add_memory_block(int base_section_nr)
* need an interface for the VM to add new memory regions,
* but without onlining it.
*/
int register_new_memory(int nid, struct mem_section *section)
int hotplug_memory_register(int nid, struct mem_section *section)
{
int ret = 0;
struct memory_block *mem;
Expand All @@ -731,7 +731,7 @@ int register_new_memory(int nid, struct mem_section *section)
}

if (mem->section_count == sections_per_block)
ret = register_mem_sect_under_node(mem, nid);
ret = register_mem_sect_under_node(mem, nid, false);
out:
mutex_unlock(&mem_sysfs_mutex);
return ret;
Expand Down
22 changes: 15 additions & 7 deletions drivers/base/node.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,8 @@ static int __ref get_nid_for_pfn(unsigned long pfn)
}

/* register memory section under specified node if it spans that node */
int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
int register_mem_sect_under_node(struct memory_block *mem_blk, int nid,
bool check_nid)
{
int ret;
unsigned long pfn, sect_start_pfn, sect_end_pfn;
Expand All @@ -425,11 +426,18 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
continue;
}

page_nid = get_nid_for_pfn(pfn);
if (page_nid < 0)
continue;
if (page_nid != nid)
continue;
/*
* We need to check if page belongs to nid only for the boot
* case, during hotplug we know that all pages in the memory
* block belong to the same node.
*/
if (check_nid) {
page_nid = get_nid_for_pfn(pfn);
if (page_nid < 0)
continue;
if (page_nid != nid)
continue;
}
ret = sysfs_create_link_nowarn(&node_devices[nid]->dev.kobj,
&mem_blk->dev.kobj,
kobject_name(&mem_blk->dev.kobj));
Expand Down Expand Up @@ -504,7 +512,7 @@ int link_mem_sections(int nid, unsigned long start_pfn, unsigned long nr_pages)

mem_blk = find_memory_block_hinted(mem_sect, mem_blk);

ret = register_mem_sect_under_node(mem_blk, nid);
ret = register_mem_sect_under_node(mem_blk, nid, true);
if (!err)
err = ret;

Expand Down
2 changes: 1 addition & 1 deletion include/linux/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ extern int register_memory_notifier(struct notifier_block *nb);
extern void unregister_memory_notifier(struct notifier_block *nb);
extern int register_memory_isolate_notifier(struct notifier_block *nb);
extern void unregister_memory_isolate_notifier(struct notifier_block *nb);
extern int register_new_memory(int, struct mem_section *);
int hotplug_memory_register(int nid, struct mem_section *section);
#ifdef CONFIG_MEMORY_HOTREMOVE
extern int unregister_memory_section(struct mem_section *);
#endif
Expand Down
4 changes: 2 additions & 2 deletions include/linux/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ extern void unregister_one_node(int nid);
extern int register_cpu_under_node(unsigned int cpu, unsigned int nid);
extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
extern int register_mem_sect_under_node(struct memory_block *mem_blk,
int nid);
int nid, bool check_nid);
extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
unsigned long phys_index);

Expand Down Expand Up @@ -97,7 +97,7 @@ static inline int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
return 0;
}
static inline int register_mem_sect_under_node(struct memory_block *mem_blk,
int nid)
int nid, bool check_nid)
{
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion mm/memory_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ static int __meminit __add_section(int nid, unsigned long phys_start_pfn,
if (!want_memblock)
return 0;

return register_new_memory(nid, __pfn_to_section(phys_start_pfn));
return hotplug_memory_register(nid, __pfn_to_section(phys_start_pfn));
}

/*
Expand Down

0 comments on commit fc44f7f

Please sign in to comment.