Blame view

init/do_mounts_initrd.c 3.02 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  #define __KERNEL_SYSCALLS__
  #include <linux/unistd.h>
  #include <linux/kernel.h>
  #include <linux/fs.h>
  #include <linux/minix_fs.h>
  #include <linux/ext2_fs.h>
  #include <linux/romfs_fs.h>
  #include <linux/initrd.h>
  #include <linux/sched.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)
  {
  	mount_initrd = 0;
  	return 1;
  }
  
  __setup("noinitrd", no_initrd);
  
  static int __init do_linuxrc(void * shell)
  {
  	static char *argv[] = { "linuxrc", NULL, };
  	extern char * envp_init[];
  
  	sys_close(old_fd);sys_close(root_fd);
  	sys_close(0);sys_close(1);sys_close(2);
  	sys_setsid();
  	(void) sys_open("/dev/console",O_RDWR,0);
  	(void) sys_dup(0);
  	(void) sys_dup(0);
  	return execve(shell, argv, envp_init);
  }
  
  static void __init handle_initrd(void)
  {
  	int error;
29a1d2d1b   Domen Puncer   [PATCH] init/do_m...
44
  	int pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  
  	real_root_dev = new_encode_dev(ROOT_DEV);
  	create_dev("/dev/root.old", Root_RAM0, NULL);
  	/* 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(".");
  	mount_devfs_fs ();
  
  	pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
  	if (pid > 0) {
29a1d2d1b   Domen Puncer   [PATCH] init/do_m...
61
  		while (pid != sys_wait4(-1, NULL, 0, NULL))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  			yield();
  	}
  
  	/* move initrd to rootfs' /old */
  	sys_fchdir(old_fd);
  	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);
  	umount_devfs("/old/dev");
  
  	if (new_decode_dev(real_root_dev) == Root_RAM0) {
  		sys_chdir("/old");
  		return;
  	}
  
  	ROOT_DEV = new_decode_dev(real_root_dev);
  	mount_root();
  
  	printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
  	error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
  	if (!error)
  		printk("okay
  ");
  	else {
  		int fd = sys_open("/dev/root.old", O_RDWR, 0);
f220ab2a5   Jay Lan   [PATCH] Improper ...
90
91
92
93
94
95
  		if (error == -ENOENT)
  			printk("/initrd does not exist. Ignored.
  ");
  		else
  			printk("failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  		printk(KERN_NOTICE "Unmounting old root
  ");
  		sys_umount("/old", MNT_DETACH);
  		printk(KERN_NOTICE "Trying to free ramdisk memory ... ");
  		if (fd < 0) {
  			error = fd;
  		} else {
  			error = sys_ioctl(fd, BLKFLSBUF, 0);
  			sys_close(fd);
  		}
  		printk(!error ? "okay
  " : "failed
  ");
  	}
  }
  
  int __init initrd_load(void)
  {
  	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("/initrd.image") && ROOT_DEV != Root_RAM0) {
  			sys_unlink("/initrd.image");
  			handle_initrd();
  			return 1;
  		}
  	}
  	sys_unlink("/initrd.image");
  	return 0;
  }