Commit ba4df280 authored by Al Viro's avatar Al Viro

don't bother with kernel_thread/kernel_execve for launching linuxrc

exec_usermodehelper_fns() will do just fine...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cb450766
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
#include <linux/initrd.h> #include <linux/initrd.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/freezer.h> #include <linux/freezer.h>
#include <linux/kmod.h>
#include "do_mounts.h" #include "do_mounts.h"
unsigned long initrd_start, initrd_end; unsigned long initrd_start, initrd_end;
int initrd_below_start_ok; int initrd_below_start_ok;
unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ 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 __initdata mount_initrd = 1;
static int __init no_initrd(char *str) static int __init no_initrd(char *str)
...@@ -33,33 +33,29 @@ static int __init no_initrd(char *str) ...@@ -33,33 +33,29 @@ static int __init no_initrd(char *str)
__setup("noinitrd", no_initrd); __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, }; sys_unshare(CLONE_FS | CLONE_FILES);
extern const char *envp_init[]; /* move initrd over / and chdir/chroot in initrd root */
const char *shell = _shell; sys_chdir("/root");
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_close(old_fd);sys_close(root_fd); sys_chroot(".");
sys_setsid(); sys_setsid();
return kernel_execve(shell, argv, envp_init); return 0;
} }
static void __init handle_initrd(void) static void __init handle_initrd(void)
{ {
static char *argv[] = { "linuxrc", NULL, };
extern char *envp_init[];
int error; int error;
int pid;
real_root_dev = new_encode_dev(ROOT_DEV); real_root_dev = new_encode_dev(ROOT_DEV);
create_dev("/dev/root.old", Root_RAM0); create_dev("/dev/root.old", Root_RAM0);
/* mount initrd on rootfs' /root */ /* mount initrd on rootfs' /root */
mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
sys_mkdir("/old", 0700); sys_mkdir("/old", 0700);
root_fd = sys_open("/", 0, 0); sys_chdir("/old");
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 * 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) ...@@ -67,27 +63,22 @@ static void __init handle_initrd(void)
*/ */
current->flags |= PF_FREEZER_SKIP; current->flags |= PF_FREEZER_SKIP;
pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); call_usermodehelper_fns("/linuxrc", argv, envp_init, UMH_WAIT_PROC,
if (pid > 0) init_linuxrc, NULL, NULL);
while (pid != sys_wait4(-1, NULL, 0, NULL))
yield();
current->flags &= ~PF_FREEZER_SKIP; current->flags &= ~PF_FREEZER_SKIP;
/* move initrd to rootfs' /old */ /* 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 */ /* switch root and cwd back to / of rootfs */
sys_fchdir(root_fd); sys_chroot("..");
sys_chroot(".");
sys_close(old_fd);
sys_close(root_fd);
if (new_decode_dev(real_root_dev) == Root_RAM0) { if (new_decode_dev(real_root_dev) == Root_RAM0) {
sys_chdir("/old"); sys_chdir("/old");
return; return;
} }
sys_chdir("/");
ROOT_DEV = new_decode_dev(real_root_dev); ROOT_DEV = new_decode_dev(real_root_dev);
mount_root(); mount_root();
......
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