]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] drivers/block/initrd.c removal
authorAndrew Morton <akpm@osdl.org>
Thu, 16 Oct 2003 00:29:46 +0000 (17:29 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Thu, 16 Oct 2003 00:29:46 +0000 (17:29 -0700)
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.

drivers/block/Makefile
drivers/block/initrd.c [deleted file]
init/do_mounts_initrd.c
init/initramfs.c

index cf72f7cfb806787e592a897508a00e5a56d8b524..bc301c82e3a635dc5ea31d4f683cd88fe3569387 100644 (file)
@@ -28,7 +28,6 @@ obj-$(CONFIG_ATARI_ACSI)      += acsi.o
 obj-$(CONFIG_ATARI_SLM)                += acsi_slm.o
 obj-$(CONFIG_AMIGA_Z2RAM)      += z2ram.o
 obj-$(CONFIG_BLK_DEV_RAM)      += rd.o
-obj-$(CONFIG_BLK_DEV_INITRD)   += initrd.o
 obj-$(CONFIG_BLK_DEV_LOOP)     += loop.o
 obj-$(CONFIG_BLK_DEV_PS2)      += ps2esdi.o
 obj-$(CONFIG_BLK_DEV_XD)       += xd.o
diff --git a/drivers/block/initrd.c b/drivers/block/initrd.c
deleted file mode 100644 (file)
index 41a7725..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-
-#include <linux/blkdev.h>
-#include <linux/genhd.h>
-#include <linux/initrd.h>
-#include <linux/init.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-
-unsigned long initrd_start, initrd_end;
-int initrd_below_start_ok;
-
-static int initrd_users;
-static spinlock_t initrd_users_lock = SPIN_LOCK_UNLOCKED;
-
-static struct gendisk *initrd_disk;
-
-static ssize_t initrd_read(struct file *file, char *buf,
-                          size_t count, loff_t *ppos)
-{
-       int left = initrd_end - initrd_start - *ppos;
-
-       if (count > left)
-               count = left;
-       if (count == 0)
-               return 0;
-       if (copy_to_user(buf, (char *)initrd_start + *ppos, count))
-               return -EFAULT;
-
-       *ppos += count;
-       return count;
-}
-
-static int initrd_release(struct inode *inode,struct file *file)
-{
-
-       blkdev_put(inode->i_bdev, BDEV_FILE);
-
-       spin_lock(&initrd_users_lock);
-       if (!--initrd_users) {
-               spin_unlock(&initrd_users_lock);
-               del_gendisk(initrd_disk);
-               free_initrd_mem(initrd_start, initrd_end);
-               initrd_start = 0;
-       } else
-               spin_unlock(&initrd_users_lock);
-
-       return 0;
-}
-
-static struct file_operations initrd_fops = {
-       .read =         initrd_read,
-       .release =      initrd_release,
-};
-
-static int initrd_open(struct inode *inode, struct file *filp)
-{
-       if (!initrd_start) 
-               return -ENODEV;
-
-       spin_lock(&initrd_users_lock);
-       initrd_users++;
-       spin_unlock(&initrd_users_lock);
-
-       filp->f_op = &initrd_fops;
-       return 0;
-}
-
-static struct block_device_operations initrd_bdops = {
-       .owner =        THIS_MODULE,
-       .open =         initrd_open,
-};
-
-static int __init initrd_init(void)
-{
-       initrd_disk = alloc_disk(1);
-       if (!initrd_disk)
-               return -ENOMEM;
-
-       initrd_disk->major = RAMDISK_MAJOR;
-       initrd_disk->first_minor = INITRD_MINOR;
-       initrd_disk->fops = &initrd_bdops;      
-
-       sprintf(initrd_disk->disk_name, "initrd");
-       sprintf(initrd_disk->devfs_name, "rd/initrd");
-
-       set_capacity(initrd_disk, (initrd_end-initrd_start+511) >> 9);
-       add_disk(initrd_disk);
-       return 0;
-}
-
-static void __exit initrd_exit(void)
-{
-       put_disk(initrd_disk);
-}
-
-module_init(initrd_init);
-module_exit(initrd_exit);
index a800891d21398ef225007301014521eec00be71b..9a0ab579ae4fee08c369d6c790a089d2a53752b6 100644 (file)
@@ -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;
 }
index 5a9f5b3b05f7ae3d79f08a9fe1eda98f1d2e9c64..42eda038009f77cd7f1a80fa56d4ca2fd01b571b 100644 (file)
@@ -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
 }