[patch] fix for pagecache fs corruption (2.3.15-pre2) [Re: [patch]

Andrea Arcangeli (andrea@suse.de)
Sun, 22 Aug 1999 15:43:08 +0200 (CEST)


On Sat, 21 Aug 1999, Bradley D. LaRonde wrote:

>Both initrd and regular ramdisk usage appear to work with the patch applied,
>but booting with initrd gives the following error (then goes on, apparently
>working fine):
>
>kernel BUG at buffer.c:696!
>invalid operand: 0000
>CPU: 0
>EIP: 0010:[<c01236de>]
>EFLAGS: 00010092
>eax: 0000001c ebx: c7ceb060 ecx: c018dc68 edx: c018dc70
>esi: c01a9a90 edi: 00000001 ebp: 00000000 esp: c009df7c
>ds: 0018 es: 0018 ss: 0018
>Process kflushd (pid: 3, stackpage=c009d000)
>Stack: 000002b8 c0144230 c7ceb060 00000001 c01a9a90 ffffffff c018f38c
>c014ee07
> c01a9a90 00000001 c0182d9b 00000001 c014eee3 00000001 00000246
>c018f38c
> c01435f4 00000000 c0125fe6 c01b3190 00000f00 c0e9dfb4 c037d0cc
>00000912
>Call Trace: [<c0144230>] [<c014ee07>] [<c0182d9b>] [<c014eee3>] [<c01435f4>]
>[<c0125fe6>] [<c01065b7>]
>Code: 0f 0b 83 c4 0c c3 57 56 53 8b 7c 24 10 8b 4c 24 14 85 c9 74
>
>ksymoops says:
>EIP: c01236de <end_buffer_io_bad+42/48>
>Trace: c0144230 <end_that_request_first+80/c4>
>Trace: c014ee07 <end_request+17/34>
>Trace: c0182d9b <head_vals.697+21af/35f4>
>Trace: c014eee3 <rd_request+bf/cc>
>Trace: c01435f4 <unplug_device+38/3c>
>Trace: c0125fe6 <bdflush+19e/1fc>
>Trace: c01065b7 <kernel_thread+23/30>
>Code: c01236de <end_buffer_io_bad+42/48> 00000000 <_EIP>: <===
>Code: c01236de <end_buffer_io_bad+42/48> 0: 0f 0b ud2a
><===
>Code: c01236e0 <end_buffer_io_bad+44/48> 2: 83 c4 0c addl
>$0xc,%esp
>Code: c01236e3 <end_buffer_io_bad+47/48> 5: c3 ret
>Code: c01236e4 <end_buffer_io_async+0/144> 6: 57
>pushl %edi
>Code: c01236e5 <end_buffer_io_async+1/144> 7: 56
>pushl %esi
>Code: c01236e6 <end_buffer_io_async+2/144> 8: 53
>pushl %ebx
>Code: c01236e7 <end_buffer_io_async+3/144> 9: 8b 7c 24 10 movl
>0x10(%esp,1),%edi
>Code: c01236eb <end_buffer_io_async+7/144> d: 8b 4c 24 14 movl
>0x14(%esp,1),%ecx
>Code: c01236ef <end_buffer_io_async+b/144> 11: 85 c9
>testl %ecx,%ecx
>Code: c01236f1 <end_buffer_io_async+d/144> 13: 74 00 je
>c01236f3 <end_buffer_io_async+f/144>
>
>The error message occurs about 20 seconds after the command shell comes up,
>even if no commands are issued. The filesystem appears to be fine, both
>before and after the message. Here are the details of what's booted:

I had some bug in my buffer code changes. I fixed it now.

This is a _incremental_ patch against the previous page-cache-ramdisk
fixes. NOTE: using pre1 or pre2 make no difference at all for these
issues.

It should fix the problem you reported plus some other "uptodate" fixes I
noticed now.

diff -urN 2.3.15-pre2-pagecache/fs/buffer.c 2.3.15-pre2-pagecache-devel/fs/buffer.c
--- 2.3.15-pre2-pagecache/fs/buffer.c Sun Aug 22 14:36:09 1999
+++ 2.3.15-pre2-pagecache-devel/fs/buffer.c Sun Aug 22 15:32:57 1999
@@ -793,6 +793,10 @@
repeat:
bh = get_hash_table(dev, block, size);
if (bh) {
+ /* we may have found a orhpaned-hashed buffer, and so it
+ may have a end_io handler different than the io_sync one. */
+ bh->b_end_io = end_buffer_io_sync;
+ mb();
if (!buffer_dirty(bh)) {
bh->b_flushtime = 0;
}
@@ -1492,8 +1496,14 @@
bh_old = get_hash_table(bh->b_dev,
bh->b_blocknr,
bh->b_size);
- if (!bh_old)
+ if (!bh_old || !buffer_uptodate(bh_old))
{
+ if (bh_old)
+ {
+ trash_buffer(bh_old);
+ __remove_from_queues(bh_old);
+ atomic_dec(&bh_old->b_count);
+ }
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
err = -EIO;
@@ -1676,8 +1686,14 @@
bh_old = get_hash_table(bh->b_dev,
bh->b_blocknr,
bh->b_size);
- if (!bh_old)
+ if (!bh_old || !buffer_uptodate(bh_old))
{
+ if (bh_old)
+ {
+ trash_buffer(bh_old);
+ __remove_from_queues(bh_old);
+ atomic_dec(&bh_old->b_count);
+ }
ll_rw_block(READ, 1, &bh);
wait_on_buffer(bh);
err = -EIO;
@@ -2118,22 +2134,46 @@
bh_old = get_hash_table(bh->b_dev,
bh->b_blocknr,
bh->b_size);
- if (bh_old)
+ if (bh_old && buffer_uptodate(bh_old))
{
memcpy(bh->b_data, bh_old->b_data,
bh->b_size);
+ set_bit(BH_Uptodate, &bh->b_state);
/* move the protected bit from
the old buffer to the new buffer. */
if (atomic_expose_buffer(bh_old))
atomic_protect_buffer(bh);
if (atomic_set_buffer_clean(bh_old))
+ {
+ /* the buffer will do IO
+ so it must have a valid
+ end_io handler before
+ setting it dirty. */
+ bh->b_end_io = end_buffer_io_sync;
+ /* even if to refile the buffer
+ will run a spin_lock(), here
+ is more robust to enforce
+ a SMP memory barrier by hand
+ because a buffer is writable
+ only in function of the
+ dirty bit and not in
+ function of where it's
+ placed in the lru lists. */
+ mb();
mark_buffer_dirty(bh, 0);
+ }

/* now trash the old regular buffer */
trash_buffer(bh_old);
__remove_from_queues(bh_old);
atomic_dec(&bh_old->b_count);
continue;
+ }
+ if (bh_old)
+ {
+ trash_buffer(bh_old);
+ __remove_from_queues(bh_old);
+ atomic_dec(&bh_old->b_count);
}
}
}

If you are more confortable with only one whole patch (instead of two
incremental patches) against a clean 2.3.15-pre2 you can find it here:

ftp://e-mind.com/pub/andrea/kernel-patches/pending-2.3.x/page-cache-2.3.15-pre2-2

To make the ramdisk drive working properly and to fix the other page-cache
fs-corruption bugs you only need to apply the above patch against
2.3.15-pre2. I propose it for inclusion into the next 2.3.x.

Andrea

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/