summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorRichard Yao <[email protected]>2013-08-04 19:35:08 -0400
committerBrian Behlendorf <[email protected]>2013-08-08 09:14:41 -0700
commit251e7a779ba5d4b5e46c42d8b792c481380da28b (patch)
tree9ba48df6ae559684fe303827da60fb6c091a3343 /module
parentba062980728bbd09c4b829f5d801a773af7381cf (diff)
Fix race in spl_kmem_cache_reap_now()
The current code contains a race condition that triggers when bit 2 in spl.spl_kmem_cache_expire is set, spl_kmem_cache_reap_now() is invoked and another thread is concurrently accessing its magazine. spl_kmem_cache_reap_now() currently invokes spl_cache_flush() on each magazine in the same thread when bit 2 in spl.spl_kmem_cache_expire is set. This is unsafe because there is one magazine per CPU and the magazines are lockless, so it is impossible to guarentee that another CPU is not using its magazine when this function is called. The solution is to only touch the local CPU's magazine and leave other CPU's magazines to other CPUs. Reported-by: DHE Signed-off-by: Richard Yao <[email protected]> Signed-off-by: Brian Behlendorf <[email protected]> Closes #274
Diffstat (limited to 'module')
-rw-r--r--module/spl/spl-kmem.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/module/spl/spl-kmem.c b/module/spl/spl-kmem.c
index 3c01ab69c..a2dcea039 100644
--- a/module/spl/spl-kmem.c
+++ b/module/spl/spl-kmem.c
@@ -2196,12 +2196,12 @@ spl_kmem_cache_reap_now(spl_kmem_cache_t *skc, int count)
/* Reclaim from the magazine then the slabs ignoring age and delay. */
if (spl_kmem_cache_expire & KMC_EXPIRE_MEM) {
spl_kmem_magazine_t *skm;
- int i;
+ unsigned long irq_flags;
- for_each_online_cpu(i) {
- skm = skc->skc_mag[i];
- spl_cache_flush(skc, skm, skm->skm_avail);
- }
+ local_irq_save(irq_flags);
+ skm = skc->skc_mag[smp_processor_id()];
+ spl_cache_flush(skc, skm, skm->skm_avail);
+ local_irq_restore(irq_flags);
}
spl_slab_reclaim(skc, count, 1);