1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 21da177e4SLinus Torvalds #include <linux/module.h> 31da177e4SLinus Torvalds #include <linux/sched.h> 41da177e4SLinus Torvalds #include <linux/ctype.h> 51da177e4SLinus Torvalds #include <linux/fd.h> 61da177e4SLinus Torvalds #include <linux/tty.h> 71da177e4SLinus Torvalds #include <linux/suspend.h> 81da177e4SLinus Torvalds #include <linux/root_dev.h> 91da177e4SLinus Torvalds #include <linux/security.h> 101da177e4SLinus Torvalds #include <linux/delay.h> 11d53d9f16SAndrew Morton #include <linux/mount.h> 12d779249eSGreg Kroah-Hartman #include <linux/device.h> 1346595390SAdrian Bunk #include <linux/init.h> 14011e3fcdSAdrian Bunk #include <linux/fs.h> 1582c8253aSAdrian Bunk #include <linux/initrd.h> 1622a9d645SArjan van de Ven #include <linux/async.h> 175ad4e53bSAl Viro #include <linux/fs_struct.h> 185a0e3ad6STejun Heo #include <linux/slab.h> 1957f150a5SRob Landley #include <linux/ramfs.h> 2016203a7aSRob Landley #include <linux/shmem_fs.h> 21*45071e1cSLoic Poulain #include <linux/ktime.h> 221da177e4SLinus Torvalds 231da177e4SLinus Torvalds #include <linux/nfs_fs.h> 241da177e4SLinus Torvalds #include <linux/nfs_fs_sb.h> 251da177e4SLinus Torvalds #include <linux/nfs_mount.h> 264f5b246bSChristoph Hellwig #include <linux/raid/detect.h> 27e262e32dSDavid Howells #include <uapi/linux/mount.h> 281da177e4SLinus Torvalds 291da177e4SLinus Torvalds #include "do_mounts.h" 301da177e4SLinus Torvalds 319b04c997STheodore Ts'o int root_mountflags = MS_RDONLY | MS_SILENT; 321da177e4SLinus Torvalds static char __initdata saved_root_name[64]; 3379975f13SWill Drewry static int root_wait; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds dev_t ROOT_DEV; 361da177e4SLinus Torvalds 371da177e4SLinus Torvalds static int __init load_ramdisk(char *str) 381da177e4SLinus Torvalds { 39c8376994SChristoph Hellwig pr_warn("ignoring the deprecated load_ramdisk= option\n"); 401da177e4SLinus Torvalds return 1; 411da177e4SLinus Torvalds } 421da177e4SLinus Torvalds __setup("load_ramdisk=", load_ramdisk); 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds static int __init readonly(char *str) 451da177e4SLinus Torvalds { 461da177e4SLinus Torvalds if (*str) 471da177e4SLinus Torvalds return 0; 481da177e4SLinus Torvalds root_mountflags |= MS_RDONLY; 491da177e4SLinus Torvalds return 1; 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds static int __init readwrite(char *str) 531da177e4SLinus Torvalds { 541da177e4SLinus Torvalds if (*str) 551da177e4SLinus Torvalds return 0; 561da177e4SLinus Torvalds root_mountflags &= ~MS_RDONLY; 571da177e4SLinus Torvalds return 1; 581da177e4SLinus Torvalds } 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds __setup("ro", readonly); 611da177e4SLinus Torvalds __setup("rw", readwrite); 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds static int __init root_dev_setup(char *line) 641da177e4SLinus Torvalds { 65a1d3a6d9SWolfram Sang strscpy(saved_root_name, line, sizeof(saved_root_name)); 661da177e4SLinus Torvalds return 1; 671da177e4SLinus Torvalds } 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds __setup("root=", root_dev_setup); 701da177e4SLinus Torvalds 71cc1ed754SPierre Ossman static int __init rootwait_setup(char *str) 72cc1ed754SPierre Ossman { 73cc1ed754SPierre Ossman if (*str) 74cc1ed754SPierre Ossman return 0; 75*45071e1cSLoic Poulain root_wait = -1; 76cc1ed754SPierre Ossman return 1; 77cc1ed754SPierre Ossman } 78cc1ed754SPierre Ossman 79cc1ed754SPierre Ossman __setup("rootwait", rootwait_setup); 80cc1ed754SPierre Ossman 81*45071e1cSLoic Poulain static int __init rootwait_timeout_setup(char *str) 82*45071e1cSLoic Poulain { 83*45071e1cSLoic Poulain int sec; 84*45071e1cSLoic Poulain 85*45071e1cSLoic Poulain if (kstrtoint(str, 0, &sec) || sec < 0) { 86*45071e1cSLoic Poulain pr_warn("ignoring invalid rootwait value\n"); 87*45071e1cSLoic Poulain goto ignore; 88*45071e1cSLoic Poulain } 89*45071e1cSLoic Poulain 90*45071e1cSLoic Poulain if (check_mul_overflow(sec, MSEC_PER_SEC, &root_wait)) { 91*45071e1cSLoic Poulain pr_warn("ignoring excessive rootwait value\n"); 92*45071e1cSLoic Poulain goto ignore; 93*45071e1cSLoic Poulain } 94*45071e1cSLoic Poulain 95*45071e1cSLoic Poulain return 1; 96*45071e1cSLoic Poulain 97*45071e1cSLoic Poulain ignore: 98*45071e1cSLoic Poulain /* Fallback to indefinite wait */ 99*45071e1cSLoic Poulain root_wait = -1; 100*45071e1cSLoic Poulain 101*45071e1cSLoic Poulain return 1; 102*45071e1cSLoic Poulain } 103*45071e1cSLoic Poulain 104*45071e1cSLoic Poulain __setup("rootwait=", rootwait_timeout_setup); 105*45071e1cSLoic Poulain 1061da177e4SLinus Torvalds static char * __initdata root_mount_data; 1071da177e4SLinus Torvalds static int __init root_data_setup(char *str) 1081da177e4SLinus Torvalds { 1091da177e4SLinus Torvalds root_mount_data = str; 1101da177e4SLinus Torvalds return 1; 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds 1131da177e4SLinus Torvalds static char * __initdata root_fs_names; 1141da177e4SLinus Torvalds static int __init fs_names_setup(char *str) 1151da177e4SLinus Torvalds { 1161da177e4SLinus Torvalds root_fs_names = str; 1171da177e4SLinus Torvalds return 1; 1181da177e4SLinus Torvalds } 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds static unsigned int __initdata root_delay; 1211da177e4SLinus Torvalds static int __init root_delay_setup(char *str) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds root_delay = simple_strtoul(str, NULL, 0); 1241da177e4SLinus Torvalds return 1; 1251da177e4SLinus Torvalds } 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds __setup("rootflags=", root_data_setup); 1281da177e4SLinus Torvalds __setup("rootfstype=", fs_names_setup); 1291da177e4SLinus Torvalds __setup("rootdelay=", root_delay_setup); 1301da177e4SLinus Torvalds 131b51593c4SVivek Goyal /* This can return zero length strings. Caller should check */ 13226e293f7SYihuan Pan static int __init split_fs_names(char *page, size_t size) 1331da177e4SLinus Torvalds { 134b51593c4SVivek Goyal int count = 1; 1356e7c1770SChristoph Hellwig char *p = page; 1361da177e4SLinus Torvalds 137a1d3a6d9SWolfram Sang strscpy(p, root_fs_names, size); 1386e7c1770SChristoph Hellwig while (*p++) { 139b51593c4SVivek Goyal if (p[-1] == ',') { 1406e7c1770SChristoph Hellwig p[-1] = '\0'; 1416e7c1770SChristoph Hellwig count++; 142b51593c4SVivek Goyal } 143b51593c4SVivek Goyal } 1446e7c1770SChristoph Hellwig 1456e7c1770SChristoph Hellwig return count; 1461da177e4SLinus Torvalds } 1471da177e4SLinus Torvalds 148cccaa5e3SDominik Brodowski static int __init do_mount_root(const char *name, const char *fs, 149cccaa5e3SDominik Brodowski const int flags, const void *data) 1501da177e4SLinus Torvalds { 151d8c9584eSAl Viro struct super_block *s; 1527de7de7cSLinus Torvalds struct page *p = NULL; 1537de7de7cSLinus Torvalds char *data_page = NULL; 154cccaa5e3SDominik Brodowski int ret; 155cccaa5e3SDominik Brodowski 1567de7de7cSLinus Torvalds if (data) { 157c60166f0SChristoph Hellwig /* init_mount() requires a full page as fifth argument */ 158cccaa5e3SDominik Brodowski p = alloc_page(GFP_KERNEL); 159cccaa5e3SDominik Brodowski if (!p) 160cccaa5e3SDominik Brodowski return -ENOMEM; 161cccaa5e3SDominik Brodowski data_page = page_address(p); 162c60166f0SChristoph Hellwig /* zero-pad. init_mount() will make sure it's terminated */ 1637de7de7cSLinus Torvalds strncpy(data_page, data, PAGE_SIZE); 1647de7de7cSLinus Torvalds } 165cccaa5e3SDominik Brodowski 166c60166f0SChristoph Hellwig ret = init_mount(name, "/root", fs, flags, data_page); 167cccaa5e3SDominik Brodowski if (ret) 168cccaa5e3SDominik Brodowski goto out; 1691da177e4SLinus Torvalds 170db63f1e3SChristoph Hellwig init_chdir("/root"); 171d8c9584eSAl Viro s = current->fs->pwd.dentry->d_sb; 172d8c9584eSAl Viro ROOT_DEV = s->s_dev; 17380cdc6daSMandeep Singh Baines printk(KERN_INFO 17480cdc6daSMandeep Singh Baines "VFS: Mounted root (%s filesystem)%s on device %u:%u.\n", 175d8c9584eSAl Viro s->s_type->name, 176bc98a42cSDavid Howells sb_rdonly(s) ? " readonly" : "", 177d8c9584eSAl Viro MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); 178cccaa5e3SDominik Brodowski 179cccaa5e3SDominik Brodowski out: 1807de7de7cSLinus Torvalds if (p) 181cccaa5e3SDominik Brodowski put_page(p); 182cccaa5e3SDominik Brodowski return ret; 1831da177e4SLinus Torvalds } 1841da177e4SLinus Torvalds 185c8643c72SChristoph Hellwig void __init mount_root_generic(char *name, char *pretty_name, int flags) 1861da177e4SLinus Torvalds { 18775f296d9SLevin, Alexander (Sasha Levin) struct page *page = alloc_page(GFP_KERNEL); 188a608ca21SJeff Layton char *fs_names = page_address(page); 1891da177e4SLinus Torvalds char *p; 1901da177e4SLinus Torvalds char b[BDEVNAME_SIZE]; 1916e7c1770SChristoph Hellwig int num_fs, i; 1921da177e4SLinus Torvalds 193ea3edd4dSChristoph Hellwig scnprintf(b, BDEVNAME_SIZE, "unknown-block(%u,%u)", 194ea3edd4dSChristoph Hellwig MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); 195e24d12b7SChristoph Hellwig if (root_fs_names) 19626e293f7SYihuan Pan num_fs = split_fs_names(fs_names, PAGE_SIZE); 197e24d12b7SChristoph Hellwig else 1986e7c1770SChristoph Hellwig num_fs = list_bdev_fs_names(fs_names, PAGE_SIZE); 1991da177e4SLinus Torvalds retry: 2006e7c1770SChristoph Hellwig for (i = 0, p = fs_names; i < num_fs; i++, p += strlen(p)+1) { 201b51593c4SVivek Goyal int err; 202b51593c4SVivek Goyal 203b51593c4SVivek Goyal if (!*p) 204b51593c4SVivek Goyal continue; 205b51593c4SVivek Goyal err = do_mount_root(name, p, flags, root_mount_data); 2061da177e4SLinus Torvalds switch (err) { 2071da177e4SLinus Torvalds case 0: 2081da177e4SLinus Torvalds goto out; 2091da177e4SLinus Torvalds case -EACCES: 2101da177e4SLinus Torvalds case -EINVAL: 2111da177e4SLinus Torvalds continue; 2121da177e4SLinus Torvalds } 2131da177e4SLinus Torvalds /* 2141da177e4SLinus Torvalds * Allow the user to distinguish between failed sys_open 2151da177e4SLinus Torvalds * and bad superblock on root device. 216dd2a345fSDave Gilbert * and give them a list of the available devices 2171da177e4SLinus Torvalds */ 2180e0cb892SBernhard Walle printk("VFS: Cannot open root device \"%s\" or %s: error %d\n", 219c8643c72SChristoph Hellwig pretty_name, b, err); 220dd2a345fSDave Gilbert printk("Please append a correct \"root=\" boot option; here are the available partitions:\n"); 221dd2a345fSDave Gilbert printk_all_partitions(); 2226aee6723SAngus Chen 2236aee6723SAngus Chen if (root_fs_names) 2246aee6723SAngus Chen num_fs = list_bdev_fs_names(fs_names, PAGE_SIZE); 2256aee6723SAngus Chen if (!num_fs) 2266aee6723SAngus Chen pr_err("Can't find any bdev filesystem to be used for mount!\n"); 2276aee6723SAngus Chen else { 2286aee6723SAngus Chen pr_err("List of all bdev filesystems:\n"); 2296aee6723SAngus Chen for (i = 0, p = fs_names; i < num_fs; i++, p += strlen(p)+1) 2306aee6723SAngus Chen pr_err(" %s", p); 2316aee6723SAngus Chen pr_err("\n"); 2326aee6723SAngus Chen } 2336aee6723SAngus Chen 2341da177e4SLinus Torvalds panic("VFS: Unable to mount root fs on %s", b); 2351da177e4SLinus Torvalds } 236e462ec50SDavid Howells if (!(flags & SB_RDONLY)) { 237e462ec50SDavid Howells flags |= SB_RDONLY; 23810975933SMiklos Szeredi goto retry; 23910975933SMiklos Szeredi } 240be6e028bSAndy Whitcroft 241dd2a345fSDave Gilbert printk("List of all partitions:\n"); 242dd2a345fSDave Gilbert printk_all_partitions(); 243be6e028bSAndy Whitcroft printk("No filesystem could mount root, tried: "); 2446e7c1770SChristoph Hellwig for (i = 0, p = fs_names; i < num_fs; i++, p += strlen(p)+1) 245be6e028bSAndy Whitcroft printk(" %s", p); 246be6e028bSAndy Whitcroft printk("\n"); 2479361401eSDavid Howells panic("VFS: Unable to mount root fs on %s", b); 2481da177e4SLinus Torvalds out: 249a608ca21SJeff Layton put_page(page); 2501da177e4SLinus Torvalds } 2511da177e4SLinus Torvalds 2521da177e4SLinus Torvalds #ifdef CONFIG_ROOT_NFS 25343717c7dSChuck Lever 25443717c7dSChuck Lever #define NFSROOT_TIMEOUT_MIN 5 25543717c7dSChuck Lever #define NFSROOT_TIMEOUT_MAX 30 25643717c7dSChuck Lever #define NFSROOT_RETRY_MAX 5 25743717c7dSChuck Lever 258a6a41d39SChristoph Hellwig static void __init mount_nfs_root(void) 2591da177e4SLinus Torvalds { 26056463e50SChuck Lever char *root_dev, *root_data; 26143717c7dSChuck Lever unsigned int timeout; 262a6a41d39SChristoph Hellwig int try; 2631da177e4SLinus Torvalds 264a6a41d39SChristoph Hellwig if (nfs_root_data(&root_dev, &root_data)) 265a6a41d39SChristoph Hellwig goto fail; 26643717c7dSChuck Lever 26743717c7dSChuck Lever /* 26843717c7dSChuck Lever * The server or network may not be ready, so try several 26943717c7dSChuck Lever * times. Stop after a few tries in case the client wants 27043717c7dSChuck Lever * to fall back to other boot methods. 27143717c7dSChuck Lever */ 27243717c7dSChuck Lever timeout = NFSROOT_TIMEOUT_MIN; 27343717c7dSChuck Lever for (try = 1; ; try++) { 274a6a41d39SChristoph Hellwig if (!do_mount_root(root_dev, "nfs", root_mountflags, root_data)) 275a6a41d39SChristoph Hellwig return; 27643717c7dSChuck Lever if (try > NFSROOT_RETRY_MAX) 27743717c7dSChuck Lever break; 27843717c7dSChuck Lever 27943717c7dSChuck Lever /* Wait, in case the server refused us immediately */ 28043717c7dSChuck Lever ssleep(timeout); 28143717c7dSChuck Lever timeout <<= 1; 28243717c7dSChuck Lever if (timeout > NFSROOT_TIMEOUT_MAX) 28343717c7dSChuck Lever timeout = NFSROOT_TIMEOUT_MAX; 28443717c7dSChuck Lever } 285a6a41d39SChristoph Hellwig fail: 286a6a41d39SChristoph Hellwig pr_err("VFS: Unable to mount root fs via NFS.\n"); 2871da177e4SLinus Torvalds } 288a6a41d39SChristoph Hellwig #else 289a6a41d39SChristoph Hellwig static inline void mount_nfs_root(void) 290a6a41d39SChristoph Hellwig { 291a6a41d39SChristoph Hellwig } 292a6a41d39SChristoph Hellwig #endif /* CONFIG_ROOT_NFS */ 2931da177e4SLinus Torvalds 2948902dd52SPaulo Alcantara (SUSE) #ifdef CONFIG_CIFS_ROOT 2958902dd52SPaulo Alcantara (SUSE) 2968902dd52SPaulo Alcantara (SUSE) #define CIFSROOT_TIMEOUT_MIN 5 2978902dd52SPaulo Alcantara (SUSE) #define CIFSROOT_TIMEOUT_MAX 30 2988902dd52SPaulo Alcantara (SUSE) #define CIFSROOT_RETRY_MAX 5 2998902dd52SPaulo Alcantara (SUSE) 300a6a41d39SChristoph Hellwig static void __init mount_cifs_root(void) 3018902dd52SPaulo Alcantara (SUSE) { 3028902dd52SPaulo Alcantara (SUSE) char *root_dev, *root_data; 3038902dd52SPaulo Alcantara (SUSE) unsigned int timeout; 304a6a41d39SChristoph Hellwig int try; 3058902dd52SPaulo Alcantara (SUSE) 306a6a41d39SChristoph Hellwig if (cifs_root_data(&root_dev, &root_data)) 307a6a41d39SChristoph Hellwig goto fail; 3088902dd52SPaulo Alcantara (SUSE) 3098902dd52SPaulo Alcantara (SUSE) timeout = CIFSROOT_TIMEOUT_MIN; 3108902dd52SPaulo Alcantara (SUSE) for (try = 1; ; try++) { 311a6a41d39SChristoph Hellwig if (!do_mount_root(root_dev, "cifs", root_mountflags, 312a6a41d39SChristoph Hellwig root_data)) 313a6a41d39SChristoph Hellwig return; 3148902dd52SPaulo Alcantara (SUSE) if (try > CIFSROOT_RETRY_MAX) 3158902dd52SPaulo Alcantara (SUSE) break; 3168902dd52SPaulo Alcantara (SUSE) 3178902dd52SPaulo Alcantara (SUSE) ssleep(timeout); 3188902dd52SPaulo Alcantara (SUSE) timeout <<= 1; 3198902dd52SPaulo Alcantara (SUSE) if (timeout > CIFSROOT_TIMEOUT_MAX) 3208902dd52SPaulo Alcantara (SUSE) timeout = CIFSROOT_TIMEOUT_MAX; 3218902dd52SPaulo Alcantara (SUSE) } 322a6a41d39SChristoph Hellwig fail: 323a6a41d39SChristoph Hellwig pr_err("VFS: Unable to mount root fs via SMB.\n"); 3248902dd52SPaulo Alcantara (SUSE) } 325a6a41d39SChristoph Hellwig #else 326a6a41d39SChristoph Hellwig static inline void mount_cifs_root(void) 327a6a41d39SChristoph Hellwig { 328a6a41d39SChristoph Hellwig } 329a6a41d39SChristoph Hellwig #endif /* CONFIG_CIFS_ROOT */ 3308902dd52SPaulo Alcantara (SUSE) 331f9259be6SChristoph Hellwig static bool __init fs_is_nodev(char *fstype) 332f9259be6SChristoph Hellwig { 333f9259be6SChristoph Hellwig struct file_system_type *fs = get_fs_type(fstype); 334f9259be6SChristoph Hellwig bool ret = false; 335f9259be6SChristoph Hellwig 336f9259be6SChristoph Hellwig if (fs) { 337f9259be6SChristoph Hellwig ret = !(fs->fs_flags & FS_REQUIRES_DEV); 338f9259be6SChristoph Hellwig put_filesystem(fs); 339f9259be6SChristoph Hellwig } 340f9259be6SChristoph Hellwig 341f9259be6SChristoph Hellwig return ret; 342f9259be6SChristoph Hellwig } 343f9259be6SChristoph Hellwig 344c8643c72SChristoph Hellwig static int __init mount_nodev_root(char *root_device_name) 345f9259be6SChristoph Hellwig { 346f9259be6SChristoph Hellwig char *fs_names, *fstype; 347f9259be6SChristoph Hellwig int err = -EINVAL; 3486e7c1770SChristoph Hellwig int num_fs, i; 349f9259be6SChristoph Hellwig 350f9259be6SChristoph Hellwig fs_names = (void *)__get_free_page(GFP_KERNEL); 351f9259be6SChristoph Hellwig if (!fs_names) 352f9259be6SChristoph Hellwig return -EINVAL; 35326e293f7SYihuan Pan num_fs = split_fs_names(fs_names, PAGE_SIZE); 354f9259be6SChristoph Hellwig 3556e7c1770SChristoph Hellwig for (i = 0, fstype = fs_names; i < num_fs; 3566e7c1770SChristoph Hellwig i++, fstype += strlen(fstype) + 1) { 357b51593c4SVivek Goyal if (!*fstype) 358b51593c4SVivek Goyal continue; 359f9259be6SChristoph Hellwig if (!fs_is_nodev(fstype)) 360f9259be6SChristoph Hellwig continue; 361f9259be6SChristoph Hellwig err = do_mount_root(root_device_name, fstype, root_mountflags, 362f9259be6SChristoph Hellwig root_mount_data); 363f9259be6SChristoph Hellwig if (!err) 364f9259be6SChristoph Hellwig break; 365f9259be6SChristoph Hellwig } 366f9259be6SChristoph Hellwig 367f9259be6SChristoph Hellwig free_page((unsigned long)fs_names); 368f9259be6SChristoph Hellwig return err; 369f9259be6SChristoph Hellwig } 370f9259be6SChristoph Hellwig 3719361401eSDavid Howells #ifdef CONFIG_BLOCK 372c8643c72SChristoph Hellwig static void __init mount_block_root(char *root_device_name) 373c69e3c3aSVishnu Pratap Singh { 374c69e3c3aSVishnu Pratap Singh int err = create_dev("/dev/root", ROOT_DEV); 375c69e3c3aSVishnu Pratap Singh 376c69e3c3aSVishnu Pratap Singh if (err < 0) 377c69e3c3aSVishnu Pratap Singh pr_emerg("Failed to create /dev/root: %d\n", err); 378c8643c72SChristoph Hellwig mount_root_generic("/dev/root", root_device_name, root_mountflags); 379c69e3c3aSVishnu Pratap Singh } 380a6a41d39SChristoph Hellwig #else 381c8643c72SChristoph Hellwig static inline void mount_block_root(char *root_device_name) 382a6a41d39SChristoph Hellwig { 383a6a41d39SChristoph Hellwig } 384a6a41d39SChristoph Hellwig #endif /* CONFIG_BLOCK */ 385a6a41d39SChristoph Hellwig 386c8643c72SChristoph Hellwig void __init mount_root(char *root_device_name) 387a6a41d39SChristoph Hellwig { 388a6a41d39SChristoph Hellwig switch (ROOT_DEV) { 389a6a41d39SChristoph Hellwig case Root_NFS: 390a6a41d39SChristoph Hellwig mount_nfs_root(); 391a6a41d39SChristoph Hellwig break; 392a6a41d39SChristoph Hellwig case Root_CIFS: 393a6a41d39SChristoph Hellwig mount_cifs_root(); 394a6a41d39SChristoph Hellwig break; 39507d63cbbSChristoph Hellwig case Root_Generic: 39607d63cbbSChristoph Hellwig mount_root_generic(root_device_name, root_device_name, 39707d63cbbSChristoph Hellwig root_mountflags); 39807d63cbbSChristoph Hellwig break; 399a6a41d39SChristoph Hellwig case 0: 400c8643c72SChristoph Hellwig if (root_device_name && root_fs_names && 401c8643c72SChristoph Hellwig mount_nodev_root(root_device_name) == 0) 402a6a41d39SChristoph Hellwig break; 403a6a41d39SChristoph Hellwig fallthrough; 404a6a41d39SChristoph Hellwig default: 405c8643c72SChristoph Hellwig mount_block_root(root_device_name); 406a6a41d39SChristoph Hellwig break; 407a6a41d39SChristoph Hellwig } 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds 4103701c600SChristoph Hellwig /* wait for any asynchronous scanning to complete */ 4113701c600SChristoph Hellwig static void __init wait_for_root(char *root_device_name) 4123701c600SChristoph Hellwig { 413*45071e1cSLoic Poulain ktime_t end; 414*45071e1cSLoic Poulain 4153701c600SChristoph Hellwig if (ROOT_DEV != 0) 4163701c600SChristoph Hellwig return; 4173701c600SChristoph Hellwig 4183701c600SChristoph Hellwig pr_info("Waiting for root device %s...\n", root_device_name); 4193701c600SChristoph Hellwig 420*45071e1cSLoic Poulain end = ktime_add_ms(ktime_get_raw(), root_wait); 421*45071e1cSLoic Poulain 422cf056a43SChristoph Hellwig while (!driver_probe_done() || 423*45071e1cSLoic Poulain early_lookup_bdev(root_device_name, &ROOT_DEV) < 0) { 4243701c600SChristoph Hellwig msleep(5); 425*45071e1cSLoic Poulain if (root_wait > 0 && ktime_after(ktime_get_raw(), end)) 426*45071e1cSLoic Poulain break; 427*45071e1cSLoic Poulain } 428*45071e1cSLoic Poulain 4293701c600SChristoph Hellwig async_synchronize_full(); 4303701c600SChristoph Hellwig 4313701c600SChristoph Hellwig } 4323701c600SChristoph Hellwig 43307d63cbbSChristoph Hellwig static dev_t __init parse_root_device(char *root_device_name) 43407d63cbbSChristoph Hellwig { 435079caa35SChristoph Hellwig int error; 436cf056a43SChristoph Hellwig dev_t dev; 437cf056a43SChristoph Hellwig 43807d63cbbSChristoph Hellwig if (!strncmp(root_device_name, "mtd", 3) || 43907d63cbbSChristoph Hellwig !strncmp(root_device_name, "ubi", 3)) 44007d63cbbSChristoph Hellwig return Root_Generic; 441c0c1a7dcSChristoph Hellwig if (strcmp(root_device_name, "/dev/nfs") == 0) 442c0c1a7dcSChristoph Hellwig return Root_NFS; 443c0c1a7dcSChristoph Hellwig if (strcmp(root_device_name, "/dev/cifs") == 0) 444c0c1a7dcSChristoph Hellwig return Root_CIFS; 445c0c1a7dcSChristoph Hellwig if (strcmp(root_device_name, "/dev/ram") == 0) 446c0c1a7dcSChristoph Hellwig return Root_RAM0; 447cf056a43SChristoph Hellwig 448079caa35SChristoph Hellwig error = early_lookup_bdev(root_device_name, &dev); 449079caa35SChristoph Hellwig if (error) { 450079caa35SChristoph Hellwig if (error == -EINVAL && root_wait) { 451079caa35SChristoph Hellwig pr_err("Disabling rootwait; root= is invalid.\n"); 452079caa35SChristoph Hellwig root_wait = 0; 453079caa35SChristoph Hellwig } 454cf056a43SChristoph Hellwig return 0; 455079caa35SChristoph Hellwig } 456cf056a43SChristoph Hellwig return dev; 4571da177e4SLinus Torvalds } 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds /* 4601da177e4SLinus Torvalds * Prepare the namespace - decide what/where to mount, load ramdisks, etc. 4611da177e4SLinus Torvalds */ 4621da177e4SLinus Torvalds void __init prepare_namespace(void) 4631da177e4SLinus Torvalds { 4641da177e4SLinus Torvalds if (root_delay) { 4651da177e4SLinus Torvalds printk(KERN_INFO "Waiting %d sec before mounting root device...\n", 4661da177e4SLinus Torvalds root_delay); 4671da177e4SLinus Torvalds ssleep(root_delay); 4681da177e4SLinus Torvalds } 4691da177e4SLinus Torvalds 470216773a7SArjan van de Ven /* 471216773a7SArjan van de Ven * wait for the known devices to complete their probing 472216773a7SArjan van de Ven * 473216773a7SArjan van de Ven * Note: this is a potential source of long boot delays. 474216773a7SArjan van de Ven * For example, it is not atypical to wait 5 seconds here 475216773a7SArjan van de Ven * for the touchpad of a laptop to initialize. 476216773a7SArjan van de Ven */ 477216773a7SArjan van de Ven wait_for_device_probe(); 478d779249eSGreg Kroah-Hartman 4791da177e4SLinus Torvalds md_run_setup(); 4801da177e4SLinus Torvalds 48107d63cbbSChristoph Hellwig if (saved_root_name[0]) 48207d63cbbSChristoph Hellwig ROOT_DEV = parse_root_device(saved_root_name); 4831da177e4SLinus Torvalds 48473231b58SChristoph Hellwig if (initrd_load(saved_root_name)) 4851da177e4SLinus Torvalds goto out; 4861da177e4SLinus Torvalds 4873701c600SChristoph Hellwig if (root_wait) 4883701c600SChristoph Hellwig wait_for_root(saved_root_name); 48973231b58SChristoph Hellwig mount_root(saved_root_name); 4901da177e4SLinus Torvalds out: 4915e787dbfSDominik Brodowski devtmpfs_mount(); 492c60166f0SChristoph Hellwig init_mount(".", "/", NULL, MS_MOVE, NULL); 4934b7ca501SChristoph Hellwig init_chroot("."); 4941da177e4SLinus Torvalds } 49557f150a5SRob Landley 4966e19ededSRob Landley static bool is_tmpfs; 497f3235626SDavid Howells static int rootfs_init_fs_context(struct fs_context *fc) 49857f150a5SRob Landley { 4996e19ededSRob Landley if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs) 500f3235626SDavid Howells return shmem_init_fs_context(fc); 5016e19ededSRob Landley 502f3235626SDavid Howells return ramfs_init_fs_context(fc); 50357f150a5SRob Landley } 50457f150a5SRob Landley 505fd3e007fSAl Viro struct file_system_type rootfs_fs_type = { 50657f150a5SRob Landley .name = "rootfs", 507f3235626SDavid Howells .init_fs_context = rootfs_init_fs_context, 50857f150a5SRob Landley .kill_sb = kill_litter_super, 50957f150a5SRob Landley }; 51057f150a5SRob Landley 511037f11b4SAl Viro void __init init_rootfs(void) 51257f150a5SRob Landley { 5136e19ededSRob Landley if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] && 514037f11b4SAl Viro (!root_fs_names || strstr(root_fs_names, "tmpfs"))) 5156e19ededSRob Landley is_tmpfs = true; 51657f150a5SRob Landley } 517