aboutsummaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2003-10-15 17:29:46 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-10-15 17:29:46 -0700
commit0af6568743dd65469d9bb21794c9511feef055ed (patch)
tree2c13ae5d76bf9ac19b5f51c6e1576cd43a24100d /init
parent01d259fe61c43fe659b9e94d098288c50bdc6c61 (diff)
downloadhistory-0af6568743dd65469d9bb21794c9511feef055ed.tar.gz
[PATCH] drivers/block/initrd.c removal
From: viro@parcelfarce.linux.theplanet.co.uk * drivers/block/initrd.c gone * chunk of memory where the current tree would look for intird image is checked for being a valid initramfs image first; then, it is either unpacked (in addition to normal built-in image) or, if it wasn't a valid image, copied into a regular file on rootfs called /dev/initrd. Then memory is freed. Result: a) we can put initramfs image in place of initrd one and kernel will DTRT. b) initrd images still work as usual; code that shoves the thing to ramdisk, etc. doesn't care whether it reads from a block device or regular file. c) initrd.c is gone, so is fake block device and a lot of irregularities with it. It has been in -mm for almost two weeks with no reported problems.
Diffstat (limited to 'init')
-rw-r--r--init/do_mounts_initrd.c28
-rw-r--r--init/initramfs.c103
2 files changed, 90 insertions, 41 deletions
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index a800891d21398e..9a0ab579ae4fee 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -9,6 +9,8 @@
#include "do_mounts.h"
+unsigned long initrd_start, initrd_end;
+int initrd_below_start_ok;
unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
static int __initdata old_fd, root_fd;
static int __initdata mount_initrd = 1;
@@ -99,18 +101,20 @@ static void __init handle_initrd(void)
int __init initrd_load(void)
{
- if (!mount_initrd)
- return 0;
-
- create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, 0), NULL);
- create_dev("/dev/initrd", MKDEV(RAMDISK_MAJOR, INITRD_MINOR), NULL);
- /* Load the initrd data into /dev/ram0. Execute it as initrd unless
- * /dev/ram0 is supposed to be our actual root device, in
- * that case the ram disk is just set up here, and gets
- * mounted in the normal path. */
- if (rd_load_image("/dev/initrd") && ROOT_DEV != Root_RAM0) {
- handle_initrd();
- return 1;
+ if (mount_initrd) {
+ create_dev("/dev/ram", Root_RAM0, NULL);
+ /*
+ * Load the initrd data into /dev/ram0. Execute it as initrd
+ * unless /dev/ram0 is supposed to be our actual root device,
+ * in that case the ram disk is just set up here, and gets
+ * mounted in the normal path.
+ */
+ if (rd_load_image("/dev/initrd") && ROOT_DEV != Root_RAM0) {
+ sys_unlink("/dev/initrd");
+ handle_initrd();
+ return 1;
+ }
}
+ sys_unlink("/dev/initrd");
return 0;
}
diff --git a/init/initramfs.c b/init/initramfs.c
index 5a9f5b3b05f7ae..42eda038009f77 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -8,9 +8,11 @@
#include <linux/delay.h>
#include <linux/string.h>
+static __initdata char *message;
static void __init error(char *x)
{
- panic("populate_root: %s\n", x);
+ if (!message)
+ message = x;
}
static void __init *malloc(int size)
@@ -63,7 +65,7 @@ static char __init *find_link(int major, int minor, int ino, char *name)
}
q = (struct hash *)malloc(sizeof(struct hash));
if (!q)
- error("can't allocate link hash entry");
+ panic("can't allocate link hash entry");
q->ino = ino;
q->minor = minor;
q->major = major;
@@ -119,7 +121,7 @@ static void __init parse_header(char *s)
/* FSM */
-enum state {
+static __initdata enum state {
Start,
Collect,
GotHeader,
@@ -130,9 +132,11 @@ enum state {
Reset
} state, next_state;
-char *victim;
-unsigned count;
-loff_t this_header, next_header;
+static __initdata char *victim;
+static __initdata unsigned count;
+static __initdata loff_t this_header, next_header;
+
+static __initdata int dry_run;
static inline void eat(unsigned n)
{
@@ -185,23 +189,30 @@ static int __init do_collect(void)
static int __init do_header(void)
{
+ if (memcmp(collected, "070701", 6)) {
+ error("no cpio magic");
+ return 1;
+ }
parse_header(collected);
next_header = this_header + N_ALIGN(name_len) + body_len;
next_header = (next_header + 3) & ~3;
+ if (dry_run) {
+ read_into(name_buf, N_ALIGN(name_len), GotName);
+ return 0;
+ }
+ state = SkipIt;
if (name_len <= 0 || name_len > PATH_MAX)
- state = SkipIt;
- else if (S_ISLNK(mode)) {
+ return 0;
+ if (S_ISLNK(mode)) {
if (body_len > PATH_MAX)
- state = SkipIt;
- else {
- collect = collected = symlink_buf;
- remains = N_ALIGN(name_len) + body_len;
- next_state = GotSymlink;
- state = Collect;
- }
- } else if (body_len && !S_ISREG(mode))
- state = SkipIt;
- else
+ return 0;
+ collect = collected = symlink_buf;
+ remains = N_ALIGN(name_len) + body_len;
+ next_state = GotSymlink;
+ state = Collect;
+ return 0;
+ }
+ if (S_ISREG(mode) || !body_len)
read_into(name_buf, N_ALIGN(name_len), GotName);
return 0;
}
@@ -248,6 +259,8 @@ static int __init do_name(void)
next_state = Reset;
return 0;
}
+ if (dry_run)
+ return 0;
if (S_ISREG(mode)) {
if (maybe_link() >= 0) {
wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
@@ -268,8 +281,7 @@ static int __init do_name(void)
sys_chown(collected, uid, gid);
sys_chmod(collected, mode);
}
- } else
- panic("populate_root: bogus mode: %o\n", mode);
+ }
return 0;
}
@@ -323,13 +335,14 @@ static int __init write_buffer(char *buf, unsigned len)
static void __init flush_buffer(char *buf, unsigned len)
{
int written;
- while ((written = write_buffer(buf, len)) < len) {
+ if (message)
+ return;
+ while ((written = write_buffer(buf, len)) < len && !message) {
char c = buf[written];
if (c == '0') {
buf += written;
len -= written;
state = Start;
- continue;
} else
error("junk in compressed archive");
}
@@ -408,18 +421,20 @@ static void __init flush_window(void)
outcnt = 0;
}
-static void __init unpack_to_rootfs(char *buf, unsigned len)
+char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
{
int written;
+ dry_run = check_only;
header_buf = malloc(110);
symlink_buf = malloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1);
name_buf = malloc(N_ALIGN(PATH_MAX));
window = malloc(WSIZE);
if (!window || !header_buf || !symlink_buf || !name_buf)
- error("can't allocate buffers");
+ panic("can't allocate buffers");
state = Start;
this_header = 0;
- while (len) {
+ message = NULL;
+ while (!message && len) {
loff_t saved_offset = this_header;
if (*buf == '0' && !(this_header & 3)) {
state = Start;
@@ -427,7 +442,8 @@ static void __init unpack_to_rootfs(char *buf, unsigned len)
buf += written;
len -= written;
continue;
- } else if (!*buf) {
+ }
+ if (!*buf) {
buf++;
len--;
this_header++;
@@ -442,7 +458,7 @@ static void __init unpack_to_rootfs(char *buf, unsigned len)
crc = (ulg)0xffffffffL; /* shift register contents */
makecrc();
if (gunzip())
- error("ungzip failed");
+ message = "ungzip failed";
if (state != Reset)
error("junk in gzipped archive");
this_header = saved_offset + inptr;
@@ -453,12 +469,41 @@ static void __init unpack_to_rootfs(char *buf, unsigned len)
free(name_buf);
free(symlink_buf);
free(header_buf);
+ return message;
}
extern char __initramfs_start, __initramfs_end;
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/initrd.h>
+#endif
void __init populate_rootfs(void)
{
- unpack_to_rootfs(&__initramfs_start,
- &__initramfs_end - &__initramfs_start);
+ char *err = unpack_to_rootfs(&__initramfs_start,
+ &__initramfs_end - &__initramfs_start, 0);
+ if (err)
+ panic(err);
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start) {
+ int fd;
+ printk(KERN_INFO "checking if image is initramfs...");
+ err = unpack_to_rootfs((char *)initrd_start,
+ initrd_end - initrd_start, 1);
+ if (!err) {
+ printk(" it is\n");
+ unpack_to_rootfs((char *)initrd_start,
+ initrd_end - initrd_start, 0);
+ free_initrd_mem(initrd_start, initrd_end);
+ return;
+ }
+ printk("it isn't (%s); looks like an initrd\n", err);
+ fd = sys_open("/dev/initrd", O_WRONLY|O_CREAT, 700);
+ if (fd >= 0) {
+ sys_write(fd, (char *)initrd_start,
+ initrd_end - initrd_start);
+ sys_close(fd);
+ free_initrd_mem(initrd_start, initrd_end);
+ }
+ }
+#endif
}