Skip to contentSkip to conversation

lmb: add lmb_alloc_nid()

PATCH In review [email protected] 3 participants 3 messages Mar 28, 2008 – Apr 1, 2008 Library code

lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

PATCH 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.

Cc Paul Mackerras <[email protected]>
Cc Benjamin Herrenschmidt <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>

---

 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
diff -puN include/linux/lmb.h~lmb-add-lmb_alloc_nid include/linux/lmb.h
@@ -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

_

#1 lore raw
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 normal lmb_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.

#2 lore raw

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 normal lmb_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.