/ on ramfs, possible? [yes! - patch included]
Subsystems (3)
Hi,
I read your post and I think I have just what you're looking for. I've attached a patch that allows you to mount root as ramfs and populate it directly from a tar archive (specified just like an initrd image, but without having to deal with a fixed-size initrd or pivot_root at all.) This was based on some earlier work from the Linux router project that I rewrote and ported to 2.2 and 2.4 a few months ago. I didn't post it to the list since I figured it was too late for 2.4.0, but if you're interested, here it is.
Here's the Configure.help description:
CONFIG_RAMFS_ROOT
Allow the kernel to mount a ramfs namespace as the root filesystem or as a pre-root filesystem for running a /linuxrc script (similar to how initial RAM disk (initrd) support works.)
Since ramfs has no physical or virtual block device to provide its data as an initrd image would, you must provide a standard tar
format
archive to be extracted into the empty ramfs root filesystem.
Currently
this tar archive may *not* be compressed (i.e., tar.gz style); if compression is desired, use a bootloader with automatic gunzip
support
such as GRUB.
To specify the tar archive used to build the root filesystem, use
the
initrd=<filename> kernel command line option (except with a tar
archive
instead of a real ext2/minix/romfs filesystem image.)
To mount the tar archive as the actual root filesystem, specify the same initrd=<filename> option above and also include
"root=/dev/ramfs"
in the kernel command line.
You may enable both this option and initrd support; however, if a tar archive is detected instead of an initrd-supported filesystem image, this option will override initrd support.
Note: Some versions of GNU tar create invalid archives that cannot be extracted by the kernel. In particular, tar may add a file to an archive without previously adding its containing directory. If your ramfs archive does not mount correctly because of this, try creating it in another way or with another file order.
(Patch should apply to 2.4.0-test10-pre6 on i386. It needs to be updated for other architectures, mostly in setup.c though.)
I hope this is helpful. Maybe the maintainers would like to comment on this too (i.e., might it be considered for 2.4.1, etc.?)
- Matt Yourst
-------------------------------------------------------------
Matt T. Yourst Massachusetts Institute of Technology
[email protected] 617.225.7690
513 French House - 476 Memorial Drive - Cambridge, MA 02136
-------------------------------------------------------------
fs/ramfs/Makefile renamed from fs/ramfs/Makefile.orig +3 -0
@@ -5,6 +5,9 @@ O_TARGET := ramfs.o O_OBJS := inode.o +ifeq ($(CONFIG_RAMFS_ROOT),y) + O_OBJS += untar.o +endif M_OBJS := $(O_TARGET)
fs/ramfs/untar.c renamed from fs/ramfs/untar.c.empty +307 -0
307 lines not on this page · raw message
fs/Config.in renamed from fs/Config.in.orig +1 -0
@@ -40,6 +40,7 @@ fi tristate 'Compressed ROM file system support' CONFIG_CRAMFS tristate 'Simple RAM-based file system support' CONFIG_RAMFS +dep_bool ' RAM-based root filesystem from tar archive' CONFIG_RAMFS_ROOT $CONFIG_RAMFS tristate 'ISO 9660 CDROM file system support' CONFIG_ISO9660_FS dep_mbool ' Microsoft Joliet CDROM extensions' CONFIG_JOLIET $CONFIG_ISO9660_FS
arch/i386/mm/init.c renamed from arch/i386/mm/init.c.orig +1 -1
@@ -669,7 +669,7 @@printk ("Freeing unused kernel memory: %dk freed\n" , (&__init_end - &__init_begin) >>10 ); } -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))void free_initrd_mem (unsigned long start,unsigned long end) {if (start < end)
arch/i386/kernel/setup.c renamed from arch/i386/kernel/setup.c.orig +18 -1
@@ -140,6 +140,16 @@extern int rd_image_start;/* starting block # of image */ #endif +#if (defined(CONFIG_RAMFS_ROOT ) || defined(CONFIG_BLK_DEV_INITRD )) +unsigned long initrd_start, initrd_end; +int mount_initrd =1 ;/* zero if initrd should not be mounted */ +int initrd_below_start_ok; +#endif + +#ifdef CONFIG_RAMFS_ROOT +extern int ramfs_check_root (void ); +#endif +extern int root_mountflags;extern char _text, _etext, _edata, _end;extern unsigned long cpu_khz;
@@ -900,7 +910,7 @@#ifdef CONFIG_X86_LOCAL_APIC init_apic_mappings ();#endif -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))if (LOADER_TYPE &&INITRD_START ) {if (INITRD_START +INITRD_SIZE <= (max_low_pfn <<PAGE_SHIFT )) {reserve_bootmem (INITRD_START ,INITRD_SIZE );
@@ -916,6 +926,13 @@ initrd_start = 0; } } +#ifdef CONFIG_RAMFS_ROOT +/* +* Give ramfs a chance to take control before initrd +* doesn't recognize the tar format and frees the memory +*/ +ramfs_check_root (); +#endif #endif /*
init/main.c renamed from init/main.c.orig +21 -11
@@ -123,10 +123,14 @@int rows, cols; -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))kdev_t real_root_dev;#endif +#ifdef CONFIG_RAMFS_ROOT +extern int ramfs_check_root (void ); +#endif +int root_mountflags =MS_RDONLY ;char *execute_command;char root_device_name[64 ];
@@ -144,12 +148,12 @@__setup ("profile=" , profile_setup); -static struct dev_name_struct {const char *name;const int num; } root_dev_names[]__initdata = { {"nfs" ,0x00ff }, + {"ramfs" ,0x00fe }, {"hda" ,0x0300 }, {"hdb" ,0x0340 }, {"hdc" ,0x1600 },
@@ -542,7 +546,7 @@kmem_cache_init ();sti ();calibrate_delay (); -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))if (initrd_start && !initrd_below_start_ok && initrd_start < min_low_pfn <<PAGE_SHIFT ) { printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
@@ -590,7 +594,7 @@cpu_idle (); } -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))static int do_linuxrc (void * shell) {static char *argv[] = {"linuxrc" ,NULL , };
@@ -627,8 +631,9 @@*/ static void __init do_basic_setup (void ) { -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))int real_root_mountflags; +int init_ramfs;#endif /*
@@ -692,11 +697,16 @@/* Networking initialization needs a process context */ sock_init (); -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT )) real_root_dev =ROOT_DEV ; real_root_mountflags = root_mountflags; +#ifdef CONFIG_RAMFS_ROOT + init_ramfs =ramfs_check_root (); +#else + init_ramfs =0 ; +#endif if (initrd_start && mount_initrd) root_mountflags &= ~MS_RDONLY ; -else mount_initrd =0 ; +else mount_initrd =0 ;#endif do_initcalls ();
@@ -715,13 +725,13 @@mount_devfs_fs (); -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT )) root_mountflags = real_root_mountflags; -if (mount_initrd &&ROOT_DEV != real_root_dev - &&MAJOR (ROOT_DEV ) ==RAMDISK_MAJOR &&MINOR (ROOT_DEV ) ==0 ) { +if ((mount_initrd &&ROOT_DEV != real_root_dev + &&MAJOR (ROOT_DEV ) ==RAMDISK_MAJOR &&MINOR (ROOT_DEV ) ==0 ) + || init_ramfs) {int error;int i, pid; - pid =kernel_thread (do_linuxrc,"/linuxrc" ,SIGCHLD );if (pid>0 )while (pid !=wait (&i));
drivers/block/rd.c renamed from drivers/block/rd.c.orig +4 -3
@@ -128,9 +128,10 @@int rd_prompt =1 ;/* 1 = prompt for RAM disk, 0 = don't prompt */ int rd_image_start;/* starting block # of image */ #ifdef CONFIG_BLK_DEV_INITRD -unsigned long initrd_start, initrd_end; -int mount_initrd =1 ;/* zero if initrd should not be mounted */ -int initrd_below_start_ok; +/* These three are now in arch/.../setup.c: */ +extern unsigned long initrd_start, initrd_end; +extern int mount_initrd;/* zero if initrd should not be mounted */ +extern int initrd_below_start_ok;static int __init no_initrd (char *str) {
fs/super.c renamed from fs/super.c.orig +34 -4
@@ -36,6 +36,7 @@#include <linux/nfs_fs.h> #include <linux/nfs_fs_sb.h> #include <linux/nfs_mount.h> +#include <linux/blk.h> #include <linux/kmod.h> #define __NO_VERSION__
@@ -53,6 +54,11 @@extern int root_mountflags; +#ifdef CONFIG_RAMFS_ROOT +extern int ramfs_untar (char * start,char * end); +extern int ramfs_check_root (void ); +#endif +static int do_remount_sb (struct super_block *sb,int flags,char * data);/* this is initialized in init/main.c */
@@ -1470,10 +1476,31 @@void *handle;char path[64 ];int path_start =-1 ; +void *data; +int using_ramfs =1 ; + +#ifdef CONFIG_RAMFS_ROOT +if ((!ramfs_check_root ()) && (ROOT_DEV !=MKDEV (UNNAMED_MAJOR ,0xfe ))) + goto skip_ramfs; + fs_type =get_fs_type ("ramfs" ); +if (!fs_type) + goto no_ramfs; +ROOT_DEV =get_unnamed_dev (); +if (!ROOT_DEV ) + goto no_anon_ramfs; + sb =read_super (ROOT_DEV ,NULL , fs_type,0 , initrd_start,1 ); +if (sb) + goto mount_it; +no_anon_ramfs: +put_filesystem (fs_type); +no_ramfs: +panic (KERN_ERR "VFS: Unable to mount root ramfs.\n" ); +skip_ramfs: + using_ramfs =0 ; +#endif #ifdef CONFIG_ROOT_NFS -void *data; -if (MAJOR (ROOT_DEV ) !=UNNAMED_MAJOR ) +if (ROOT_DEV !=MKDEV (UNNAMED_MAJOR ,0xff )) goto skip_nfs; fs_type =get_fs_type ("nfs" );if (!fs_type)
@@ -1613,6 +1640,10 @@set_fs_pwd (current->fs, vfsmnt, sb->s_root);if (bdev)bdput (bdev);/* sb holds a reference */ +#ifdef CONFIG_RAMFS_ROOT +if (using_ramfs) +ramfs_untar ((char *)initrd_start, (char *)initrd_end); +#endif return ; }panic ("VFS: add_vfsmnt failed for root fs" );
@@ -1746,8 +1777,7 @@ goto out2; } - -#ifdef CONFIG_BLK_DEV_INITRD +#if (defined(CONFIG_BLK_DEV_INITRD ) || defined(CONFIG_RAMFS_ROOT ))int __init change_root (kdev_t new_root_dev,const char *put_old) {
Documentation/Configure.help renamed from Documentation/Configure.help.old +31 -0
@@ -10826,6 +10826,37 @@ say M here and read Documentation/modules.txt. The module will be called ramfs.o. +RAM-based root filesystem from tar archive +CONFIG_RAMFS_ROOT + Allow the kernel to mount a ramfs namespace as the root filesystem + or as a pre-root filesystem for running a /linuxrc script (similar + to how initial RAM disk (initrd) support works.) + + Since ramfs has no physical or virtual block device to provide its + data as an initrd image would, you must provide a standard tar format + archive to be extracted into the empty ramfs root filesystem. Currently + this tar archive may *not* be compressed (i.e., tar.gz style); if + compression is desired, use a bootloader with automatic gunzip support + such as GRUB. + + To specify the tar archive used to build the root filesystem, use the + initrd=<filename> kernel command line option (except with a tar archive + instead of a real ext2/minix/romfs filesystem image.) + + To mount the tar archive as the actual root filesystem, specify the + same initrd=<filename> option above and also include "root=/dev/ramfs" + in the kernel command line. + + You may enable both this option and initrd support; however, if a + tar archive is detected instead of an initrd-supported filesystem + image, this option will override initrd support. + + Note: Some versions of GNU tar create invalid archives that cannot + be extracted by the kernel. In particular, tar may add a file to an + archive without previously adding its containing directory. If your + ramfs archive does not mount correctly because of this, try creating + it in another way or with another file order. + ISO 9660 CDROM file system support CONFIG_ISO9660_FS This is the standard file system used on CDROMs. It was previously
CREDITS renamed from CREDITS.old +7 -0
@@ -2928,6 +2928,13 @@ S: Alexandria, Virginia 22304 S: USA +N: Matt Yourst +E: [email protected] +D: ramfs root filesystem support +S: 476 Memorial Drive +S: Cambridge, MA 02139 +S: USA + N: Niibe Yutaka E: [email protected] D: PLIP driver