linux/init/do_mounts.c
<<
>>
Prefs
   1#include <linux/module.h>
   2#include <linux/sched.h>
   3#include <linux/ctype.h>
   4#include <linux/fd.h>
   5#include <linux/tty.h>
   6#include <linux/suspend.h>
   7#include <linux/root_dev.h>
   8#include <linux/security.h>
   9#include <linux/delay.h>
  10#include <linux/genhd.h>
  11#include <linux/mount.h>
  12#include <linux/device.h>
  13#include <linux/init.h>
  14#include <linux/fs.h>
  15#include <linux/initrd.h>
  16#include <linux/async.h>
  17#include <linux/fs_struct.h>
  18
  19#include <linux/nfs_fs.h>
  20#include <linux/nfs_fs_sb.h>
  21#include <linux/nfs_mount.h>
  22
  23#include "do_mounts.h"
  24
  25int __initdata rd_doload;       /* 1 = load RAM disk, 0 = don't load */
  26
  27int root_mountflags = MS_RDONLY | MS_SILENT;
  28static char * __initdata root_device_name;
  29static char __initdata saved_root_name[64];
  30static int __initdata root_wait;
  31
  32dev_t ROOT_DEV;
  33
  34static int __init load_ramdisk(char *str)
  35{
  36        rd_doload = simple_strtol(str,NULL,0) & 3;
  37        return 1;
  38}
  39__setup("load_ramdisk=", load_ramdisk);
  40
  41static int __init readonly(char *str)
  42{
  43        if (*str)
  44                return 0;
  45        root_mountflags |= MS_RDONLY;
  46        return 1;
  47}
  48
  49static int __init readwrite(char *str)
  50{
  51        if (*str)
  52                return 0;
  53        root_mountflags &= ~MS_RDONLY;
  54        return 1;
  55}
  56
  57__setup("ro", readonly);
  58__setup("rw", readwrite);
  59
  60/*
  61 *      Convert a name into device number.  We accept the following variants:
  62 *
  63 *      1) device number in hexadecimal represents itself
  64 *      2) /dev/nfs represents Root_NFS (0xff)
  65 *      3) /dev/<disk_name> represents the device number of disk
  66 *      4) /dev/<disk_name><decimal> represents the device number
  67 *         of partition - device number of disk plus the partition number
  68 *      5) /dev/<disk_name>p<decimal> - same as the above, that form is
  69 *         used when disk name of partitioned disk ends on a digit.
  70 *
  71 *      If name doesn't have fall into the categories above, we return (0,0).
  72 *      block_class is used to check if something is a disk name. If the disk
  73 *      name contains slashes, the device name has them replaced with
  74 *      bangs.
  75 */
  76
  77dev_t name_to_dev_t(char *name)
  78{
  79        char s[32];
  80        char *p;
  81        dev_t res = 0;
  82        int part;
  83
  84        if (strncmp(name, "/dev/", 5) != 0) {
  85                unsigned maj, min;
  86
  87                if (sscanf(name, "%u:%u", &maj, &min) == 2) {
  88                        res = MKDEV(maj, min);
  89                        if (maj != MAJOR(res) || min != MINOR(res))
  90                                goto fail;
  91                } else {
  92                        res = new_decode_dev(simple_strtoul(name, &p, 16));
  93                        if (*p)
  94                                goto fail;
  95                }
  96                goto done;
  97        }
  98
  99        name += 5;
 100        res = Root_NFS;
 101        if (strcmp(name, "nfs") == 0)
 102                goto done;
 103        res = Root_RAM0;
 104        if (strcmp(name, "ram") == 0)
 105                goto done;
 106
 107        if (strlen(name) > 31)
 108                goto fail;
 109        strcpy(s, name);
 110        for (p = s; *p; p++)
 111                if (*p == '/')
 112                        *p = '!';
 113        res = blk_lookup_devt(s, 0);
 114        if (res)
 115                goto done;
 116
 117        /*
 118         * try non-existant, but valid partition, which may only exist
 119         * after revalidating the disk, like partitioned md devices
 120         */
 121        while (p > s && isdigit(p[-1]))
 122                p--;
 123        if (p == s || !*p || *p == '0')
 124                goto fail;
 125
 126        /* try disk name without <part number> */
 127        part = simple_strtoul(p, NULL, 10);
 128        *p = '\0';
 129        res = blk_lookup_devt(s, part);
 130        if (res)
 131                goto done;
 132
 133        /* try disk name without p<part number> */
 134        if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
 135                goto fail;
 136        p[-1] = '\0';
 137        res = blk_lookup_devt(s, part);
 138        if (res)
 139                goto done;
 140
 141fail:
 142        return 0;
 143done:
 144        return res;
 145}
 146
 147static int __init root_dev_setup(char *line)
 148{
 149        strlcpy(saved_root_name, line, sizeof(saved_root_name));
 150        return 1;
 151}
 152
 153__setup("root=", root_dev_setup);
 154
 155static int __init rootwait_setup(char *str)
 156{
 157        if (*str)
 158                return 0;
 159        root_wait = 1;
 160        return 1;
 161}
 162
 163__setup("rootwait", rootwait_setup);
 164
 165static char * __initdata root_mount_data;
 166static int __init root_data_setup(char *str)
 167{
 168        root_mount_data = str;
 169        return 1;
 170}
 171
 172static char * __initdata root_fs_names;
 173static int __init fs_names_setup(char *str)
 174{
 175        root_fs_names = str;
 176        return 1;
 177}
 178
 179static unsigned int __initdata root_delay;
 180static int __init root_delay_setup(char *str)
 181{
 182        root_delay = simple_strtoul(str, NULL, 0);
 183        return 1;
 184}
 185
 186__setup("rootflags=", root_data_setup);
 187__setup("rootfstype=", fs_names_setup);
 188__setup("rootdelay=", root_delay_setup);
 189
 190static void __init get_fs_names(char *page)
 191{
 192        char *s = page;
 193
 194        if (root_fs_names) {
 195                strcpy(page, root_fs_names);
 196                while (*s++) {
 197                        if (s[-1] == ',')
 198                                s[-1] = '\0';
 199                }
 200        } else {
 201                int len = get_filesystem_list(page);
 202                char *p, *next;
 203
 204                page[len] = '\0';
 205                for (p = page-1; p; p = next) {
 206                        next = strchr(++p, '\n');
 207                        if (*p++ != '\t')
 208                                continue;
 209                        while ((*s++ = *p++) != '\n')
 210                                ;
 211                        s[-1] = '\0';
 212                }
 213        }
 214        *s = '\0';
 215}
 216
 217static int __init do_mount_root(char *name, char *fs, int flags, void *data)
 218{
 219        int err = sys_mount(name, "/root", fs, flags, data);
 220        if (err)
 221                return err;
 222
 223        sys_chdir("/root");
 224        ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
 225        printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
 226               current->fs->pwd.mnt->mnt_sb->s_type->name,
 227               current->fs->pwd.mnt->mnt_sb->s_flags & MS_RDONLY ?
 228               " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
 229        return 0;
 230}
 231
 232void __init mount_block_root(char *name, int flags)
 233{
 234        char *fs_names = __getname();
 235        char *p;
 236#ifdef CONFIG_BLOCK
 237        char b[BDEVNAME_SIZE];
 238#else
 239        const char *b = name;
 240#endif
 241
 242        get_fs_names(fs_names);
 243retry:
 244        for (p = fs_names; *p; p += strlen(p)+1) {
 245                int err = do_mount_root(name, p, flags, root_mount_data);
 246                switch (err) {
 247                        case 0:
 248                                goto out;
 249                        case -EACCES:
 250                                flags |= MS_RDONLY;
 251                                goto retry;
 252                        case -EINVAL:
 253                                continue;
 254                }
 255                /*
 256                 * Allow the user to distinguish between failed sys_open
 257                 * and bad superblock on root device.
 258                 * and give them a list of the available devices
 259                 */
 260#ifdef CONFIG_BLOCK
 261                __bdevname(ROOT_DEV, b);
 262#endif
 263                printk("VFS: Cannot open root device \"%s\" or %s\n",
 264                                root_device_name, b);
 265                printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");
 266
 267                printk_all_partitions();
 268#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT
 269                printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify "
 270                       "explicit textual name for \"root=\" boot option.\n");
 271#endif
 272                panic("VFS: Unable to mount root fs on %s", b);
 273        }
 274
 275        printk("List of all partitions:\n");
 276        printk_all_partitions();
 277        printk("No filesystem could mount root, tried: ");
 278        for (p = fs_names; *p; p += strlen(p)+1)
 279                printk(" %s", p);
 280        printk("\n");
 281#ifdef CONFIG_BLOCK
 282        __bdevname(ROOT_DEV, b);
 283#endif
 284        panic("VFS: Unable to mount root fs on %s", b);
 285out:
 286        putname(fs_names);
 287}
 288 
 289#ifdef CONFIG_ROOT_NFS
 290static int __init mount_nfs_root(void)
 291{
 292        void *data = nfs_root_data();
 293
 294        create_dev("/dev/root", ROOT_DEV);
 295        if (data &&
 296            do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
 297                return 1;
 298        return 0;
 299}
 300#endif
 301
 302#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
 303void __init change_floppy(char *fmt, ...)
 304{
 305        struct termios termios;
 306        char buf[80];
 307        char c;
 308        int fd;
 309        va_list args;
 310        va_start(args, fmt);
 311        vsprintf(buf, fmt, args);
 312        va_end(args);
 313        fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0);
 314        if (fd >= 0) {
 315                sys_ioctl(fd, FDEJECT, 0);
 316                sys_close(fd);
 317        }
 318        printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
 319        fd = sys_open("/dev/console", O_RDWR, 0);
 320        if (fd >= 0) {
 321                sys_ioctl(fd, TCGETS, (long)&termios);
 322                termios.c_lflag &= ~ICANON;
 323                sys_ioctl(fd, TCSETSF, (long)&termios);
 324                sys_read(fd, &c, 1);
 325                termios.c_lflag |= ICANON;
 326                sys_ioctl(fd, TCSETSF, (long)&termios);
 327                sys_close(fd);
 328        }
 329}
 330#endif
 331
 332void __init mount_root(void)
 333{
 334#ifdef CONFIG_ROOT_NFS
 335        if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
 336                if (mount_nfs_root())
 337                        return;
 338
 339                printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
 340                ROOT_DEV = Root_FD0;
 341        }
 342#endif
 343#ifdef CONFIG_BLK_DEV_FD
 344        if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
 345                /* rd_doload is 2 for a dual initrd/ramload setup */
 346                if (rd_doload==2) {
 347                        if (rd_load_disk(1)) {
 348                                ROOT_DEV = Root_RAM1;
 349                                root_device_name = NULL;
 350                        }
 351                } else
 352                        change_floppy("root floppy");
 353        }
 354#endif
 355#ifdef CONFIG_BLOCK
 356        create_dev("/dev/root", ROOT_DEV);
 357        mount_block_root("/dev/root", root_mountflags);
 358#endif
 359}
 360
 361/*
 362 * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
 363 */
 364void __init prepare_namespace(void)
 365{
 366        int is_floppy;
 367
 368        if (root_delay) {
 369                printk(KERN_INFO "Waiting %dsec before mounting root device...\n",
 370                       root_delay);
 371                ssleep(root_delay);
 372        }
 373
 374        /*
 375         * wait for the known devices to complete their probing
 376         *
 377         * Note: this is a potential source of long boot delays.
 378         * For example, it is not atypical to wait 5 seconds here
 379         * for the touchpad of a laptop to initialize.
 380         */
 381        wait_for_device_probe();
 382
 383        md_run_setup();
 384
 385        if (saved_root_name[0]) {
 386                root_device_name = saved_root_name;
 387                if (!strncmp(root_device_name, "mtd", 3) ||
 388                    !strncmp(root_device_name, "ubi", 3)) {
 389                        mount_block_root(root_device_name, root_mountflags);
 390                        goto out;
 391                }
 392                ROOT_DEV = name_to_dev_t(root_device_name);
 393                if (strncmp(root_device_name, "/dev/", 5) == 0)
 394                        root_device_name += 5;
 395        }
 396
 397        if (initrd_load())
 398                goto out;
 399
 400        /* wait for any asynchronous scanning to complete */
 401        if ((ROOT_DEV == 0) && root_wait) {
 402                printk(KERN_INFO "Waiting for root device %s...\n",
 403                        saved_root_name);
 404                while (driver_probe_done() != 0 ||
 405                        (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
 406                        msleep(100);
 407                async_synchronize_full();
 408        }
 409
 410        is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
 411
 412        if (is_floppy && rd_doload && rd_load_disk(0))
 413                ROOT_DEV = Root_RAM0;
 414
 415        mount_root();
 416out:
 417        sys_mount(".", "/", NULL, MS_MOVE, NULL);
 418        sys_chroot(".");
 419}
 420
 421
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.