aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAlok N Kataria <alokk@calsoftinc.com>2005-09-28 00:45:46 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-28 10:46:42 -0400
commit5c382300876f2337f7b945c159ffcaf285f296ea (patch)
treed505f231c23d415f2609c6bf0ef7c196503dc161 /mm
parent0f9578b70a9f112bfb541e1d5ab486a376e64503 (diff)
[PATCH] kmalloc_node IRQ safety fix
In kmalloc_node we are checking if the allocation is for the same node when interrupts are "on". This may lead to an allocation on another node than intended. This patch just shifts the check for the current node in __cache_alloc_node when interrupts are disabled. Signed-off-by: Alok N Kataria <alokk@calsoftinc.com> Acked-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/slab.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/mm/slab.c b/mm/slab.c
index c9adfce00405..5cbbdfa6dd0e 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2510,16 +2510,12 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
2510#define cache_alloc_debugcheck_after(a,b,objp,d) (objp) 2510#define cache_alloc_debugcheck_after(a,b,objp,d) (objp)
2511#endif 2511#endif
2512 2512
2513 2513static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
2514static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
2515{ 2514{
2516 unsigned long save_flags;
2517 void* objp; 2515 void* objp;
2518 struct array_cache *ac; 2516 struct array_cache *ac;
2519 2517
2520 cache_alloc_debugcheck_before(cachep, flags); 2518 check_irq_off();
2521
2522 local_irq_save(save_flags);
2523 ac = ac_data(cachep); 2519 ac = ac_data(cachep);
2524 if (likely(ac->avail)) { 2520 if (likely(ac->avail)) {
2525 STATS_INC_ALLOCHIT(cachep); 2521 STATS_INC_ALLOCHIT(cachep);
@@ -2529,6 +2525,18 @@ static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast fl
2529 STATS_INC_ALLOCMISS(cachep); 2525 STATS_INC_ALLOCMISS(cachep);
2530 objp = cache_alloc_refill(cachep, flags); 2526 objp = cache_alloc_refill(cachep, flags);
2531 } 2527 }
2528 return objp;
2529}
2530
2531static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags)
2532{
2533 unsigned long save_flags;
2534 void* objp;
2535
2536 cache_alloc_debugcheck_before(cachep, flags);
2537
2538 local_irq_save(save_flags);
2539 objp = ____cache_alloc(cachep, flags);
2532 local_irq_restore(save_flags); 2540 local_irq_restore(save_flags);
2533 objp = cache_alloc_debugcheck_after(cachep, flags, objp, 2541 objp = cache_alloc_debugcheck_after(cachep, flags, objp,
2534 __builtin_return_address(0)); 2542 __builtin_return_address(0));
@@ -2856,7 +2864,10 @@ void *kmem_cache_alloc_node(kmem_cache_t *cachep, unsigned int __nocast flags, i
2856 2864
2857 cache_alloc_debugcheck_before(cachep, flags); 2865 cache_alloc_debugcheck_before(cachep, flags);
2858 local_irq_save(save_flags); 2866 local_irq_save(save_flags);
2859 ptr = __cache_alloc_node(cachep, flags, nodeid); 2867 if (nodeid == numa_node_id())
2868 ptr = ____cache_alloc(cachep, flags);
2869 else
2870 ptr = __cache_alloc_node(cachep, flags, nodeid);
2860 local_irq_restore(save_flags); 2871 local_irq_restore(save_flags);
2861 ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0)); 2872 ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0));
2862 2873