lmb: add lmb_alloc_nid()
[email protected]
maintainerPATCH 6/24 lmb: add lmb_alloc_nid()
From: David Miller <[email protected]>
A variant of lmb_alloc() that tries to allocate memory on a specified NUMA node 'nid' but falls back to normal lmb_alloc() if that fails.
The caller provides a 'nid_range' function pointer which assists the allocator. It is given args 'start', 'end', and pointer to integer 'this_nid'.
It places at 'this_nid' the NUMA node id that corresponds to 'start', and returns the end address within 'start' to 'end' at which memory assosciated with 'nid' ends.
This callback allows a platform to use lmb_alloc_nid() in just about any context, even ones in which early_pfn_to_nid() might not be working yet.
This function will be used by the NUMA setup code on sparc64, and also it can be used by powerpc, replacing it's hand crafted "careful_allocation()" function in arch/powerpc/mm/numa.c
If x86 ever converts its NUMA support over to using the LMB helpers, it can use this too as it has something entirely similar.
---
include/linux/lmb.h | 2 lib/lmb.c | 86 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 78 insertions(+), 10 deletions(-)
include/linux/lmb.h renamed from include/linux/lmb.h~lmb-add-lmb_alloc_nid +2 -0
@@ -42,6 +42,8 @@ extern void __init lmb_init(void);extern void __init lmb_analyze (void );extern long __init lmb_add (u64 base,u64 size);extern long __init lmb_reserve (u64 base,u64 size); +extern u64 __init lmb_alloc_nid (u64 size,u64 align,int nid, +u64 (*nid_range)(u64 ,u64 ,int *));extern u64 __init lmb_alloc (u64 size,u64 align);extern u64 __init lmb_alloc_base (u64 size,u64 ,u64 max_addr);
lib/lmb.c renamed from lib/lmb.c~lmb-add-lmb_alloc_nid +76 -10
98 lines not on this page · raw message
_
Quoted 4 lines · [email protected] writes:
From: David Miller <[email protected]>
A variant of
lmb_alloc()that tries to allocate memory on a specified NUMA node 'nid' but falls back to normallmb_alloc()if that fails.
...
lib/lmb.c long __init lmb_overlaps_region(struct l · line 255
Quoted 11 lines
lib/lmb.c renamed from lib/lmb.c~lmb-add-lmb_alloc_nid +11
-0+static u64 __init lmb_alloc_nid_unreserved (u64 start,u64 end, +u64 size,u64 align) +{ +u64 base; +long j; + + base =lmb_align_down ((end - size), align); +while (start <= base && + ((j =lmb_overlaps_region (&lmb.reserved, base, size)) >=0 )) + base =lmb_align_down (lmb.reserved.region[j].base - size, + align);
How do we know that lmb.reserved.region[j].base is >= size at this point? If it isn't, then base could end up as some extremely large unsigned value, which would be a Bad Thing.
Paul.
From: Paul Mackerras <[email protected]>
Date: Tue, 1 Apr 2008 15:15:46 +1100
Quoted 9 lines
Quoted 4 lines · [email protected] writes:
From: David Miller <[email protected]>
A variant of
lmb_alloc()that tries to allocate memory on a specified NUMA node 'nid' but falls back to normallmb_alloc()if that fails....
Quoted 15 lines
lib/lmb.c long __init lmb_overlaps_region(struct l · line 255
Quoted 11 lines
lib/lmb.c renamed from lib/lmb.c~lmb-add-lmb_alloc_nid +11
-0+static u64 __init lmb_alloc_nid_unreserved (u64 start,u64 end, +u64 size,u64 align) +{ +u64 base; +long j; + + base =lmb_align_down ((end - size), align); +while (start <= base && + ((j =lmb_overlaps_region (&lmb.reserved, base, size)) >=0 )) + base =lmb_align_down (lmb.reserved.region[j].base - size, + align);How do we know that lmb.reserved.region[j].base is >= size at this point? If it isn't, then base could end up as some extremely large unsigned value, which would be a Bad Thing.
The same exact issue exists in the existing code, from which this is derived, in __lmb_alloc_base().
This situation can occur any time a region is smaller than the 'size' argument, in both functions.