Patch "locking/spinlock/debug: Fix various data races" has been added to the 4.4-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    locking/spinlock/debug: Fix various data races

to the 4.4-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     locking-spinlock-debug-fix-various-data-races.patch
and it can be found in the queue-4.4 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 94d2d936ddddc296f89867b4100b2af480d96b8d
Author: Marco Elver <elver@xxxxxxxxxx>
Date:   Wed Nov 20 16:57:15 2019 +0100

    locking/spinlock/debug: Fix various data races
    
    [ Upstream commit 1a365e822372ba24c9da0822bc583894f6f3d821 ]
    
    This fixes various data races in spinlock_debug. By testing with KCSAN,
    it is observable that the console gets spammed with data races reports,
    suggesting these are extremely frequent.
    
    Example data race report:
    
      read to 0xffff8ab24f403c48 of 4 bytes by task 221 on cpu 2:
       debug_spin_lock_before kernel/locking/spinlock_debug.c:85 [inline]
       do_raw_spin_lock+0x9b/0x210 kernel/locking/spinlock_debug.c:112
       __raw_spin_lock include/linux/spinlock_api_smp.h:143 [inline]
       _raw_spin_lock+0x39/0x40 kernel/locking/spinlock.c:151
       spin_lock include/linux/spinlock.h:338 [inline]
       get_partial_node.isra.0.part.0+0x32/0x2f0 mm/slub.c:1873
       get_partial_node mm/slub.c:1870 [inline]
      <snip>
    
      write to 0xffff8ab24f403c48 of 4 bytes by task 167 on cpu 3:
       debug_spin_unlock kernel/locking/spinlock_debug.c:103 [inline]
       do_raw_spin_unlock+0xc9/0x1a0 kernel/locking/spinlock_debug.c:138
       __raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:159 [inline]
       _raw_spin_unlock_irqrestore+0x2d/0x50 kernel/locking/spinlock.c:191
       spin_unlock_irqrestore include/linux/spinlock.h:393 [inline]
       free_debug_processing+0x1b3/0x210 mm/slub.c:1214
       __slab_free+0x292/0x400 mm/slub.c:2864
      <snip>
    
    As a side-effect, with KCSAN, this eventually locks up the console, most
    likely due to deadlock, e.g. .. -> printk lock -> spinlock_debug ->
    KCSAN detects data race -> kcsan_print_report() -> printk lock ->
    deadlock.
    
    This fix will 1) avoid the data races, and 2) allow using lock debugging
    together with KCSAN.
    
    Reported-by: Qian Cai <cai@xxxxxx>
    Signed-off-by: Marco Elver <elver@xxxxxxxxxx>
    Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
    Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
    Cc: Paul E. McKenney <paulmck@xxxxxxxxxx>
    Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
    Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
    Cc: Will Deacon <will.deacon@xxxxxxx>
    Link: https://lkml.kernel.org/r/20191120155715.28089-1-elver@xxxxxxxxxx
    Signed-off-by: Ingo Molnar <mingo@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/locking/spinlock_debug.c b/kernel/locking/spinlock_debug.c
index 0374a596cffa..95e610e3f7ef 100644
--- a/kernel/locking/spinlock_debug.c
+++ b/kernel/locking/spinlock_debug.c
@@ -51,19 +51,19 @@ EXPORT_SYMBOL(__rwlock_init);
 
 static void spin_dump(raw_spinlock_t *lock, const char *msg)
 {
-	struct task_struct *owner = NULL;
+	struct task_struct *owner = READ_ONCE(lock->owner);
 
-	if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
-		owner = lock->owner;
+	if (owner == SPINLOCK_OWNER_INIT)
+		owner = NULL;
 	printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
 		msg, raw_smp_processor_id(),
 		current->comm, task_pid_nr(current));
 	printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, "
 			".owner_cpu: %d\n",
-		lock, lock->magic,
+		lock, READ_ONCE(lock->magic),
 		owner ? owner->comm : "<none>",
 		owner ? task_pid_nr(owner) : -1,
-		lock->owner_cpu);
+		READ_ONCE(lock->owner_cpu));
 	dump_stack();
 }
 
@@ -80,16 +80,16 @@ static void spin_bug(raw_spinlock_t *lock, const char *msg)
 static inline void
 debug_spin_lock_before(raw_spinlock_t *lock)
 {
-	SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
-	SPIN_BUG_ON(lock->owner == current, lock, "recursion");
-	SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+	SPIN_BUG_ON(READ_ONCE(lock->magic) != SPINLOCK_MAGIC, lock, "bad magic");
+	SPIN_BUG_ON(READ_ONCE(lock->owner) == current, lock, "recursion");
+	SPIN_BUG_ON(READ_ONCE(lock->owner_cpu) == raw_smp_processor_id(),
 							lock, "cpu recursion");
 }
 
 static inline void debug_spin_lock_after(raw_spinlock_t *lock)
 {
-	lock->owner_cpu = raw_smp_processor_id();
-	lock->owner = current;
+	WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
+	WRITE_ONCE(lock->owner, current);
 }
 
 static inline void debug_spin_unlock(raw_spinlock_t *lock)
@@ -99,8 +99,8 @@ static inline void debug_spin_unlock(raw_spinlock_t *lock)
 	SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
 	SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
 							lock, "wrong CPU");
-	lock->owner = SPINLOCK_OWNER_INIT;
-	lock->owner_cpu = -1;
+	WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
+	WRITE_ONCE(lock->owner_cpu, -1);
 }
 
 static void __spin_lock_debug(raw_spinlock_t *lock)
@@ -233,8 +233,8 @@ static inline void debug_write_lock_before(rwlock_t *lock)
 
 static inline void debug_write_lock_after(rwlock_t *lock)
 {
-	lock->owner_cpu = raw_smp_processor_id();
-	lock->owner = current;
+	WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
+	WRITE_ONCE(lock->owner, current);
 }
 
 static inline void debug_write_unlock(rwlock_t *lock)
@@ -243,8 +243,8 @@ static inline void debug_write_unlock(rwlock_t *lock)
 	RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
 	RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
 							lock, "wrong CPU");
-	lock->owner = SPINLOCK_OWNER_INIT;
-	lock->owner_cpu = -1;
+	WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
+	WRITE_ONCE(lock->owner_cpu, -1);
 }
 
 #if 0		/* This can cause lockups */



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux