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

Reply via email to