aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-02-26 06:01:44 -0500
committerJens Axboe <axboe@fb.com>2014-03-13 16:56:38 -0400
commit106fd892bc714a9b7c28daba98a3623a41c32f1a (patch)
treeaaa08a49fe4c4bcb6ae342649cde84cbd879521e
parent7b8a3d22ba93682a542a445ef43d03f495cdf3d6 (diff)
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>
-rw-r--r--drivers/block/swim3.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 20e061c3e023..c74f7b56e7c4 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -30,6 +30,7 @@
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/wait.h>
33#include <asm/io.h> 34#include <asm/io.h>
34#include <asm/dbdma.h> 35#include <asm/dbdma.h>
35#include <asm/prom.h> 36#include <asm/prom.h>
@@ -840,14 +841,17 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
840 spin_lock_irqsave(&swim3_lock, flags); 841 spin_lock_irqsave(&swim3_lock, flags);
841 if (fs->state != idle && fs->state != available) { 842 if (fs->state != idle && fs->state != available) {
842 ++fs->wanted; 843 ++fs->wanted;
843 while (fs->state != available) { 844 /* this will enable irqs in order to sleep */
845 if (!interruptible)
846 wait_event_lock_irq(fs->wait,
847 fs->state == available,
848 swim3_lock);
849 else if (wait_event_interruptible_lock_irq(fs->wait,
850 fs->state == available,
851 swim3_lock)) {
852 --fs->wanted;
844 spin_unlock_irqrestore(&swim3_lock, flags); 853 spin_unlock_irqrestore(&swim3_lock, flags);
845 if (interruptible && signal_pending(current)) { 854 return -EINTR;
846 --fs->wanted;
847 return -EINTR;
848 }
849 interruptible_sleep_on(&fs->wait);
850 spin_lock_irqsave(&swim3_lock, flags);
851 } 855 }
852 --fs->wanted; 856 --fs->wanted;
853 } 857 }