Re: Kernels do not compile anymore

B. D. Elliott (bde@nwlink.com)
Tue, 14 Dec 1999 00:04:10 -0800


On Mon, Dec 13, 1999 at 08:18:03PM -0500, Richard B. Johnson wrote:
> On Tue, 14 Dec 1999, Alan Cox wrote:
>
> > > You just noticed this trend ??? ALL 2.1.x and 2.2.x kernel will not compile
> > > with all modules turned "on" (Alan's versions are better but still can not
> > > be compiled "out of box").
> >
> > 2.2.14 should be very very close to compile with any combination except
> > a few we know are near unfixable. Arjan did a lot of work and fixed an
> > amazing number of these problems.
> >
>
> I can contribute some work on company time on a "new" kernel if initrd
> would compile. It doesn't have to "work". It only has to be "reconnected"
> enough so I have a clue as to how its supposed to work. Given that, I
> should be able to get it to work.
>
> The company project I am working on uses Linux in an embeded system.
> It boots from NVRAM (proprietary on-board, but proprietary only in
> that you can't buy a NVRAM board and plug it into your PC). However,
> I'll give anybody a Linux driver if they want to roll their own
> NVRAM. This NVRAM, 32 pages of 64k, becomes a boot drive during
> POST and boots Linux onto a permanent RAM disk containing the
> application which replaces init. This 'init' does everything
> to configure the network, GPIB, etc. Then launches several
> servers. Basically, the whole thing does communications and
> control of a VXI bus.
>
> So, if somebody could fix up a new kernel so initrd would compile,
> I could help find/repair bugs. Otherwise, I will have to stick
> with 2.3.13, the last that worked.

The patches below work for me in 2.3.{30,31}. I can use the kernel both
with an initrd in a rescue floppy, and without for normal booting.

I separate the ramdisk patch here because someone else is supposedly
preparing a better fix, although I haven't seen anything recently.

Some comments:

I haven't totally removed the "collision" test from main.c, as I don't
understand why it was ever there. By its nature, initrd is an
architecture-related feature, and this test should be elsewhere (note
the code in setup.c). In addition, it is unclear why the kernel doesn't
simply panic if this test fails, as it is quite unlikely that anything
useful can be done without the initrd.

I would guess that booting failure of initrd-enabled kernels without any
initrd is in calling reserve_bootmem() with a zero-length area. In any
case, if you don't have an initrd, there is no reason to call it.

I am not satisfied with the BUG() call in the rd.c logic, although it is
not clear what should be done, as there is typically no fallback possible
when running with ramdisk.

=======================================================================
--- linux/init/main.c.orig Wed Dec 8 23:20:25 1999
+++ linux/init/main.c Wed Dec 8 23:22:27 1999
@@ -499,6 +500,7 @@
kmem_cache_init();
sti();
calibrate_delay();
+#if 0000
#ifdef CONFIG_BLK_DEV_INITRD
// FIXME, use the bootmem.h interface.
if (initrd_start && !initrd_below_start_ok && initrd_start < memory_start) {
@@ -507,6 +509,7 @@
initrd_start = 0;
}
#endif
+#endif /* 0000 */
mem_init();
kmem_cache_sizes_init();
#ifdef CONFIG_PROC_FS
--- linux/arch/i386/kernel/setup.c.orig Tue Dec 7 23:01:40 1999
+++ linux/arch/i386/kernel/setup.c Wed Dec 8 23:22:27 1999
@@ -706,7 +706,7 @@
#endif

#ifdef CONFIG_BLK_DEV_INITRD
- if (LOADER_TYPE) {
+ if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) {
reserve_bootmem(INITRD_START, INITRD_SIZE);
initrd_start =
=======================================================================

=======================================================================
--- linux/drivers/block/rd.c.orig Wed Dec 8 23:20:19 1999
+++ linux/drivers/block/rd.c Wed Dec 8 23:22:27 1999
@@ -189,6 +189,8 @@
{
unsigned int minor;
unsigned long offset, len;
+ struct buffer_head *rbh;
+ struct buffer_head *sbh;

repeat:
INIT_REQUEST;
@@ -215,16 +217,66 @@
}

/*
- * If we're reading, fill the buffer with 0's. This is okay since
- * we're using protected buffers which should never get freed...
+ * This has become somewhat more complicated with the addition of
+ * the page cache. The problem is 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.
*
- * If we're writing, we protect the buffer.
- */
-
- if (CURRENT->cmd == READ)
- memset(CURRENT->buffer, 0, len);
- else
- set_bit(BH_Protected, &CURRENT->bh->b_state);
+ * 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.
+ * Write - Mark the buffer as "Protected".
+ *
+ * 2. Supplied buffer mismatched one in the buffer cache:
+ * Read - Copy the data from the buffer cache entry.
+ * Write - Copy the data to the buffer cache entry.
+ *
+ * 3 No buffer cache entry existed:
+ * Read - Clear the supplied buffer, but do not create a real
+ * 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, 0, len);
+ } else if (rbh) {
+ if (CURRENT->cmd == READ)
+ memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size);
+ else
+ memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size);
+ } else { /* !rbh */
+ if (CURRENT->cmd == READ)
+ 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? */
+ }
+ }
+ if (rbh) {
+ set_bit(BH_Protected, &CURRENT->bh->b_state);
+ brelse(rbh);
+ }

end_request(1);
goto repeat;
=======================================================================

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