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