From: Olaf Hering <olh@suse.de>

initramfs can not be used in current 2.6 kernels, the files will never be
executed because prepare_namespace doesn't care about them.  The only way to
workaround that limitation is a root=0:0 cmdline option to force rootfs as
root filesystem.  This will break further booting because rootfs is not the
final root filesystem.

This patch checks for the presence of /sbin/init which comes from the cpio
archive (and thats the only way to store files into the rootfs).  This
binary/script has to do all the work of prepare_namespace().  One can specify
a different binary from the cpio archive via the kinit= option.  It does not
break current setups because initrd will not touch rootfs.

Any why would one want to do that?  After some thought, only 2 reasons come
to mind: the cpio archive can be built as user (no loop mount required), and
it should simplify migration to 2.7 (I hope the stuff behind
prepare_namespace will disappear).



---

 Documentation/early-userspace/README |   28 ++++++++++++++++++++++++++++
 Documentation/kernel-parameters.txt  |    3 +++
 init/main.c                          |   17 +++++++++++++++++
 3 files changed, 48 insertions(+)

diff -puN Documentation/early-userspace/README~initramfs-kinit_command Documentation/early-userspace/README
--- 25/Documentation/early-userspace/README~initramfs-kinit_command	2004-02-20 23:37:11.000000000 -0800
+++ 25-akpm/Documentation/early-userspace/README	2004-02-20 23:37:11.000000000 -0800
@@ -72,4 +72,32 @@ For questions and help, you can sign up 
 mailing list at http://www.zytor.com/mailman/listinfo/klibc
 
 
+How does it work?
+=================
+
+The kernel has currently 3 ways to mount the root filesystem:
+a) all required device and filesystem drivers compiled into the
+   kernel, no initrd. init/main.c:init() will call prepare_namespace()
+   to mount the final root filesystem, based on the root= option
+   and optional init= to run some other init binary than listed
+   at the end of init/main.c:init().
+b) some device and filesystem drivers built as modules and stored in
+   an initrd. The initrd must contain a binary '/linuxrc' which is
+   supposed to load these driver modules. It is also possible to
+   mount the final root filesystem via linuxrc and use the pivot_root
+   syscall. The initrd is mounted and executed via prepare_namespace().
+c) using initramfs. The call to prepare_namespace() must be skipped. This
+   means that a binary must do all the work. Said binary can be stored
+   into initramfs either via modifying usr/gen_init_cpio.c or via the new
+   initrd format, an cpio archive. It must be called "/sbin/init".
+   A different binary can be specified with the kinit= boot option.
+   This binary is responsible to do all the things prepare_namespace()
+   would do.
+   To remain backwards compatibility, the kinit binary will only run if
+   it comes via an initramfs cpio archive, or if the kinit= option is
+   specified. If this is not the case, init/main.c:init() will run
+   prepare_namespace() to mount the final root and exec one of the
+   predefined init binaries.
+
+
 Bryan O'Sullivan <bos@serpentine.com>
diff -puN Documentation/kernel-parameters.txt~initramfs-kinit_command Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~initramfs-kinit_command	2004-02-20 23:37:11.000000000 -0800
+++ 25-akpm/Documentation/kernel-parameters.txt	2004-02-20 23:37:11.000000000 -0800
@@ -499,6 +499,9 @@ running once the system is up.
 
 	keepinitrd	[HW,ARM]
 
+	kinit=		Specify the path to the init executable to replace
+			prepare_namespace() (for initramfs archives)
+
 	l2cr=		[PPC]
 
 	lapic		[IA-32,APIC] Enable the local APIC even if BIOS disabled it.
diff -puN init/main.c~initramfs-kinit_command init/main.c
--- 25/init/main.c~initramfs-kinit_command	2004-02-20 23:37:11.000000000 -0800
+++ 25-akpm/init/main.c	2004-02-20 23:37:11.000000000 -0800
@@ -299,6 +299,15 @@ static int __init init_setup(char *str)
 }
 __setup("init=", init_setup);
 
+static char *kinit_command;
+
+static int __init kinit_setup(char *str)
+{
+	kinit_command = str;
+	return 1;
+}
+__setup("kinit=", kinit_setup);
+
 extern void setup_arch(char **);
 extern void cpu_idle(void);
 
@@ -534,6 +543,7 @@ static void __init do_initcalls(void)
 	flush_scheduled_work();
 }
 
+asmlinkage long sys_access(const char __user * filename, int mode);
 /*
  * Ok, the machine is now initialized. None of the devices
  * have been touched yet, but the CPU subsystem is up and
@@ -597,6 +607,13 @@ static int init(void * unused)
 	sched_init_smp();
 	do_basic_setup();
 
+	/*
+	 * check if there is an early userspace init, if yes
+	 * let it do all the work
+	 */
+	if (kinit_command || sys_access("/sbin/init", 0) == 0)
+		execute_command = kinit_command ? kinit_command : 0;
+	else
 	prepare_namespace();
 
 	/*

_