Commit 07b4e2bc authored by Yinghai Lu's avatar Yinghai Lu Committed by Linus Torvalds

mm: sparse: fix section usemap placement calculation

Commit 238305bb ("mm: remove sparsemem allocation details from the
bootmem allocator") introduced a bug in the allocation goal calculation
that put section usemaps not in the same section as the node
descriptors, creating unnecessary hotplug dependencies between them:

  node 0 must be removed before remove section 16399
  node 1 must be removed before remove section 16399
  node 2 must be removed before remove section 16399
  node 3 must be removed before remove section 16399
  node 4 must be removed before remove section 16399
  node 5 must be removed before remove section 16399
  node 6 must be removed before remove section 16399

The reason is that it applies PAGE_SECTION_MASK to the physical address
of the node descriptor when finding a suitable place to put the usemap,
when this mask is actually intended to be used with PFNs.  Because the
PFN mask is wider, the target address will point beyond the wanted
section holding the node descriptor and the node must be offlined before
the section holding the usemap can go.

Fix this by extending the mask to address width before use.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 688bb415
...@@ -287,7 +287,7 @@ sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat, ...@@ -287,7 +287,7 @@ sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat,
* from the same section as the pgdat where possible to avoid * from the same section as the pgdat where possible to avoid
* this problem. * this problem.
*/ */
goal = __pa(pgdat) & PAGE_SECTION_MASK; goal = __pa(pgdat) & (PAGE_SECTION_MASK << PAGE_SHIFT);
host_pgdat = NODE_DATA(early_pfn_to_nid(goal >> PAGE_SHIFT)); host_pgdat = NODE_DATA(early_pfn_to_nid(goal >> PAGE_SHIFT));
return __alloc_bootmem_node_nopanic(host_pgdat, size, return __alloc_bootmem_node_nopanic(host_pgdat, size,
SMP_CACHE_BYTES, goal); SMP_CACHE_BYTES, goal);
......
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