mm/hotplug: reorder memblock_[free|remove]() calls in try_remove_memory()
authorAnshuman Khandual <anshuman.khandual@arm.com>
Sun, 1 Dec 2019 01:53:44 +0000 (17:53 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 1 Dec 2019 20:59:04 +0000 (12:59 -0800)
Currently during memory hot add procedure, memory gets into memblock
before calling arch_add_memory() which creates its linear mapping.

  add_memory_resource() {
..................
memblock_add_node()
..................
arch_add_memory()
..................
  }

But during memory hot remove procedure, removal from memblock happens
first before its linear mapping gets teared down with
arch_remove_memory() which is not consistent.  Resource removal should
happen in reverse order as they were added.  However this does not pose
any problem for now, unless there is an assumption regarding linear
mapping.  One example was a subtle failure on arm64 platform [1].
Though this has now found a different solution.

  try_remove_memory() {
..................
memblock_free()
memblock_remove()
..................
arch_remove_memory()
..................
  }

This changes the sequence of resource removal including memblock and
linear mapping tear down during memory hot remove which will now be the
reverse order in which they were added during memory hot add.  The
changed removal order looks like the following.

  try_remove_memory() {
..................
arch_remove_memory()
..................
memblock_free()
memblock_remove()
..................
  }

[1] https://patchwork.kernel.org/patch/11127623/

Memory hot remove now works on arm64 without this because a recent
commit 60bb462fc7ad ("drivers/base/node.c: simplify
unregister_memory_block_under_nodes()").

This does not fix a serious problem.  It just removes an inconsistency
while freeing resources during memory hot remove which for now does not
pose a real problem.

David mentioned that re-ordering should still make sense for consistency
purpose (removing stuff in the reverse order they were added).  This
patch is now detached from arm64 hot-remove series.

Michal:

: I would just a note that the inconsistency doesn't pose any problem now
: but if somebody makes any assumptions about linear mappings then it could
: get subtly broken like your example for arm64 which has found a different
: solution in the meantime.

Link: http://lkml.kernel.org/r/1569380273-7708-1-git-send-email-anshuman.khandual@arm.com
Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Acked-by: Michal Hocko <mhocko@suse.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
mm/memory_hotplug.c

index f307bd82d750542b27a4e01cfeadfda32b2b5d02..1b1ad398dff84471087101d1f486da4df19534ac 100644 (file)
@@ -1750,13 +1750,13 @@ static int __ref try_remove_memory(int nid, u64 start, u64 size)
 
        /* remove memmap entry */
        firmware_map_remove(start, start + size, "System RAM");
-       memblock_free(start, size);
-       memblock_remove(start, size);
 
        /* remove memory block devices before removing memory */
        remove_memory_block_devices(start, size);
 
        arch_remove_memory(nid, start, size, NULL);
+       memblock_free(start, size);
+       memblock_remove(start, size);
        __release_memory_resource(start, size);
 
        try_offline_node(nid);