Commit 8df1d0e4 authored by David Hildenbrand's avatar David Hildenbrand Committed by Linus Torvalds
Browse files

mm/memory_hotplug: make add_memory() take the device_hotplug_lock

add_memory() currently does not take the device_hotplug_lock, however
is aleady called under the lock from
to synchronize against CPU hot-remove and similar.

In general, we should hold the device_hotplug_lock when adding memory to
synchronize against online/offline request (e.g.  from user space) - which
already resulted in lock inversions due to device_lock() and
mem_hotplug_lock - see 30467e0b ("mm, hotplug: fix concurrent memory
hot-add deadlock").  add_memory()/add_memory_resource() will create memory
block devices, so this really feels like the right thing to do.

Holding the device_hotplug_lock makes sure that a memory block device
can really only be accessed (e.g. via .online/.state) from user space,
once the memory has been fully added to the system.

The lock is not held yet in
So, let's either use the locked variants or take the lock.

Don't export add_memory_resource(), as it once was exported to be used by
XEN, which is never built as a module.  If somebody requires it, we also
have to export a locked variant (as device_hotplug_lock is never


Signed-off-by: default avatarDavid Hildenbrand <>
Reviewed-by: default avatarPavel Tatashin <>
Reviewed-by: default avatarRafael J. Wysocki <>
Reviewed-by: default avatarRashmica Gupta <>
Reviewed-by: default avatarOscar Salvador <>
Cc: Benjamin Herrenschmidt <>
Cc: Paul Mackerras <>
Cc: Michael Ellerman <>
Cc: "Rafael J. Wysocki" <>
Cc: Len Brown <>
Cc: Greg Kroah-Hartman <>
Cc: Boris Ostrovsky <>
Cc: Juergen Gross <>
Cc: Nathan Fontenot <>
Cc: John Allen <>
Cc: Michal Hocko <>
Cc: Dan Williams <>
Cc: Joonsoo Kim <>
Cc: Vlastimil Babka <>
Cc: Mathieu Malaterre <>
Cc: Pavel Tatashin <>
Cc: Balbir Singh <>
Cc: Haiyang Zhang <>
Cc: Heiko Carstens <>
Cc: Jonathan Corbet <>
Cc: Kate Stewart <>
Cc: "K. Y. Srinivasan" <>
Cc: Martin Schwidefsky <>
Cc: Michael Neuling <>
Cc: Philippe Ombredanne <>
Cc: Stephen Hemminger <>
Cc: Thomas Gleixner <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent d15e5926
......@@ -668,7 +668,7 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
nid = memory_add_physaddr_to_nid(lmb->base_addr);
/* Add the memory */
rc = add_memory(nid, lmb->base_addr, block_sz);
rc = __add_memory(nid, lmb->base_addr, block_sz);
if (rc) {
return rc;
......@@ -228,7 +228,7 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
if (node < 0)
node = memory_add_physaddr_to_nid(info->start_addr);
result = add_memory(node, info->start_addr, info->length);
result = __add_memory(node, info->start_addr, info->length);
* If the memory block has been used by the kernel, add_memory()
......@@ -519,15 +519,20 @@ memory_probe_store(struct device *dev, struct device_attribute *attr,
if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
return -EINVAL;
ret = lock_device_hotplug_sysfs();
if (ret)
goto out;
nid = memory_add_physaddr_to_nid(phys_addr);
ret = add_memory(nid, phys_addr,
MIN_MEMORY_BLOCK_SIZE * sections_per_block);
ret = __add_memory(nid, phys_addr,
MIN_MEMORY_BLOCK_SIZE * sections_per_block);
if (ret)
goto out;
ret = count;
return ret;
......@@ -395,7 +395,10 @@ static enum bp_state reserve_additional_memory(void)
* callers drop the mutex before trying again.
/* add_memory_resource() requires the device_hotplug lock */
rc = add_memory_resource(nid, resource, memhp_auto_online);
if (rc) {
......@@ -324,6 +324,7 @@ static inline void __remove_memory(int nid, u64 start, u64 size) {}
extern void __ref free_area_init_core_hotplug(int nid);
extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
void *arg, int (*func)(struct memory_block *, void *));
extern int __add_memory(int nid, u64 start, u64 size);
extern int add_memory(int nid, u64 start, u64 size);
extern int add_memory_resource(int nid, struct resource *resource, bool online);
extern int arch_add_memory(int nid, u64 start, u64 size,
......@@ -1068,7 +1068,12 @@ static int online_memory_block(struct memory_block *mem, void *arg)
return device_online(&mem->dev);
/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
* NOTE: The caller must call lock_device_hotplug() to serialize hotplug
* and online/offline operations (triggered e.g. by sysfs).
* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG
int __ref add_memory_resource(int nid, struct resource *res, bool online)
u64 start, size;
......@@ -1137,9 +1142,9 @@ int __ref add_memory_resource(int nid, struct resource *res, bool online)
return ret;
int __ref add_memory(int nid, u64 start, u64 size)
/* requires device_hotplug_lock, see add_memory_resource() */
int __ref __add_memory(int nid, u64 start, u64 size)
struct resource *res;
int ret;
......@@ -1153,6 +1158,17 @@ int __ref add_memory(int nid, u64 start, u64 size)
return ret;
int add_memory(int nid, u64 start, u64 size)
int rc;
rc = __add_memory(nid, start, size);
return rc;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment