floppy smp (and misc) fixes
PATCH 1/1 floppy smp (and misc) fixes
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.
block/floppy.c renamed from block/floppy.c~ +34 -7
@@ -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 ();
Signature · 1 line
Jens Axboe