Re: floppy access causes crash in 2.1.3

Alain Knaff (Alain.Knaff@imag.fr)
Thu, 17 Oct 1996 23:35:30 +0200


>I got a couple of crashes running make zdisk the other day under 2.1.3 and
>again it's crashing when I'm trying to make redhat 4.0 boot floppies. I
>don't have the problem under 2.0.21. (same floppies and everything)

ok, I think I found the problem:

Starting from 2.1.3 on, the sync_buffers routine no longer scans all
buffer lists, but only the "dirty" (modified) buffer list. The result
of this is that fsync is no longer synchronous, i.e. it is no longer
guaranteed that all buffers have been written to disk when fsync
returns.
This affects the floppy driver very badly. Indeed, in order to allow
sharing with ftape, the floppy driver releases its IRQ and DMA when
nobody has the device open. However, it can't handle any I/O requests
in this state. In order to make sure that it doesn't get any
"deferred write" requests in this state, it fsyncs its buffers
whenever a file descriptor to a floppy device is closed. Usually this
ensures that all outstanding writes to the floppy are done at close
time. Unfortunatelym this no longer works, and the write requests
which happen after close crash the floppy driver.

The following patch should fix the problem:

Regards,

Alain

diff -ur 2.1.4/linux/fs/buffer.c linux/fs/buffer.c
--- 2.1.4/linux/fs/buffer.c Thu Oct 17 21:47:38 1996
+++ linux/fs/buffer.c Thu Oct 17 21:22:55 1996
@@ -210,7 +210,31 @@
next->b_count--;
retry = 1;
}
-
+
+ repeat2:
+ bh = lru_list[BUF_LOCKED];
+ if (!bh)
+ break;
+ for (i = nr_buffers_type[BUF_LOCKED]*2 ; i-- > 0 ; bh = next) {
+ if (bh->b_list != BUF_LOCKED)
+ goto repeat2;
+ next = bh->b_next_free;
+ if (!lru_list[BUF_LOCKED])
+ break;
+ if (dev && bh->b_dev != dev)
+ continue;
+ if (buffer_locked(bh)) {
+ /* Buffer is locked; skip it unless wait is
+ requested AND pass > 0. */
+ if (!wait || !pass) {
+ retry = 1;
+ continue;
+ }
+ wait_on_buffer (bh);
+ goto repeat2;
+ }
+ }
+
/* If we are waiting for the sync to succeed, and if any dirty
blocks were written, then repeat; on the second pass, only
wait for buffers being written (do not pass to write any