Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

swim3: fix interruptible_sleep_on race

interruptible_sleep_on is racy and going away. This replaces the one
caller in the swim3 driver with the equivalent race-free
wait_event_interruptible call. Since we're here already, this
also fixes the case where we get interrupted from atomic context,
which used to just spin in the loop.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Jens Axboe <axboe@fb.com>

authored by

Arnd Bergmann and committed by
Jens Axboe
106fd892 7b8a3d22

+11 -7
+11 -7
drivers/block/swim3.c
··· 30 30 #include <linux/mutex.h> 31 31 #include <linux/module.h> 32 32 #include <linux/spinlock.h> 33 + #include <linux/wait.h> 33 34 #include <asm/io.h> 34 35 #include <asm/dbdma.h> 35 36 #include <asm/prom.h> ··· 841 840 spin_lock_irqsave(&swim3_lock, flags); 842 841 if (fs->state != idle && fs->state != available) { 843 842 ++fs->wanted; 844 - while (fs->state != available) { 843 + /* this will enable irqs in order to sleep */ 844 + if (!interruptible) 845 + wait_event_lock_irq(fs->wait, 846 + fs->state == available, 847 + swim3_lock); 848 + else if (wait_event_interruptible_lock_irq(fs->wait, 849 + fs->state == available, 850 + swim3_lock)) { 851 + --fs->wanted; 845 852 spin_unlock_irqrestore(&swim3_lock, flags); 846 - if (interruptible && signal_pending(current)) { 847 - --fs->wanted; 848 - return -EINTR; 849 - } 850 - interruptible_sleep_on(&fs->wait); 851 - spin_lock_irqsave(&swim3_lock, flags); 853 + return -EINTR; 852 854 } 853 855 --fs->wanted; 854 856 }