]> git.hungrycats.org Git - linux/commitdiff
drivers/base/memory.c: fix kernel warning during memory hotplug on ppc64
authorJohn Allen <jallen@linux.vnet.ibm.com>
Thu, 14 Jan 2016 23:22:16 +0000 (15:22 -0800)
committerJiri Slaby <jslaby@suse.cz>
Mon, 11 Apr 2016 14:43:50 +0000 (16:43 +0200)
commit cb5490a5eea415106d7438df440da5fb1e17318d upstream.

Fix a bug where a kernel warning is triggered when performing a memory
hotplug on ppc64.  This warning may also occur on any architecture that
uses the memory_probe_store interface.

  WARNING: at drivers/base/memory.c:200
  CPU: 9 PID: 13042 Comm: systemd-udevd Not tainted 4.4.0-rc4-00113-g0bd0f1e-dirty #7
  NIP [c00000000055e034] pages_correctly_reserved+0x134/0x1b0
  LR [c00000000055e7f8] memory_subsys_online+0x68/0x140
  Call Trace:
    memory_subsys_online+0x68/0x140
    device_online+0xb4/0x120
    store_mem_state+0xb0/0x180
    dev_attr_store+0x34/0x60
    sysfs_kf_write+0x64/0xa0
    kernfs_fop_write+0x17c/0x1e0
    __vfs_write+0x40/0x160
    vfs_write+0xb8/0x200
    SyS_write+0x60/0x110
    system_call+0x38/0xd0

The warning is triggered because there is a udev rule that automatically
tries to online memory after it has been added.  The udev rule varies
from distro to distro, but will generally look something like:

  SUBSYSTEM=="memory", ACTION=="add", ATTR{state}=="offline", ATTR{state}="online"

On any architecture that uses memory_probe_store to reserve memory, the
udev rule will be triggered after the first section of the block is
reserved and will subsequently attempt to online the entire block,
interrupting the memory reservation process and causing the warning.
This patch modifies memory_probe_store to add a block of memory with a
single call to add_memory as opposed to looping through and adding each
section individually.  A single call to add_memory is protected by the
mem_hotplug mutex which will prevent the udev rule from onlining memory
until the reservation of the entire block is complete.

Signed-off-by: John Allen <jallen@linux.vnet.ibm.com>
Acked-by: Dave Hansen <dave.hansen@intel.com>
Cc: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
drivers/base/memory.c

index 3e2a3059b1f8dee76191ef0721a7ebe9964b94ed..3c2b7174eb6f4b2657aa80bcf4dfa38b1b7d7945 100644 (file)
@@ -417,8 +417,7 @@ memory_probe_store(struct device *dev, struct device_attribute *attr,
                   const char *buf, size_t count)
 {
        u64 phys_addr;
-       int nid;
-       int i, ret;
+       int nid, ret;
        unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
 
        phys_addr = simple_strtoull(buf, NULL, 0);
@@ -426,15 +425,12 @@ memory_probe_store(struct device *dev, struct device_attribute *attr,
        if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
                return -EINVAL;
 
-       for (i = 0; i < sections_per_block; i++) {
-               nid = memory_add_physaddr_to_nid(phys_addr);
-               ret = add_memory(nid, phys_addr,
-                                PAGES_PER_SECTION << PAGE_SHIFT);
-               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);
 
-               phys_addr += MIN_MEMORY_BLOCK_SIZE;
-       }
+       if (ret)
+               goto out;
 
        ret = count;
 out: