linux-stable/drivers/base
Laurent Dufour f85086f95f mm: don't rely on system state to detect hot-plug operations
In register_mem_sect_under_node() the system_state's value is checked to
detect whether the call is made during boot time or during an hot-plug
operation.  Unfortunately, that check against SYSTEM_BOOTING is wrong
because regular memory is registered at SYSTEM_SCHEDULING state.  In
addition, memory hot-plug operation can be triggered at this system
state by the ACPI [1].  So checking against the system state is not
enough.

The consequence is that on system with interleaved node's ranges like this:

 Early memory node ranges
   node   1: [mem 0x0000000000000000-0x000000011fffffff]
   node   2: [mem 0x0000000120000000-0x000000014fffffff]
   node   1: [mem 0x0000000150000000-0x00000001ffffffff]
   node   0: [mem 0x0000000200000000-0x000000048fffffff]
   node   2: [mem 0x0000000490000000-0x00000007ffffffff]

This can be seen on PowerPC LPAR after multiple memory hot-plug and
hot-unplug operations are done.  At the next reboot the node's memory
ranges can be interleaved and since the call to link_mem_sections() is
made in topology_init() while the system is in the SYSTEM_SCHEDULING
state, the node's id is not checked, and the sections registered to
multiple nodes:

  $ ls -l /sys/devices/system/memory/memory21/node*
  total 0
  lrwxrwxrwx 1 root root     0 Aug 24 05:27 node1 -> ../../node/node1
  lrwxrwxrwx 1 root root     0 Aug 24 05:27 node2 -> ../../node/node2

In that case, the system is able to boot but if later one of theses
memory blocks is hot-unplugged and then hot-plugged, the sysfs
inconsistency is detected and this is triggering a BUG_ON():

  kernel BUG at /Users/laurent/src/linux-ppc/mm/memory_hotplug.c:1084!
  Oops: Exception in kernel mode, sig: 5 [#1]
  LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries
  Modules linked in: rpadlpar_io rpaphp pseries_rng rng_core vmx_crypto gf128mul binfmt_misc ip_tables x_tables xfs libcrc32c crc32c_vpmsum autofs4
  CPU: 8 PID: 10256 Comm: drmgr Not tainted 5.9.0-rc1+ #25
  Call Trace:
    add_memory_resource+0x23c/0x340 (unreliable)
    __add_memory+0x5c/0xf0
    dlpar_add_lmb+0x1b4/0x500
    dlpar_memory+0x1f8/0xb80
    handle_dlpar_errorlog+0xc0/0x190
    dlpar_store+0x198/0x4a0
    kobj_attr_store+0x30/0x50
    sysfs_kf_write+0x64/0x90
    kernfs_fop_write+0x1b0/0x290
    vfs_write+0xe8/0x290
    ksys_write+0xdc/0x130
    system_call_exception+0x160/0x270
    system_call_common+0xf0/0x27c

This patch addresses the root cause by not relying on the system_state
value to detect whether the call is due to a hot-plug operation.  An
extra parameter is added to link_mem_sections() detailing whether the
operation is due to a hot-plug operation.

[1] According to Oscar Salvador, using this qemu command line, ACPI
memory hotplug operations are raised at SYSTEM_SCHEDULING state:

  $QEMU -enable-kvm -machine pc -smp 4,sockets=4,cores=1,threads=1 -cpu host -monitor pty \
        -m size=$MEM,slots=255,maxmem=4294967296k  \
        -numa node,nodeid=0,cpus=0-3,mem=512 -numa node,nodeid=1,mem=512 \
        -object memory-backend-ram,id=memdimm0,size=134217728 -device pc-dimm,node=0,memdev=memdimm0,id=dimm0,slot=0 \
        -object memory-backend-ram,id=memdimm1,size=134217728 -device pc-dimm,node=0,memdev=memdimm1,id=dimm1,slot=1 \
        -object memory-backend-ram,id=memdimm2,size=134217728 -device pc-dimm,node=0,memdev=memdimm2,id=dimm2,slot=2 \
        -object memory-backend-ram,id=memdimm3,size=134217728 -device pc-dimm,node=0,memdev=memdimm3,id=dimm3,slot=3 \
        -object memory-backend-ram,id=memdimm4,size=134217728 -device pc-dimm,node=1,memdev=memdimm4,id=dimm4,slot=4 \
        -object memory-backend-ram,id=memdimm5,size=134217728 -device pc-dimm,node=1,memdev=memdimm5,id=dimm5,slot=5 \
        -object memory-backend-ram,id=memdimm6,size=134217728 -device pc-dimm,node=1,memdev=memdimm6,id=dimm6,slot=6 \

Fixes: 4fbce63391 ("mm/memory_hotplug.c: make register_mem_sect_under_node() a callback of walk_memory_range()")
Signed-off-by: Laurent Dufour <ldufour@linux.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Oscar Salvador <osalvador@suse.de>
Acked-by: Michal Hocko <mhocko@suse.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: Scott Cheloha <cheloha@linux.ibm.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: <stable@vger.kernel.org>
Link: https://lkml.kernel.org/r/20200915094143.79181-3-ldufour@linux.ibm.com
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-09-26 10:33:57 -07:00
..
firmware_loader Driver core fixes for 5.9-rc5 2020-09-13 09:02:59 -07:00
power PM: sleep: core: Fix the handling of pending runtime resume requests 2020-08-25 16:28:23 +02:00
regmap regmap: fix page selection for noinc writes 2020-09-21 20:58:02 +01:00
test drivers: base: default KUNIT_* fragments to KUNIT_ALL_TESTS 2020-06-01 14:24:25 -06:00
arch_topology.c arch_topology, sched/core: Cleanup thermal pressure definition 2020-07-22 10:22:05 +02:00
attribute_container.c scsi: drivers: base: Support atomic version of attribute_container_device_trigger 2020-01-15 22:55:36 -05:00
base.h driver core: add deferring probe reason to devices_deferred property 2020-07-30 09:03:43 +02:00
bus.c device.h: move 'struct bus' stuff out to device/bus.h 2019-12-16 10:11:12 +01:00
cacheinfo.c Driver Core and debugfs changes for 5.3-rc1 2019-07-12 12:24:03 -07:00
class.c device.h: move 'struct class' stuff out to device/class.h 2019-12-16 10:11:14 +01:00
component.c component: Silence bind error on -EPROBE_DEFER 2020-04-28 17:54:15 +02:00
container.c
core.c Driver core fixes for 5.9-rc5 2020-09-13 09:02:59 -07:00
cpu.c x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation 2020-04-20 12:19:22 +02:00
dd.c driver core: add deferring probe reason to devices_deferred property 2020-07-30 09:03:43 +02:00
devcon.c Merge generic_lookup_helpers into usb-next 2019-09-03 17:11:07 +02:00
devcoredump.c devcoredump: fix typo in comment 2019-08-15 17:38:11 +02:00
devres.c devres: handle zero size in devm_kmalloc() 2020-07-02 14:36:02 +02:00
devtmpfs.c init: add an init_chroot helper 2020-07-31 08:17:52 +02:00
driver.c drivers: base: Convert to printk alias functions 2020-07-10 14:16:44 +02:00
firmware.c
hypervisor.c
init.c base: fix order of OF initialization 2018-07-07 17:54:29 +02:00
isa.c
Kconfig drivers: base: default KUNIT_* fragments to KUNIT_ALL_TESTS 2020-06-01 14:24:25 -06:00
Makefile drivers: base: Introducing software nodes to the firmware node framework 2018-11-26 18:19:11 +01:00
map.c
memory.c drivers/base/memory: rename base_memory_block_id to memory_block_id 2020-07-10 14:38:44 +02:00
module.c
node.c mm: don't rely on system state to detect hot-plug operations 2020-09-26 10:33:57 -07:00
pinctrl.c
platform-msi.c platform-msi: Fix typos in comment 2020-05-18 10:28:30 +01:00
platform.c driver core: platform: expose numa_node to users in sysfs 2020-07-10 14:14:37 +02:00
property.c device property: Avoid NULL pointer dereference in device_get_next_child_node() 2020-07-23 17:04:28 +02:00
soc.c driver/base/soc: Use kobj_to_dev() API 2020-04-28 21:05:42 +02:00
swnode.c software node: Use software_node_unregister() when unregistering group of nodes 2020-07-10 14:35:37 +02:00
syscore.c treewide: Switch printk users from %pf and %pF to %ps and %pS, respectively 2019-04-09 14:19:06 +02:00
topology.c topology: mark a function as __init to save some memory 2020-07-10 14:35:37 +02:00
transport_class.c scsi: drivers: base: Propagate errors through the transport component 2020-01-15 22:55:37 -05:00