[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 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) 2511 #endif 2512 2513 - 2514 - static inline void *__cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) 2515 { 2516 - unsigned long save_flags; 2517 void* objp; 2518 struct array_cache *ac; 2519 2520 - cache_alloc_debugcheck_before(cachep, flags); 2521 - 2522 - local_irq_save(save_flags); 2523 ac = ac_data(cachep); 2524 if (likely(ac->avail)) { 2525 STATS_INC_ALLOCHIT(cachep); ··· 2525 STATS_INC_ALLOCMISS(cachep); 2526 objp = cache_alloc_refill(cachep, flags); 2527 } 2528 local_irq_restore(save_flags); 2529 objp = cache_alloc_debugcheck_after(cachep, flags, objp, 2530 __builtin_return_address(0)); ··· 2864 2865 cache_alloc_debugcheck_before(cachep, flags); 2866 local_irq_save(save_flags); 2867 - ptr = __cache_alloc_node(cachep, flags, nodeid); 2868 local_irq_restore(save_flags); 2869 ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0)); 2870
··· 2510 #define cache_alloc_debugcheck_after(a,b,objp,d) (objp) 2511 #endif 2512 2513 + static inline void *____cache_alloc(kmem_cache_t *cachep, unsigned int __nocast flags) 2514 { 2515 void* objp; 2516 struct array_cache *ac; 2517 2518 + check_irq_off(); 2519 ac = ac_data(cachep); 2520 if (likely(ac->avail)) { 2521 STATS_INC_ALLOCHIT(cachep); ··· 2529 STATS_INC_ALLOCMISS(cachep); 2530 objp = cache_alloc_refill(cachep, flags); 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); 2544 local_irq_restore(save_flags); 2545 objp = cache_alloc_debugcheck_after(cachep, flags, objp, 2546 __builtin_return_address(0)); ··· 2856 2857 cache_alloc_debugcheck_before(cachep, flags); 2858 local_irq_save(save_flags); 2859 + if (nodeid == numa_node_id()) 2860 + ptr = ____cache_alloc(cachep, flags); 2861 + else 2862 + ptr = __cache_alloc_node(cachep, flags, nodeid); 2863 local_irq_restore(save_flags); 2864 ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, __builtin_return_address(0)); 2865