[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>

authored by Alok N Kataria and committed by Linus Torvalds 5c382300 0f9578b7

+18 -7
+18 -7
mm/slab.c
··· 2510 2510 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) 2511 2511 #endif 2512 2512 2513 - 2514 - static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) 2513 + static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) 2515 2514 { 2516 - unsigned long save_flags; 2517 2515 void* objp; 2518 2516 struct array_cache *ac; 2519 2517 2520 - cache_alloc_debugcheck_before(cachep, flags); 2521 - 2522 - local_irq_save(save_flags); 2518 + check_irq_off(); 2523 2519 ac = ac_data(cachep); 2524 2520 if (likely(ac->avail)) { 2525 2521 STATS_INC_ALLOCHIT(cachep); ··· 2525 2529 STATS_INC_ALLOCMISS(cachep); 2526 2530 objp = cache_alloc_refill(cachep, flags); 2527 2531 } 2532 + return objp; 2533 + } 2534 + 2535 + static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) 2536 + { 2537 + unsigned long save_flags; 2538 + void* objp; 2539 + 2540 + cache_alloc_debugcheck_before(cachep, flags); 2541 + 2542 + local_irq_save(save_flags); 2543 + objp = ____cache_alloc(cachep, flags); 2528 2544 local_irq_restore(save_flags); 2529 2545 objp = cache_alloc_debugcheck_after(cachep, flags, objp, 2530 2546 __builtin_return_address(0)); ··· 2864 2856 2865 2857 cache_alloc_debugcheck_before(cachep, flags); 2866 2858 local_irq_save(save_flags); 2867 - ptr = __cache_alloc_node(cachep, flags, nodeid); 2859 + if (nodeid == numa_node_id()) 2860 + ptr = ____cache_alloc(cachep, flags); 2861 + else 2862 + ptr = __cache_alloc_node(cachep, flags, nodeid); 2868 2863 local_irq_restore(save_flags); 2869 2864 ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0)); 2870 2865