]> granicus.if.org Git - zfs/commitdiff
Consistently use local_irq_disable/local_irq_enable
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 25 Sep 2013 21:52:29 +0000 (14:52 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 9 Oct 2013 21:00:56 +0000 (14:00 -0700)
It was observed that spl_kmem_cache_alloc() uses local_irq_save()
and saves the interrupt state in a local variable.  This would
normally be fine except that spl_kmem_cache_alloc() calls
spl_cache_refill() which re-enables interrupts.  It is then
possible that while interrupts are enabled the process is
rescheduled to a different cpu before being disable again.
This could result in us restoring the saved interrupt state
from one cpu to another.

What the consequences of this are aren't perfectly clear, but
this is clearly a bug and it has the potential to cause issues.
The code has been updated to just use local_irq_enable() and
local_irq_disable() to avoid this.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
module/spl/spl-kmem.c

index a2dcea03968164a6ee72c1e8da81b01b0d3b9e6b..23e47808aaa70931d596e435312b1090e96a3f54 100644 (file)
@@ -1995,7 +1995,6 @@ void *
 spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags)
 {
        spl_kmem_magazine_t *skm;
-       unsigned long irq_flags;
        void *obj = NULL;
        SENTRY;
 
@@ -2003,7 +2002,7 @@ spl_kmem_cache_alloc(spl_kmem_cache_t *skc, int flags)
        ASSERT(!test_bit(KMC_BIT_DESTROY, &skc->skc_flags));
        ASSERT(flags & KM_SLEEP);
        atomic_inc(&skc->skc_ref);
-       local_irq_save(irq_flags);
+       local_irq_disable();
 
 restart:
        /* Safe to update per-cpu structure without lock, but
@@ -2025,7 +2024,7 @@ restart:
                        SGOTO(restart, obj = NULL);
        }
 
-       local_irq_restore(irq_flags);
+       local_irq_enable();
        ASSERT(obj);
        ASSERT(IS_P2ALIGNED(obj, skc->skc_obj_align));