Skip to content

Commit 9b99c17

Browse files
AlisonSchofielddjbw
authored andcommitted
x86/numa: Fix the address overlap check in numa_fill_memblks()
numa_fill_memblks() fills in the gaps in numa_meminfo memblks over a physical address range. To do so, it first creates a list of existing memblks that overlap that address range. The issue is that it is off by one when comparing to the end of the address range, so memblks that do not overlap are selected. The impact of selecting a memblk that does not actually overlap is that an existing memblk may be filled when the expected action is to do nothing and return NUMA_NO_MEMBLK to the caller. The caller can then add a new NUMA node and memblk. Replace the broken open-coded search for address overlap with the memblock helper memblock_addrs_overlap(). Update the kernel doc and in code comments. Suggested by: "Huang, Ying" <[email protected]> Fixes: 8f012db ("x86/numa: Introduce numa_fill_memblks()") Signed-off-by: Alison Schofield <[email protected]> Acked-by: Mike Rapoport (IBM) <[email protected]> Acked-by: Dave Hansen <[email protected]> Reviewed-by: Dan Williams <[email protected]> Link: https://lore.kernel.org/r/10a3e6109c34c21a8dd4c513cf63df63481a2b07.1705085543.git.alison.schofield@intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent eef5c7b commit 9b99c17

File tree

3 files changed

+12
-14
lines changed

3 files changed

+12
-14
lines changed

arch/x86/mm/numa.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -944,14 +944,12 @@ static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata;
944944
* @start: address to begin fill
945945
* @end: address to end fill
946946
*
947-
* Find and extend numa_meminfo memblks to cover the @start-@end
948-
* physical address range, such that the first memblk includes
949-
* @start, the last memblk includes @end, and any gaps in between
950-
* are filled.
947+
* Find and extend numa_meminfo memblks to cover the physical
948+
* address range @start-@end
951949
*
952950
* RETURNS:
953951
* 0 : Success
954-
* NUMA_NO_MEMBLK : No memblk exists in @start-@end range
952+
* NUMA_NO_MEMBLK : No memblks exist in address range @start-@end
955953
*/
956954

957955
int __init numa_fill_memblks(u64 start, u64 end)
@@ -963,17 +961,14 @@ int __init numa_fill_memblks(u64 start, u64 end)
963961

964962
/*
965963
* Create a list of pointers to numa_meminfo memblks that
966-
* overlap start, end. Exclude (start == bi->end) since
967-
* end addresses in both a CFMWS range and a memblk range
968-
* are exclusive.
969-
*
970-
* This list of pointers is used to make in-place changes
971-
* that fill out the numa_meminfo memblks.
964+
* overlap start, end. The list is used to make in-place
965+
* changes that fill out the numa_meminfo memblks.
972966
*/
973967
for (int i = 0; i < mi->nr_blks; i++) {
974968
struct numa_memblk *bi = &mi->blk[i];
975969

976-
if (start < bi->end && end >= bi->start) {
970+
if (memblock_addrs_overlap(start, end - start, bi->start,
971+
bi->end - bi->start)) {
977972
blk[count] = &mi->blk[i];
978973
count++;
979974
}

include/linux/memblock.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size);
121121
int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
122122
#endif
123123
void memblock_trim_memory(phys_addr_t align);
124+
unsigned long memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
125+
phys_addr_t base2, phys_addr_t size2);
124126
bool memblock_overlaps_region(struct memblock_type *type,
125127
phys_addr_t base, phys_addr_t size);
126128
bool memblock_validate_numa_coverage(unsigned long threshold_bytes);

mm/memblock.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,9 @@ static inline phys_addr_t memblock_cap_size(phys_addr_t base, phys_addr_t *size)
180180
/*
181181
* Address comparison utilities
182182
*/
183-
static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
184-
phys_addr_t base2, phys_addr_t size2)
183+
unsigned long __init_memblock
184+
memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, phys_addr_t base2,
185+
phys_addr_t size2)
185186
{
186187
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
187188
}

0 commit comments

Comments
 (0)