Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/init/do_mounts_initrd.c

  1 /*
  2  * Many of the syscalls used in this file expect some of the arguments
  3  * to be __user pointers not __kernel pointers.  To limit the sparse
  4  * noise, turn off sparse checking for this file.
  5  */
  6 #ifdef __CHECKER__
  7 #undef __CHECKER__
  8 #warning "Sparse checking disabled for this file"
  9 #endif
 10 
 11 #include <linux/unistd.h>
 12 #include <linux/kernel.h>
 13 #include <linux/fs.h>
 14 #include <linux/minix_fs.h>
 15 #include <linux/romfs_fs.h>
 16 #include <linux/initrd.h>
 17 #include <linux/sched.h>
 18 #include <linux/freezer.h>
 19 #include <linux/kmod.h>
 20 
 21 #include "do_mounts.h"
 22 
 23 unsigned long initrd_start, initrd_end;
 24 int initrd_below_start_ok;
 25 unsigned int real_root_dev;     /* do_proc_dointvec cannot handle kdev_t */
 26 static int __initdata mount_initrd = 1;
 27 
 28 static int __init no_initrd(char *str)
 29 {
 30         mount_initrd = 0;
 31         return 1;
 32 }
 33 
 34 __setup("noinitrd", no_initrd);
 35 
 36 static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 37 {
 38         sys_unshare(CLONE_FS | CLONE_FILES);
 39         /* stdin/stdout/stderr for /linuxrc */
 40         sys_open("/dev/console", O_RDWR, 0);
 41         sys_dup(0);
 42         sys_dup(0);
 43         /* move initrd over / and chdir/chroot in initrd root */
 44         sys_chdir("/root");
 45         sys_mount(".", "/", NULL, MS_MOVE, NULL);
 46         sys_chroot(".");
 47         sys_setsid();
 48         return 0;
 49 }
 50 
 51 static void __init handle_initrd(void)
 52 {
 53         struct subprocess_info *info;
 54         static char *argv[] = { "linuxrc", NULL, };
 55         extern char *envp_init[];
 56         int error;
 57 
 58         real_root_dev = new_encode_dev(ROOT_DEV);
 59         create_dev("/dev/root.old", Root_RAM0);
 60         /* mount initrd on rootfs' /root */
 61         mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
 62         sys_mkdir("/old", 0700);
 63         sys_chdir("/old");
 64 
 65         /* try loading default modules from initrd */
 66         load_default_modules();
 67 
 68         /*
 69          * In case that a resume from disk is carried out by linuxrc or one of
 70          * its children, we need to tell the freezer not to wait for us.
 71          */
 72         current->flags |= PF_FREEZER_SKIP;
 73 
 74         info = call_usermodehelper_setup("/linuxrc", argv, envp_init,
 75                                          GFP_KERNEL, init_linuxrc, NULL, NULL);
 76         if (!info)
 77                 return;
 78         call_usermodehelper_exec(info, UMH_WAIT_PROC);
 79 
 80         current->flags &= ~PF_FREEZER_SKIP;
 81 
 82         /* move initrd to rootfs' /old */
 83         sys_mount("..", ".", NULL, MS_MOVE, NULL);
 84         /* switch root and cwd back to / of rootfs */
 85         sys_chroot("..");
 86 
 87         if (new_decode_dev(real_root_dev) == Root_RAM0) {
 88                 sys_chdir("/old");
 89                 return;
 90         }
 91 
 92         sys_chdir("/");
 93         ROOT_DEV = new_decode_dev(real_root_dev);
 94         mount_root();
 95 
 96         printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
 97         error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
 98         if (!error)
 99                 printk("okay\n");
100         else {
101                 int fd = sys_open("/dev/root.old", O_RDWR, 0);
102                 if (error == -ENOENT)
103                         printk("/initrd does not exist. Ignored.\n");
104                 else
105                         printk("failed\n");
106                 printk(KERN_NOTICE "Unmounting old root\n");
107                 sys_umount("/old", MNT_DETACH);
108                 printk(KERN_NOTICE "Trying to free ramdisk memory ... ");
109                 if (fd < 0) {
110                         error = fd;
111                 } else {
112                         error = sys_ioctl(fd, BLKFLSBUF, 0);
113                         sys_close(fd);
114                 }
115                 printk(!error ? "okay\n" : "failed\n");
116         }
117 }
118 
119 bool __init initrd_load(void)
120 {
121         if (mount_initrd) {
122                 create_dev("/dev/ram", Root_RAM0);
123                 /*
124                  * Load the initrd data into /dev/ram0. Execute it as initrd
125                  * unless /dev/ram0 is supposed to be our actual root device,
126                  * in that case the ram disk is just set up here, and gets
127                  * mounted in the normal path.
128                  */
129                 if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
130                         sys_unlink("/initrd.image");
131                         handle_initrd();
132                         return true;
133                 }
134         }
135         sys_unlink("/initrd.image");
136         return false;
137 }
138 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us