RE: [BUG] initrd broken in 2.3.51->99pre3

From: Mike Galbraith (mikeg@weiden.de)
Date: Thu Apr 06 2000 - 09:13:57 EST


On Mon, 3 Apr 2000, Mike Klar wrote:

> Mike Galbraith wrote:
>
> > On Sun, 2 Apr 2000, Mike Klar wrote:
> >
> > > .. I ran into the same
> > > problem while testing initrd recently, and the kernel decided
> > not to load
> > > the initrd image because initrd start address was >= top of
> > memory. Same
> > > line of code oopsed. In fact, loading the kernel with
> > root=/dev/ram without
> > > providing an initrd at all did the same thing.
> >
> > Greetings,
> >
> > Can you show me how you generated such an initrd load failure?
>
> Sure. I probably should have at least mentioned what I was using as a
> bootloader... 8^)
>
> These tests were done on a K6-2/450 system with 196MB DRAM, using
> 2.3.99-pre4-2 (.config below), but I expect the behavior has been similar
> for the last few versions. The ramdisk.img referenced below was the rescue
> root image from some distribution or other, probably SuSE 6.1, it does not
> have a linuxrc on it.
>
> initrd load refusal happened using linload from DOS, with a 4MB
> _uncompressed_ initrd image, while limiting the memory size to 12MB:
>
> linload zimage initrd=radisk.img root=/dev/ram mem=12MB
>
> Apparently, linload decided to put the initrd image starting at 12MB, which
> the kernel didn't take too kindly to, since as far as it knew, that was top
> of memory. Interestingly enough, the same command with the same ramdisk
> image, but compressed, seemed to put the initrd where the kernel could find
> it (but then it runs into a different problem later on, with bdflush).

The problem appears to be that when passing MEM=foo, that the bootloader
may set it up so that the initrd exactly fits (loadlin does).. ergo the
check in arch/i386/kernel/setup.c fails no matter what MEM is set to.

Below are two patches. The first fixes the above, and prevents oops
(fwtw) on ramdisk load failure. The second is a proposed fix for the
//FIXME in init/main.c and also removes a __init/__setup pair which
is also in rd.c.

Here, with MEM=12M, I have too little ram left to load a 3.7mb initrd
(uncompressed) because it basically ooms the box.. but that's another
story. It seems to be fine for anything larger.

        -Mike

Diff1:
--- linux-2.3.99pre4-4/arch/i386/kernel/setup.c.org Wed Apr 5 09:12:00 2000
+++ linux-2.3.99pre4-4/arch/i386/kernel/setup.c Thu Apr 6 15:21:44 2000
@@ -727,7 +727,7 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
         if (LOADER_TYPE && INITRD_START) {
- if (INITRD_START + INITRD_SIZE < (max_low_pfn << PAGE_SHIFT)) {
+ if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
                         reserve_bootmem(INITRD_START, INITRD_SIZE);
                         initrd_start =
                                 INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
--- linux-2.3.99pre4-4/drivers/block/rd.c.org Sat Mar 25 10:24:45 2000
+++ linux-2.3.99pre4-4/drivers/block/rd.c Thu Apr 6 15:21:44 2000
@@ -326,7 +326,7 @@
         }
 #endif
 
- if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
+ if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS || !inode->i_bdev)
                 return -ENXIO;
 
         /*

Diff2:
--- linux-2.3.99pre4-4/init/main.c.org Sat Mar 25 10:24:55 2000
+++ linux-2.3.99pre4-4/init/main.c Thu Apr 6 15:23:46 2000
@@ -510,16 +510,14 @@
         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) {
+ if (initrd_start && !initrd_below_start_ok &&
+ initrd_start < min_low_pfn << PAGE_SHIFT) {
                 printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
- "disabling it.\n",initrd_start,memory_start);
+ "disabling it.\n",initrd_start,min_low_pfn << PAGE_SHIFT);
                 initrd_start = 0;
         }
 #endif
-#endif /* 0000 */
         mem_init();
         kmem_cache_sizes_init();
 #ifdef CONFIG_PROC_FS
@@ -572,14 +570,6 @@
         return execve(shell, argv, envp_init);
 }
 
-static int __init no_initrd(char *s)
-{
- mount_initrd = 0;
- return 1;
-}
-
-__setup("noinitrd", no_initrd);
-
 #endif
 
 struct task_struct *child_reaper = &init_task;
--- linux-2.3.99pre4-4/mm/bootmem.c.org Sat Mar 25 10:23:43 2000
+++ linux-2.3.99pre4-4/mm/bootmem.c Thu Apr 6 15:21:44 2000
@@ -24,6 +24,7 @@
  * true for the boot process anyway)
  */
 unsigned long max_low_pfn;
+unsigned long min_low_pfn;
 
 /* return the number of _pages_ that will be allocated for the boot bitmap */
 unsigned long __init bootmem_bootmap_pages (unsigned long pages)
@@ -282,6 +283,7 @@
 unsigned long __init init_bootmem (unsigned long start, unsigned long pages)
 {
         max_low_pfn = pages;
+ min_low_pfn = start;
         return(init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages));
 }
 
--- linux-2.3.99pre4-4/include/linux/bootmem.h.org Sun Mar 26 09:06:37 2000
+++ linux-2.3.99pre4-4/include/linux/bootmem.h Thu Apr 6 15:21:44 2000
@@ -14,6 +14,7 @@
  */
 
 extern unsigned long max_low_pfn;
+extern unsigned long min_low_pfn;
 
 /*
  * node_bootmem_map is a map pointer - the bits represent all physical

-
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 : Fri Apr 07 2000 - 21:00:16 EST