Re: 2.3.42 crashes on boot (Was: [PATCH] devfs v99.11 available)

From: B. D. Elliott (bde@nwlink.com)
Date: Thu Feb 10 2000 - 08:14:17 EST


On Thu, Feb 10, 2000 at 10:19:03PM +1100, Richard Gooch wrote:
> Sergey Kubushin writes:
> > On Wed, 9 Feb 2000, Richard Gooch wrote:
> >
> > > NOTE: the devfs-patch-v99.x patches are maintenance patches for the
> > > 2.2.x production kernels. Devfs development is done against recent
> > > development kernels. Occasionally, the latest devfs patch for the
> > > development kernels may be backported to 2.2.x series, but this
> > > happens rarely.
> > >
> > > This is against 2.2.14. Highlights of this release:
> > >
> > > - Ported devfs-patch-v99.10 to kernel 2.2.14
> > >
> > > - Moved /dev/tty0 to /dev/vc/0
> >
> > It's very nice, but can somebody explain why 2.3.42 with devfs v.154
> > crashes on boot ? Initrd strikes back ?
>
> Odd. Please send me (off-list) your /etc/lilo.conf so I can see
> exactly what is being passed to the kernel.
>
> > Here is the oops:
> >
> > === Cut ===
> > ksymoops 0.7c on i686 2.3.36. Options used
> > -V (specified)
> > -K (specified)
> > -L (specified)
> > -o /lib/modules/kernel/2.3.42/ (specified)
> > -m /boot/System.map-2.3.42 (specified)
> >
> > No modules in ksyms, skipping objects
> > Unable to handle kernel NULL pointer dereference at virtual address 00000038
> > c0149ba1
> > *pde = 00104001
> > Oops: 0000
> > CPU: 0
> > EIP: 0010:[<c0149ba1>]
> > Using defaults from ksymoops -t elf32-i386 -a i386
> > EFLAGS: 00010246
> > eax: 00000038 ebx: 00000000 ecx: c02839f2 edx: c14fbe54
> > esi: 00000018 edi: c14fbe54 ebp: ffffffed esp: c14fbb00
> > ds: 0018 es: 0018 ss: 0018
> > Process swapper (pid: 1, stackpage=c14fb000)
> > Stack: 00000100 00000000 c14fbb6c c14fbd04 c0283acd c14fbe54 c14fbca8 c02a00e0
> > c0277fc8 00000000 00001000 c02839f2 00000000 c14fbb6c 00000000 00000000
> > 00000000 00000000 c14fbc4c c14fbe54 c14fbca8 00000000 00000000 00000000
> > Call Trace: [<c0110018>] [<c01081cb>] [<c010a010>]
> > Code: 39 46 20 74 2a 50 8b 46 20 50 68 c0 9e 21 c0 e8 53 52 fd ff
> >
> > >>EIP; c0149ba1 <blkdev_open+19/dc> <=====
> > Trace; c0110018 <do_int+a8/1b4>
> > Trace; c01081cb <init+5f/1e4>
> > Trace; c010a010 <kernel_thread+28/38>
> > Code; c0149ba1 <blkdev_open+19/dc>
> > 00000000 <_EIP>:
> > Code; c0149ba1 <blkdev_open+19/dc> <=====
> > 0: 39 46 20 cmp %eax,0x20(%esi) <=====
> > Code; c0149ba4 <blkdev_open+1c/dc>
> > 3: 74 2a je 2f <_EIP+0x2f> c0149bd0 <blkdev_open+48/dc>
> > Code; c0149ba6 <blkdev_open+1e/dc>
> > 5: 50 push %eax
> > Code; c0149ba7 <blkdev_open+1f/dc>
> > 6: 8b 46 20 mov 0x20(%esi),%eax
> > Code; c0149baa <blkdev_open+22/dc>
> > 9: 50 push %eax
> > Code; c0149bab <blkdev_open+23/dc>
> > a: 68 c0 9e 21 c0 push $0xc0219ec0
> > Code; c0149bb0 <blkdev_open+28/dc>
> > f: e8 53 52 fd ff call fffd5267 <_EIP+0xfffd5267> c011ee08 <printk+0/1f4>
> > === Cut ===
>
> If it crashes during boot (say mounting root), I would have expected
> mount_root() to appear in this traceback. Odd that it's not. Can you
> start sprinkling printk()'s around to figure out where blkdev_open()
> is being called from when this happens?
>
> Also, I'll need details of how you're using initrd (whether you leave
> it mounted after switching root and so on).
>
> Regards,
>
> Richard....
> Old: rgooch@atnf.csiro.au
> Current: rgooch@ras.ucalgary.ca

I don't believe that the problem described is in devfs. It was introduced
some time after 2.3.35 in the reworking of the block device interface.

With the patches below, I can boot an initrd/ramdisk system using 2.3.42
with devfs, and it appears to run properly.

PLEASE note the following:

1. There is some kind of recent breakage of ramdisk that this does not
   completely fix. The symptom is that __sometimes__ files in the page
   cache are not flushed to the ramdisk buffer cache. Sometimes it works
   correctly.

2. The patch for initrd reading/writing is a hybrid of my earlier version
   and the one from Mike Galbraith, as mine was incomplete.

3. This patch kludges out the effect of the recent "invalidate device
   buffers on the final close" that destroys ramdisks.

