cpumask: add alloc_cpumask_var_node
Subsystems (3)
PATCH 1/1 cpumask: add alloc_cpumask_var_node
Add alloc_cpumask_var_node. This will be needed in x86 code to allocate the domain and old_domain cpumasks on the same node as where the containing irq_cfg struct is allocated.
Additional documentation added to all the alloc_cpumask and free_cpumask functions.
For submission via linux-next.
--- include/linux/cpumask.h | 1 lib/cpumask.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+)
include/linux/cpumask.h +1 -0
@@ -1008,6 +1008,7 @@ static inline size_t cpumask_size(void)typedef struct cpumask *cpumask_var_t ;bool alloc_cpumask_var (cpumask_var_t *mask,gfp_t flags); +bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags,int node);void alloc_bootmem_cpumask_var (cpumask_var_t *mask);void free_cpumask_var (cpumask_var_t mask);void free_bootmem_cpumask_var (cpumask_var_t mask);
lib/cpumask.c +60 -0
83 lines not on this page · raw message
Hi Mike,
Just some simple comments.
Quoted 5 lines · On Mon, 15 Dec 2008 18:32:51 -0800 Mike Travis <[email protected]> wrote:
+/**
+ *alloc_cpumask_var- return an allocated struct cpumask
+ * @mask: pointer tocpumask_var_twhere the cpumask is returned
+ * @cpu:GFP_flags
^^^
flags
Quoted 4 lines
+ *
alloc_cpumask_var_node- return an allocated struct cpumask on a
+ * specific node.
+ * @mask: pointer tocpumask_var_twhere the cpumask is returned
+ * @cpu:GFP_flags
^^^
flags
Quoted 14 lines
+ * @node: node to allocate memory on
+ *
+ * Only defined whenCONFIG_CPUMASK_OFFSTACK=y, otherwise is
+ * a nop returning a constant 1 (in <linux/cpumask.h>)
+ * Returns TRUE if memory allocation succeeded, FALSE otherwise.
+ */lib/cpumask.c +8
-0+bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags,int node) +{ +if (likely (slab_is_available ())) + *mask =kmalloc_node (cpumask_size (), flags, node); +else { +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +printk (KERN_ERR +"=> alloc_cpumask_var_node: kmalloc not available!\n" );
lib/cpumask.c bool alloc_cpumask_var(cpumask_var_t *ma · line 138
Quoted 10 lines
lib/cpumask.c +10
-0+dump_stack (); +#endif + *mask =NULL ; + } +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +if (!*mask) { +printk (KERN_ERR "=> alloc_cpumask_var_node: failed!\n" ); +dump_stack (); + } +#endif
So if !slab_is_available() and CONFIG_DEBUG_PER_CPU_MAPS is set, we get two stack dumps?
Quoted 2 lines
+ *
free_cpumask_var- frees memory allocated for a struct cpumask.
+ * mask: cpumask to free
^
missing '@'
Quoted 2 lines
+ *
free_bootmem_cpumask_var- frees bootmem memory allocated for a struct cpumask.
+ * mask: cpumask to free
^
here as well.
Signature · 3 lines
Cheers, Stephen Rothwell [email protected] http://www.canb.auug.org.au/~sfr/
Quoted 11 lines · Stephen Rothwell
Hi Mike,
Just some simple comments.
Quoted 4 lines · On Mon, 15 Dec 2008 18:32:51 -0800 Mike Travis <[email protected]> wrote:
+/**
+ *alloc_cpumask_var- return an allocated struct cpumask
+ * @mask: pointer tocpumask_var_twhere the cpumask is returned
+ * @cpu:GFP_flags^^^flags
Hmm, even the simplest changes can go awry... ;-)
Quoted 7 lines
Quoted 5 lines
+ *
alloc_cpumask_var_node- return an allocated struct cpumask on a
+ * specific node.
+ * @mask: pointer tocpumask_var_twhere the cpumask is returned
+ * @cpu:GFP_flags^^^flags
Gotcha.
Quoted 20 lines
Quoted 20 lines
+ * @node: node to allocate memory on
+ *
+ * Only defined whenCONFIG_CPUMASK_OFFSTACK=y, otherwise is
+ * a nop returning a constant 1 (in <linux/cpumask.h>)
+ * Returns TRUE if memory allocation succeeded, FALSE otherwise.
+ */lib/cpumask.c +13
-0+bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags,int node) +{ +if (likely (slab_is_available ())) + *mask =kmalloc_node (cpumask_size (), flags, node); +else { +#ifdef CONFIG_DEBUG_PER_CPU_MAPS +printk (KERN_ERR +"=> alloc_cpumask_var_node: kmalloc not available!\n" ); +dump_stack (); +#endif + *mask =NULL ; + } +#ifdef CONFIG_DEBUG_PER_CPU_MAPS
Quoted 8 lines
lib/cpumask.c bool alloc_cpumask_var(cpumask_var_t *ma · line 138
Quoted 5 lines
lib/cpumask.c +5
-0+if (!*mask) { +printk (KERN_ERR "=> alloc_cpumask_var_node: failed!\n" ); +dump_stack (); + } +#endif So if !slab_is_available() and
CONFIG_DEBUG_PER_CPU_MAPSis set, we get two stack dumps?
Umm, you're right, one message should suffice... ;-)
Here's one place I discovered it in testing:
[ 0.000000] Initializing CPU#0 [ 0.000000] RCU-based detection of stalled CPUs is enabled. [ 0.000000] => alloc_cpumask_var: kmalloc not available! [ 0.000000] Pid: 0, comm: swapper Not tainted 2.6.28-rc8-128-defconfig.12151554-00944-g968ea6d -dirty #21 [ 0.000000] Call Trace: [ 0.000000] [<ffffffff8123b5bb>] alloc_cpumask_var+0x73/0xa7 [ 0.000000] [<ffffffff819197d0>] arch_early_irq_init+0x35/0xc3 [ 0.000000] [<ffffffff8192583d>] early_irq_init+0x57/0x59 [ 0.000000] [<ffffffff8190ab77>] start_kernel+0x1f9/0x3c2 [ 0.000000] [<ffffffff8190a29a>] x86_64_start_reservations+0xa9/0xad [ 0.000000] [<ffffffff8190a39b>] x86_64_start_kernel+0xda/0xe1 [ 0.000000] => alloc_cpumask_var: failed!
<same as above>
...
The message clued me into the fact that the function was allocating early and needed to be an alloc_bootmem_cpumask_var().
Quoted 11 lines
Quoted 3 lines
+ *
free_cpumask_var- frees memory allocated for a struct cpumask.
+ * mask: cpumask to free^missing '@'
Quoted 2 lines
+ *
free_bootmem_cpumask_var- frees bootmem memory allocated for a struct cpumask.
+ * mask: cpumask to free^here as well.
Will fix it up and resend.
Thanks!
Mike
PATCH 1/1 cpumask: add alloc_cpumask_var_node V2
Subject: cpumask: add alloc_cpumask_var_node V2
V2: Fix syntax errors in function comments.
Display only one error message when !slab_is_available. Add nop inline alloc_cpumask_var_node() for !SMP, Fix EXPORT_SYMBOL for alloc_cpumask_var_node.
Add alloc_cpumask_var_node. This will be needed in x86 code to allocate the domain and old_domain cpumasks on the same node as where the containing irq_cfg struct is allocated.
Additional documentation added to all the alloc_cpumask and free_cpumask functions.
For submission via linux-next.
--- include/linux/cpumask.h | 7 ++++ lib/cpumask.c | 70 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 4 deletions(-)
include/linux/cpumask.h +7 -0
@@ -1026,6 +1026,7 @@ static inline size_t cpumask_size(void)typedef struct cpumask *cpumask_var_t ;bool alloc_cpumask_var (cpumask_var_t *mask,gfp_t flags); +bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags,int node);void alloc_bootmem_cpumask_var (cpumask_var_t *mask);void free_cpumask_var (cpumask_var_t mask);void free_bootmem_cpumask_var (cpumask_var_t mask);
@@ -1038,6 +1039,12 @@ static inline bool alloc_cpumask_var(cpureturn true; } +static inline bool alloc_cpumask_var_node (cpumask_var_t *mask, +gfp_t flags,int node) +{ +return true; +} +static inline void alloc_bootmem_cpumask_var (cpumask_var_t *mask) { }
lib/cpumask.c +66 -4
105 lines not on this page · raw message
Re: [PATCH 1/1] cpumask: add alloc_cpumask_var_node V2
Quoted 3 lines · On Tuesday 16 December 2008 14:49:37 Mike Travis wrote:
Add
alloc_cpumask_var_node. This will be needed in x86 code to allocate the domain andold_domaincpumasks on the same node as where the containingirq_cfgstruct is allocated.
OK, this is understandable. If you don't mind I'll split this patch into documentation and node patches separately.
Since kmalloc(size, gfp) == kmalloc_node(size, gfp, -1), I think we can change this to implement alloc_cpumask_var() in terms of alloc_cpumask_var_node(..., numa_node_id()).
Here's what I ended up with:
Add alloc_cpumask_var_node()
This will be needed in x86 code to allocate the domain and old_domain cpumasks on the same node as where the containing irq_cfg struct is allocated.
include/linux/cpumask.h +7 -0
@@ -1011,6 +1011,7 @@ static inline size_t cpumask_size(void)#ifdef CONFIG_CPUMASK_OFFSTACK typedef struct cpumask *cpumask_var_t ; +bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags,int node);bool alloc_cpumask_var (cpumask_var_t *mask,gfp_t flags);void alloc_bootmem_cpumask_var (cpumask_var_t *mask);void free_cpumask_var (cpumask_var_t mask);
@@ -1020,6 +1021,12 @@ typedef struct cpumask cpumask_var_t[1];typedef struct cpumask cpumask_var_t [1 ];static inline bool alloc_cpumask_var (cpumask_var_t *mask,gfp_t flags) +{ +return true; +} + +static inline bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags, +int node) {return true; }
lib/cpumask.c +8 -3
@@ -76,15 +76,14 @@ int cpumask_any_but(const struct cpumask/* These are not inline because of header tangles. */ #ifdef CONFIG_CPUMASK_OFFSTACK -bool alloc_cpumask_var (cpumask_var_t *mask,gfp_t flags) +bool alloc_cpumask_var_node (cpumask_var_t *mask,gfp_t flags,int node) {if (likely (slab_is_available ())) - *mask =kmalloc (cpumask_size (), flags); + *mask =kmalloc_node (cpumask_size (), flags, node);else {#ifdef CONFIG_DEBUG_PER_CPU_MAPS printk (KERN_ERR "=> alloc_cpumask_var: kmalloc not available!\n" ); -dump_stack ();#endif *mask =NULL ; }
@@ -95,6 +94,12 @@ bool alloc_cpumask_var(cpumask_var_t *ma }#endif return *mask !=NULL ; +} +EXPORT_SYMBOL (alloc_cpumask_var_node); + +bool alloc_cpumask_var (cpumask_var_t *mask,gfp_t flags) +{ +return alloc_cpumask_var_node (mask, flag,numa_node_id ()); }EXPORT_SYMBOL (alloc_cpumask_var);
cpumask: documentation for cpumask_var_t
Additional documentation added to all the alloc_cpumask and free_cpumask functions.
lib/cpumask.c +43 -0
72 lines not on this page · raw message
Re: [PATCH 1/1] cpumask: add alloc_cpumask_var_node V2
Quoted 5 lines · Rusty Russell
Quoted 3 lines · On Tuesday 16 December 2008 14:49:37 Mike Travis wrote:
Add
alloc_cpumask_var_node. This will be needed in x86 code to allocate the domain andold_domaincpumasks on the same node as where the containingirq_cfgstruct is allocated.
Quoted 7 lines
OK, this is understandable. If you don't mind I'll split this patch into documentation and node patches separately.
Since
kmalloc(size, gfp)==kmalloc_node(size, gfp, -1), I think we can change this to implementalloc_cpumask_var()in terms ofalloc_cpumask_var_node(..., numa_node_id()).
Cool, thanks!
Mike