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/