4. Since it is 5AM, I can't remember what else I should mention here.

========================================================================
--- linux/fs/block_dev.c.orig Sun Feb 6 01:56:39 2000
+++ linux/fs/block_dev.c Mon Feb 7 00:06:41 2000
@@ -616,7 +616,8 @@
         /* syncing will go here */
         if (kind == BDEV_FILE || kind == BDEV_FS)
                 fsync_dev(rdev);
- if (atomic_dec_and_test(&bdev->bd_openers)) {
+ if (atomic_dec_and_test(&bdev->bd_openers) &&
+ MAJOR(rdev) != RAMDISK_MAJOR) {
                 /* invalidating buffers will go here */
                 invalidate_buffers(rdev);
         }
--- linux/drivers/block/rd.c.orig Sun Feb 6 01:56:33 2000
+++ linux/drivers/block/rd.c Mon Feb 7 00:08:14 2000
@@ -217,24 +217,23 @@
         }
 
         /*
- * This has become somewhat more complicated with the addition of
- * the page cache. The problem is that in some cases the furnished
+ * There is a problem here in that in some cases the furnished
          * buffer is "real", i.e., part of the existing ramdisk, while in
          * others it is "unreal", e.g., part of a page. In the first case
          * not much needs to be done, while in the second, some kind of
          * transfer is needed.
           *
- * The two cases are distinguished here by checking whether the
- * real buffer is already in the buffer cache, and whether it is
- * the same as the one supplied.
+ * The two cases are distinguished by checking whether the real
+ * buffer is already in the buffer cache, and whether it matches
+ * the one supplied.
          *
          * There are three cases with read/write to consider:
          *
- * 1. Supplied buffer matched one in the buffer cache:
- * Read - Clear the buffer, as it wasn't already valid.
+ * 1. Supplied buffer matched the one in the buffer cache:
+ * Read - Clear the buffer, as it wasn't previously valid.
          * Write - Mark the buffer as "Protected".
          *
- * 2. Supplied buffer mismatched one in the buffer cache:
+ * 2. Supplied buffer mismatched the one in the buffer cache:
          * Read - Copy the data from the buffer cache entry.
          * Write - Copy the data to the buffer cache entry.
          *
@@ -243,19 +242,13 @@
          * one.
          * Write - Create a real buffer, copy the data to it, and mark
          * it as "Protected".
- *
- * NOTE: There seems to be some schizophrenia here - the logic
- * using "len" seems to assume arbitrary request lengths, while
- * the "protect" logic assumes a single buffer cache entry.
- * This seems to be left over from the ancient contiguous ramdisk
- * logic.
          */
 
         sbh = CURRENT->bh;
         rbh = get_hash_table(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
         if (sbh == rbh) {
                 if (CURRENT->cmd == READ)
- memset(CURRENT->buffer, 1, len);
+ memset(CURRENT->buffer, 0, len);
         } else if (rbh) {
                 if (CURRENT->cmd == READ)
                         memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size);
@@ -263,14 +256,18 @@
                         memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size);
         } else { /* !rbh */
                 if (CURRENT->cmd == READ)
- memset(sbh->b_data, 2, len);
+ memset(sbh->b_data, 0, len);
                 else {
                         rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
                         if (rbh)
                                 memcpy(rbh->b_data, CURRENT->buffer,
                                     rbh->b_size);
- else
- BUG(); /* No buffer, what to do here? */
+ else {
+ printk(KERN_ERR "RAMDISK: "
+ "could not allocate buffer\n");
+ end_request(0);
+ goto repeat;
+ }
                 }
         }
         if (rbh) {
@@ -342,17 +339,8 @@
 
 
 static struct file_operations initrd_fops = {
- NULL, /* lseek */
- initrd_read, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* open */
- NULL, /* flush */
- initrd_release, /* release */
- NULL /* fsync */
+ release: initrd_release,
+ read: initrd_read,
 };
 
 #endif
@@ -591,19 +579,21 @@
         memset(&infile, 0, sizeof(infile));
         memset(&inode, 0, sizeof(inode));
         memset(&in_dentry, 0, sizeof(in_dentry));
- inode.i_rdev = device;
+ init_special_inode(&inode, S_IFBLK | S_IRWXU, device);
         init_waitqueue_head(&inode.i_wait);
         infile.f_mode = 1; /* read only */
         infile.f_dentry = &in_dentry;
+ infile.f_op = &initrd_fops;
         in_dentry.d_inode = &inode;
 
         memset(&outfile, 0, sizeof(outfile));
         memset(&out_inode, 0, sizeof(out_inode));
         memset(&out_dentry, 0, sizeof(out_dentry));
- out_inode.i_rdev = ram_device;
+ init_special_inode(&out_inode, S_IFBLK | S_IRWXU, ram_device);
         init_waitqueue_head(&out_inode.i_wait);
         outfile.f_mode = 3; /* read/write */
         outfile.f_dentry = &out_dentry;
+ outfile.f_op = &def_blk_fops;
         out_dentry.d_inode = &out_inode;
 
         if (blkdev_open(&inode, &infile) != 0) return;
========================================================================

-- 
B. D. Elliott   bde@nwlink.com   (Seattle)

- 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/



This archive was generated by hypermail 2b29 : Tue Feb 15 2000 - 21:00:17 EST