Commit 0af65687 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent 01d259fe
......@@ -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
......
#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);
......@@ -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 (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;
}
......@@ -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 (name_len <= 0 || name_len > PATH_MAX)
if (dry_run) {
read_into(name_buf, N_ALIGN(name_len), GotName);
return 0;
}
state = SkipIt;
else if (S_ISLNK(mode)) {
if (name_len <= 0 || name_len > PATH_MAX)
return 0;
if (S_ISLNK(mode)) {
if (body_len > PATH_MAX)
state = SkipIt;
else {
return 0;
collect = collected = symlink_buf;
remains = N_ALIGN(name_len) + body_len;
next_state = GotSymlink;
state = Collect;
return 0;
}
} else if (body_len && !S_ISREG(mode))
state = SkipIt;
else
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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment