diff options
author | David Rientjes <rientjes@google.com> | 2009-12-14 20:59:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-15 11:53:20 -0500 |
commit | 9ae49fab239fb49de92a657c7426271e0793c4e1 (patch) | |
tree | 156f78df3db4dbc408f6839febe7adba148c2c9f /drivers/base/node.c | |
parent | caed0f486e582eeeb6e3546417fd758230fe4ad9 (diff) |
mm: slab-allocate memory section nodemask for large systems
Nodemasks should not be allocated on the stack for large systems (when it
is larger than 256 bytes) since there is a threat of overflow.
This patch causes the unregister_mem_sect_under_nodes() nodemask to be
allocated on the stack for smaller systems and be allocated by slab for
larger systems.
GFP_KERNEL is used since remove_memory_block() can block.
Cc: Gary Hade <garyhade@us.ibm.com>
Cc: Badari Pulavarty <pbadari@us.ibm.com>
Cc: Alex Chiang <achiang@hp.com>
Signed-off-by: David Rientjes <rientjes@google.com>
Cc: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/base/node.c')
-rw-r--r-- | drivers/base/node.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index 41414113b9f0..70122791683d 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -363,12 +363,16 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid) | |||
363 | /* unregister memory section under all nodes that it spans */ | 363 | /* unregister memory section under all nodes that it spans */ |
364 | int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | 364 | int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) |
365 | { | 365 | { |
366 | nodemask_t unlinked_nodes; | 366 | NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL); |
367 | unsigned long pfn, sect_start_pfn, sect_end_pfn; | 367 | unsigned long pfn, sect_start_pfn, sect_end_pfn; |
368 | 368 | ||
369 | if (!mem_blk) | 369 | if (!mem_blk) { |
370 | NODEMASK_FREE(unlinked_nodes); | ||
370 | return -EFAULT; | 371 | return -EFAULT; |
371 | nodes_clear(unlinked_nodes); | 372 | } |
373 | if (!unlinked_nodes) | ||
374 | return -ENOMEM; | ||
375 | nodes_clear(*unlinked_nodes); | ||
372 | sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); | 376 | sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); |
373 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; | 377 | sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; |
374 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { | 378 | for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { |
@@ -379,13 +383,14 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) | |||
379 | continue; | 383 | continue; |
380 | if (!node_online(nid)) | 384 | if (!node_online(nid)) |
381 | continue; | 385 | continue; |
382 | if (node_test_and_set(nid, unlinked_nodes)) | 386 | if (node_test_and_set(nid, *unlinked_nodes)) |
383 | continue; | 387 | continue; |
384 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, | 388 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, |
385 | kobject_name(&mem_blk->sysdev.kobj)); | 389 | kobject_name(&mem_blk->sysdev.kobj)); |
386 | sysfs_remove_link(&mem_blk->sysdev.kobj, | 390 | sysfs_remove_link(&mem_blk->sysdev.kobj, |
387 | kobject_name(&node_devices[nid].sysdev.kobj)); | 391 | kobject_name(&node_devices[nid].sysdev.kobj)); |
388 | } | 392 | } |
393 | NODEMASK_FREE(unlinked_nodes); | ||
389 | return 0; | 394 | return 0; |
390 | } | 395 | } |
391 | 396 | ||