diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index 3e0878e..9b261ec 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -16,13 +16,13 @@ #include #include #include -#include #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; static int __init no_initrd(char *str) @@ -33,37 +33,33 @@ static int __init no_initrd(char *str) __setup("noinitrd", no_initrd); -static int init_linuxrc(struct subprocess_info *info, struct cred *new) +static int __init do_linuxrc(void *_shell) { - sys_unshare(CLONE_FS | CLONE_FILES); - /* stdin/stdout/stderr for /linuxrc */ - sys_open("/dev/console", O_RDWR, 0); - sys_dup(0); - sys_dup(0); - /* move initrd over / and chdir/chroot in initrd root */ - sys_chdir("/root"); - sys_mount(".", "/", NULL, MS_MOVE, NULL); - sys_chroot("."); + static const char *argv[] = { "linuxrc", NULL, }; + extern const char *envp_init[]; + const char *shell = _shell; + + sys_close(old_fd);sys_close(root_fd); sys_setsid(); - return 0; + return sys_execve(shell, argv, envp_init); } static void __init handle_initrd(void) { - struct subprocess_info *info; - static char *argv[] = { "linuxrc", NULL, }; - extern char *envp_init[]; int error; + int pid; real_root_dev = new_encode_dev(ROOT_DEV); create_dev("/dev/root.old", Root_RAM0); /* mount initrd on rootfs' /root */ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); sys_mkdir("/old", 0700); - sys_chdir("/old"); - - /* try loading default modules from initrd */ - load_default_modules(); + root_fd = sys_open("/", 0, 0); + old_fd = sys_open("/old", 0, 0); + /* move initrd over / and chdir/chroot in initrd root */ + sys_chdir("/root"); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); /* * In case that a resume from disk is carried out by linuxrc or one of @@ -71,25 +67,27 @@ static void __init handle_initrd(void) */ current->flags |= PF_FREEZER_SKIP; - info = call_usermodehelper_setup("/linuxrc", argv, envp_init, - GFP_KERNEL, init_linuxrc, NULL, NULL); - if (!info) - return; - call_usermodehelper_exec(info, UMH_WAIT_PROC); + pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); + if (pid > 0) + while (pid != sys_wait4(-1, NULL, 0, NULL)) + yield(); current->flags &= ~PF_FREEZER_SKIP; /* move initrd to rootfs' /old */ - sys_mount("..", ".", NULL, MS_MOVE, NULL); + sys_fchdir(old_fd); + sys_mount("/", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ - sys_chroot(".."); + sys_fchdir(root_fd); + sys_chroot("."); + sys_close(old_fd); + sys_close(root_fd); if (new_decode_dev(real_root_dev) == Root_RAM0) { sys_chdir("/old"); return; } - sys_chdir("/"); ROOT_DEV = new_decode_dev(real_root_dev); mount_root();