diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-02 15:29:10 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-11 21:40:30 -0400 |
commit | ba4df2808a86f8b103c4db0b8807649383e9bd13 (patch) | |
tree | b027ebf6d1345842686577e04d2cda1e4b05201f /init | |
parent | cb450766bcafc7bd7d40e9a5a0050745e8c68b3e (diff) | |
download | lwn-ba4df2808a86f8b103c4db0b8807649383e9bd13.tar.gz lwn-ba4df2808a86f8b103c4db0b8807649383e9bd13.zip |
don't bother with kernel_thread/kernel_execve for launching linuxrc
exec_usermodehelper_fns() will do just fine...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'init')
-rw-r--r-- | init/do_mounts_initrd.c | 41 |
1 files changed, 16 insertions, 25 deletions
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index 135959a276be..5e4ded51788e 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c @@ -16,13 +16,13 @@ #include <linux/initrd.h> #include <linux/sched.h> #include <linux/freezer.h> +#include <linux/kmod.h> #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,33 +33,29 @@ static int __init no_initrd(char *str) __setup("noinitrd", no_initrd); -static int __init do_linuxrc(void *_shell) +static int init_linuxrc(struct subprocess_info *info, struct cred *new) { - static const char *argv[] = { "linuxrc", NULL, }; - extern const char *envp_init[]; - const char *shell = _shell; - - sys_close(old_fd);sys_close(root_fd); + sys_unshare(CLONE_FS | CLONE_FILES); + /* move initrd over / and chdir/chroot in initrd root */ + sys_chdir("/root"); + sys_mount(".", "/", NULL, MS_MOVE, NULL); + sys_chroot("."); sys_setsid(); - return kernel_execve(shell, argv, envp_init); + return 0; } static void __init handle_initrd(void) { + 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); - 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("."); + sys_chdir("/old"); /* * In case that a resume from disk is carried out by linuxrc or one of @@ -67,27 +63,22 @@ static void __init handle_initrd(void) */ current->flags |= PF_FREEZER_SKIP; - pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); - if (pid > 0) - while (pid != sys_wait4(-1, NULL, 0, NULL)) - yield(); + call_usermodehelper_fns("/linuxrc", argv, envp_init, UMH_WAIT_PROC, + init_linuxrc, NULL, NULL); current->flags &= ~PF_FREEZER_SKIP; /* move initrd to rootfs' /old */ - sys_fchdir(old_fd); - sys_mount("/", ".", NULL, MS_MOVE, NULL); + sys_mount("..", ".", NULL, MS_MOVE, NULL); /* switch root and cwd back to / of rootfs */ - sys_fchdir(root_fd); - sys_chroot("."); - sys_close(old_fd); - sys_close(root_fd); + sys_chroot(".."); 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(); |