aboutsummaryrefslogtreecommitdiffstats
path: root/init/do_mounts_initrd.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-10-02 15:29:10 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-11 21:40:30 -0400
commitba4df2808a86f8b103c4db0b8807649383e9bd13 (patch)
treeb027ebf6d1345842686577e04d2cda1e4b05201f /init/do_mounts_initrd.c
parentcb450766bcafc7bd7d40e9a5a0050745e8c68b3e (diff)
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/do_mounts_initrd.c')
-rw-r--r--init/do_mounts_initrd.c41
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 @@
16#include <linux/initrd.h> 16#include <linux/initrd.h>
17#include <linux/sched.h> 17#include <linux/sched.h>
18#include <linux/freezer.h> 18#include <linux/freezer.h>
19#include <linux/kmod.h>
19 20
20#include "do_mounts.h" 21#include "do_mounts.h"
21 22
22unsigned long initrd_start, initrd_end; 23unsigned long initrd_start, initrd_end;
23int initrd_below_start_ok; 24int initrd_below_start_ok;
24unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */ 25unsigned int real_root_dev; /* do_proc_dointvec cannot handle kdev_t */
25static int __initdata old_fd, root_fd;
26static int __initdata mount_initrd = 1; 26static int __initdata mount_initrd = 1;
27 27
28static int __init no_initrd(char *str) 28static int __init no_initrd(char *str)
@@ -33,33 +33,29 @@ static int __init no_initrd(char *str)
33 33
34__setup("noinitrd", no_initrd); 34__setup("noinitrd", no_initrd);
35 35
36static int __init do_linuxrc(void *_shell) 36static int init_linuxrc(struct subprocess_info *info, struct cred *new)
37{ 37{
38 static const char *argv[] = { "linuxrc", NULL, }; 38 sys_unshare(CLONE_FS | CLONE_FILES);
39 extern const char *envp_init[]; 39 /* move initrd over / and chdir/chroot in initrd root */
40 const char *shell = _shell; 40 sys_chdir("/root");
41 41 sys_mount(".", "/", NULL, MS_MOVE, NULL);
42 sys_close(old_fd);sys_close(root_fd); 42 sys_chroot(".");
43 sys_setsid(); 43 sys_setsid();
44 return kernel_execve(shell, argv, envp_init); 44 return 0;
45} 45}
46 46
47static void __init handle_initrd(void) 47static void __init handle_initrd(void)
48{ 48{
49 static char *argv[] = { "linuxrc", NULL, };
50 extern char *envp_init[];
49 int error; 51 int error;
50 int pid;
51 52
52 real_root_dev = new_encode_dev(ROOT_DEV); 53 real_root_dev = new_encode_dev(ROOT_DEV);
53 create_dev("/dev/root.old", Root_RAM0); 54 create_dev("/dev/root.old", Root_RAM0);
54 /* mount initrd on rootfs' /root */ 55 /* mount initrd on rootfs' /root */
55 mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); 56 mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
56 sys_mkdir("/old", 0700); 57 sys_mkdir("/old", 0700);
57 root_fd = sys_open("/", 0, 0); 58 sys_chdir("/old");
58 old_fd = sys_open("/old", 0, 0);
59 /* move initrd over / and chdir/chroot in initrd root */
60 sys_chdir("/root");
61 sys_mount(".", "/", NULL, MS_MOVE, NULL);
62 sys_chroot(".");
63 59
64 /* 60 /*
65 * In case that a resume from disk is carried out by linuxrc or one of 61 * 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 */ 63 */
68 current->flags |= PF_FREEZER_SKIP; 64 current->flags |= PF_FREEZER_SKIP;
69 65
70 pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD); 66 call_usermodehelper_fns("/linuxrc", argv, envp_init, UMH_WAIT_PROC,
71 if (pid > 0) 67 init_linuxrc, NULL, NULL);
72 while (pid != sys_wait4(-1, NULL, 0, NULL))
73 yield();
74 68
75 current->flags &= ~PF_FREEZER_SKIP; 69 current->flags &= ~PF_FREEZER_SKIP;
76 70
77 /* move initrd to rootfs' /old */ 71 /* move initrd to rootfs' /old */
78 sys_fchdir(old_fd); 72 sys_mount("..", ".", NULL, MS_MOVE, NULL);
79 sys_mount("/", ".", NULL, MS_MOVE, NULL);
80 /* switch root and cwd back to / of rootfs */ 73 /* switch root and cwd back to / of rootfs */
81 sys_fchdir(root_fd); 74 sys_chroot("..");
82 sys_chroot(".");
83 sys_close(old_fd);
84 sys_close(root_fd);
85 75
86 if (new_decode_dev(real_root_dev) == Root_RAM0) { 76 if (new_decode_dev(real_root_dev) == Root_RAM0) {
87 sys_chdir("/old"); 77 sys_chdir("/old");
88 return; 78 return;
89 } 79 }
90 80
81 sys_chdir("/");
91 ROOT_DEV = new_decode_dev(real_root_dev); 82 ROOT_DEV = new_decode_dev(real_root_dev);
92 mount_root(); 83 mount_root();
93 84