From: Jens Axboe <axboe@suse.de>
To: Linux Kernel <linux-kernel@vger.kernel.org>
Subject: [PATCH] floppy smp (and misc) fixes
Date: Wed, 4 Jun 2003 15:10:12 +0200 [thread overview]
Message-ID: <20030604131012.GT4853@suse.de> (raw)
Hi,
There are several smp races in the 2.4.21-rc floppy driver that can
cause a process writing/reading to the drive to stall forever. Basically
it quits out of request handling with requests pending. I verified that
these requests were not seen by the floppy driver yet. It went to unlock
the drive in a bad state.
Additionally, I put a smaller limit on requests sizes. It doesn't make
any sense to have 128 * 255 sectors pending in the write queue (about
16MiB of data) and it just causes huge latencies when someone wants to
stop a dd, for instance.
With this patch I cannot reproduce any more floppy hangs on a 4-way.
--- drivers/block/floppy.c~ 2003-06-04 14:58:50.000000000 +0200
+++ drivers/block/floppy.c 2003-06-04 14:59:33.000000000 +0200
@@ -482,6 +482,7 @@
static int floppy_sizes[256];
static int floppy_blocksizes[256];
+static int floppy_maxsectors[256];
/*
* The driver is trying to determine the correct media format
@@ -622,7 +623,8 @@
static void is_alive(const char *message)
{
/* this routine checks whether the floppy driver is "alive" */
- if (fdc_busy && command_status < 2 && !timer_pending(&fd_timeout)){
+ if (test_bit(0, &fdc_busy) && command_status < 2
+ && !timer_pending(&fd_timeout)){
DPRINT("timeout handler died: %s\n",message);
}
}
@@ -650,7 +652,7 @@
#define CURRENTD -1
#define MAXTIMEOUT -2
-static void reschedule_timeout(int drive, const char *message, int marg)
+static void __reschedule_timeout(int drive, const char *message, int marg)
{
if (drive == CURRENTD)
drive = current_drive;
@@ -669,6 +671,16 @@
timeout_message = message;
}
+
+static void reschedule_timeout(int drive, const char *message, int marg)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
+ __reschedule_timeout(drive, message, marg);
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
static int maximum(int a, int b)
{
if (a > b)
@@ -897,7 +909,7 @@
}
command_status = FD_COMMAND_NONE;
- reschedule_timeout(drive, "lock fdc", 0);
+ __reschedule_timeout(drive, "lock fdc", 0);
set_fdc(drive);
return 0;
}
@@ -911,17 +923,23 @@
/* unlocks the driver */
static inline void unlock_fdc(void)
{
+ unsigned long flags;
+
raw_cmd = 0;
- if (!fdc_busy)
+ if (!test_bit(0, &fdc_busy))
DPRINT("FDC access conflict!\n");
if (DEVICE_INTR)
DPRINT("device interrupt still active at FDC release: %p!\n",
DEVICE_INTR);
command_status = FD_COMMAND_NONE;
+ spin_lock_irqsave(&io_request_lock, flags);
del_timer(&fd_timeout);
cont = NULL;
clear_bit(0, &fdc_busy);
+ if (!QUEUE_EMPTY)
+ do_fd_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
+ spin_unlock_irqrestore(&io_request_lock, flags);
floppy_release_irq_and_dma();
wake_up(&fdc_wait);
}
@@ -1000,9 +1018,13 @@
static void cancel_activity(void)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&io_request_lock, flags);
CLEAR_INTR;
floppy_tq.routine = (void *)(void *) empty;
del_timer(&fd_timer);
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
/* this function makes sure that the disk stays in the drive during the
@@ -2986,7 +3008,7 @@
printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
return;
}
- if (fdc_busy){
+ if (test_bit(0, &fdc_busy)) {
/* fdc busy, this new request will be treated when the
current one is done */
is_alive("do fd request, old request running");
@@ -3878,7 +3900,7 @@
/* auto-sensing */
int size = floppy_blocksizes[MINOR(dev)];
if (!size)
- size = 1024;
+ size = 512;
if (!(bh = getblk(dev,0,size))){
process_fd_request();
return -ENXIO;
@@ -4170,14 +4192,19 @@
return -EBUSY;
}
- for (i=0; i<256; i++)
+ for (i=0; i<256; i++) {
if (ITYPE(i))
floppy_sizes[i] = (floppy_type[ITYPE(i)].size+1) >> 1;
else
floppy_sizes[i] = MAX_DISK_SIZE;
+ floppy_blocksizes[i] = 512;
+ floppy_maxsectors[i] = 64;
+ }
+
blk_size[MAJOR_NR] = floppy_sizes;
blksize_size[MAJOR_NR] = floppy_blocksizes;
+ max_sectors[MAJOR_NR] = floppy_maxsectors;
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
reschedule_timeout(MAXTIMEOUT, "floppy init", MAXTIMEOUT);
config_types();
--
Jens Axboe
reply other threads:[~2003-06-04 12:56 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20030604131012.GT4853@suse.de \
--to=axboe@suse.de \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.