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