Blame view

init/do_mounts.c 14.8 KB
457c89965   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/ctype.h>
  #include <linux/fd.h>
  #include <linux/tty.h>
  #include <linux/suspend.h>
  #include <linux/root_dev.h>
  #include <linux/security.h>
  #include <linux/delay.h>
dd2a345f8   Dave Gilbert   Display all possi...
11
  #include <linux/genhd.h>
d53d9f16e   Andrew Morton   [PATCH] name_to_d...
12
  #include <linux/mount.h>
d779249ed   Greg Kroah-Hartman   Driver Core: add ...
13
  #include <linux/device.h>
46595390e   Adrian Bunk   init/do_mounts.c:...
14
  #include <linux/init.h>
011e3fcd1   Adrian Bunk   proper prototype ...
15
  #include <linux/fs.h>
82c8253ac   Adrian Bunk   init/do_mounts.c ...
16
  #include <linux/initrd.h>
22a9d6456   Arjan van de Ven   async: Asynchrono...
17
  #include <linux/async.h>
5ad4e53bd   Al Viro   Get rid of indire...
18
  #include <linux/fs_struct.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
57f150a58   Rob Landley   initmpfs: move ro...
20
  #include <linux/ramfs.h>
16203a7a9   Rob Landley   initmpfs: make ro...
21
  #include <linux/shmem_fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
23
24
25
  
  #include <linux/nfs_fs.h>
  #include <linux/nfs_fs_sb.h>
  #include <linux/nfs_mount.h>
4f5b246b3   Christoph Hellwig   md: move the earl...
26
  #include <linux/raid/detect.h>
e262e32d6   David Howells   vfs: Suppress MS_...
27
  #include <uapi/linux/mount.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
29
  
  #include "do_mounts.h"
9b04c997b   Theodore Ts'o   [PATCH] vfs: MS_V...
30
  int root_mountflags = MS_RDONLY | MS_SILENT;
f56f6d30c   Adrian Bunk   make init/do_moun...
31
  static char * __initdata root_device_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  static char __initdata saved_root_name[64];
79975f132   Will Drewry   init: add root=PA...
33
  static int root_wait;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  dev_t ROOT_DEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
  static int __init load_ramdisk(char *str)
  {
c8376994c   Christoph Hellwig   initrd: remove su...
38
39
  	pr_warn("ignoring the deprecated load_ramdisk= option
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  	return 1;
  }
  __setup("load_ramdisk=", load_ramdisk);
  
  static int __init readonly(char *str)
  {
  	if (*str)
  		return 0;
  	root_mountflags |= MS_RDONLY;
  	return 1;
  }
  
  static int __init readwrite(char *str)
  {
  	if (*str)
  		return 0;
  	root_mountflags &= ~MS_RDONLY;
  	return 1;
  }
  
  __setup("ro", readonly);
  __setup("rw", readwrite);
6d0aed7a3   Jens Axboe   do_mounts: only e...
62
  #ifdef CONFIG_BLOCK
1ad7e8994   Stephen Warren   block: store part...
63
64
65
66
  struct uuidcmp {
  	const char *uuid;
  	int len;
  };
b5af921ec   Will Drewry   init: add support...
67
68
69
  /**
   * match_dev_by_uuid - callback for finding a partition using its uuid
   * @dev:	device passed in by the caller
1ad7e8994   Stephen Warren   block: store part...
70
   * @data:	opaque pointer to the desired struct uuidcmp to match
b5af921ec   Will Drewry   init: add support...
71
72
73
   *
   * Returns 1 if the device matches, and 0 otherwise.
   */
9f3b795a6   Michał Mirosław   driver-core: cons...
74
  static int match_dev_by_uuid(struct device *dev, const void *data)
b5af921ec   Will Drewry   init: add support...
75
  {
9f3b795a6   Michał Mirosław   driver-core: cons...
76
  	const struct uuidcmp *cmp = data;
b5af921ec   Will Drewry   init: add support...
77
78
79
80
  	struct hd_struct *part = dev_to_part(dev);
  
  	if (!part->info)
  		goto no_match;
1ad7e8994   Stephen Warren   block: store part...
81
82
  	if (strncasecmp(cmp->uuid, part->info->uuid, cmp->len))
  		goto no_match;
b5af921ec   Will Drewry   init: add support...
83
84
85
86
87
88
89
90
91
  
  	return 1;
  no_match:
  	return 0;
  }
  
  
  /**
   * devt_from_partuuid - looks up the dev_t of a partition by its UUID
a68b31080   chishanmingshen   init/do_mounts.c:...
92
   * @uuid_str:	char array containing ascii UUID
b5af921ec   Will Drewry   init: add support...
93
94
95
96
97
   *
   * The function will return the first partition which contains a matching
   * UUID value in its partition_meta_info struct.  This does not search
   * by filesystem UUIDs.
   *
a68b31080   chishanmingshen   init/do_mounts.c:...
98
   * If @uuid_str is followed by a "/PARTNROFF=%d", then the number will be
79975f132   Will Drewry   init: add root=PA...
99
100
   * extracted and used as an offset from the partition identified by the UUID.
   *
b5af921ec   Will Drewry   init: add support...
101
102
   * Returns the matching dev_t on success or 0 on failure.
   */
1ad7e8994   Stephen Warren   block: store part...
103
  static dev_t devt_from_partuuid(const char *uuid_str)
b5af921ec   Will Drewry   init: add support...
104
105
  {
  	dev_t res = 0;
1ad7e8994   Stephen Warren   block: store part...
106
  	struct uuidcmp cmp;
b5af921ec   Will Drewry   init: add support...
107
  	struct device *dev = NULL;
79975f132   Will Drewry   init: add root=PA...
108
109
110
  	struct gendisk *disk;
  	struct hd_struct *part;
  	int offset = 0;
283f8fc03   Stephen Warren   init: reduce PART...
111
112
  	bool clear_root_wait = false;
  	char *slash;
79975f132   Will Drewry   init: add root=PA...
113

1ad7e8994   Stephen Warren   block: store part...
114
  	cmp.uuid = uuid_str;
1ad7e8994   Stephen Warren   block: store part...
115

283f8fc03   Stephen Warren   init: reduce PART...
116
  	slash = strchr(uuid_str, '/');
79975f132   Will Drewry   init: add root=PA...
117
  	/* Check for optional partition number offset attributes. */
283f8fc03   Stephen Warren   init: reduce PART...
118
  	if (slash) {
79975f132   Will Drewry   init: add root=PA...
119
120
  		char c = 0;
  		/* Explicitly fail on poor PARTUUID syntax. */
283f8fc03   Stephen Warren   init: reduce PART...
121
122
123
  		if (sscanf(slash + 1,
  			   "PARTNROFF=%d%c", &offset, &c) != 1) {
  			clear_root_wait = true;
79975f132   Will Drewry   init: add root=PA...
124
125
  			goto done;
  		}
283f8fc03   Stephen Warren   init: reduce PART...
126
127
128
129
130
131
132
133
  		cmp.len = slash - uuid_str;
  	} else {
  		cmp.len = strlen(uuid_str);
  	}
  
  	if (!cmp.len) {
  		clear_root_wait = true;
  		goto done;
79975f132   Will Drewry   init: add root=PA...
134
  	}
b5af921ec   Will Drewry   init: add support...
135

1ad7e8994   Stephen Warren   block: store part...
136
137
  	dev = class_find_device(&block_class, NULL, &cmp,
  				&match_dev_by_uuid);
b5af921ec   Will Drewry   init: add support...
138
139
140
141
  	if (!dev)
  		goto done;
  
  	res = dev->devt;
b5af921ec   Will Drewry   init: add support...
142

79975f132   Will Drewry   init: add root=PA...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  	/* Attempt to find the partition by offset. */
  	if (!offset)
  		goto no_offset;
  
  	res = 0;
  	disk = part_to_disk(dev_to_part(dev));
  	part = disk_get_part(disk, dev_to_part(dev)->partno + offset);
  	if (part) {
  		res = part_devt(part);
  		put_device(part_to_dev(part));
  	}
  
  no_offset:
  	put_device(dev);
b5af921ec   Will Drewry   init: add support...
157
  done:
283f8fc03   Stephen Warren   init: reduce PART...
158
159
160
161
162
163
164
165
166
167
  	if (clear_root_wait) {
  		pr_err("VFS: PARTUUID= is invalid.
  "
  		       "Expected PARTUUID=<valid-uuid-id>[/PARTNROFF=%%d]
  ");
  		if (root_wait)
  			pr_err("Disabling rootwait; root= is invalid.
  ");
  		root_wait = 0;
  	}
b5af921ec   Will Drewry   init: add support...
168
169
  	return res;
  }
f027c34d8   Nikolaus Voss   init/do_mounts.c:...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
  
  /**
   * match_dev_by_label - callback for finding a partition using its label
   * @dev:	device passed in by the caller
   * @data:	opaque pointer to the label to match
   *
   * Returns 1 if the device matches, and 0 otherwise.
   */
  static int match_dev_by_label(struct device *dev, const void *data)
  {
  	const char *label = data;
  	struct hd_struct *part = dev_to_part(dev);
  
  	if (part->info && !strcmp(label, part->info->volname))
  		return 1;
  
  	return 0;
  }
6d0aed7a3   Jens Axboe   do_mounts: only e...
188
  #endif
b5af921ec   Will Drewry   init: add support...
189

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
191
192
  /*
   *	Convert a name into device number.  We accept the following variants:
   *
0bf37ae4c   Pavel Machek   init/do_mounts: b...
193
194
   *	1) <hex_major><hex_minor> device number in hexadecimal represents itself
   *         no leading 0x, for example b302.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
196
197
198
199
200
   *	2) /dev/nfs represents Root_NFS (0xff)
   *	3) /dev/<disk_name> represents the device number of disk
   *	4) /dev/<disk_name><decimal> represents the device number
   *         of partition - device number of disk plus the partition number
   *	5) /dev/<disk_name>p<decimal> - same as the above, that form is
   *	   used when disk name of partitioned disk ends on a digit.
b5af921ec   Will Drewry   init: add support...
201
202
   *	6) PARTUUID=00112233-4455-6677-8899-AABBCCDDEEFF representing the
   *	   unique id of a partition if the partition table provides it.
d33b98fc8   Stephen Warren   block: partition:...
203
204
205
206
   *	   The UUID may be either an EFI/GPT UUID, or refer to an MSDOS
   *	   partition using the format SSSSSSSS-PP, where SSSSSSSS is a zero-
   *	   filled hex representation of the 32-bit "NT disk signature", and PP
   *	   is a zero-filled hex representation of the 1-based partition number.
79975f132   Will Drewry   init: add root=PA...
207
208
   *	7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to
   *	   a partition with a known unique id.
6c251611c   Sebastian Capella   init/do_mounts.c:...
209
210
   *	8) <major>:<minor> major and minor number of the device separated by
   *	   a colon.
f027c34d8   Nikolaus Voss   init/do_mounts.c:...
211
212
   *	9) PARTLABEL=<name> with name being the GPT partition label.
   *	   MSDOS partitions do not support labels!
8902dd526   Paulo Alcantara (SUSE)   init: Support mou...
213
   *	10) /dev/cifs represents Root_CIFS (0xfe)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
   *
edfaa7c36   Kay Sievers   Driver core: conv...
215
216
217
218
   *	If name doesn't have fall into the categories above, we return (0,0).
   *	block_class is used to check if something is a disk name. If the disk
   *	name contains slashes, the device name has them replaced with
   *	bangs.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
   */
e6e20a7a5   Dan Ehrenberg   init: export name...
220
  dev_t name_to_dev_t(const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
  {
  	char s[32];
  	char *p;
  	dev_t res = 0;
30f2f0eb4   Kay Sievers   block: do_mounts ...
225
  	int part;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226

6d0aed7a3   Jens Axboe   do_mounts: only e...
227
  #ifdef CONFIG_BLOCK
b5af921ec   Will Drewry   init: add support...
228
229
  	if (strncmp(name, "PARTUUID=", 9) == 0) {
  		name += 9;
b5af921ec   Will Drewry   init: add support...
230
231
232
233
  		res = devt_from_partuuid(name);
  		if (!res)
  			goto fail;
  		goto done;
f027c34d8   Nikolaus Voss   init/do_mounts.c:...
234
235
236
237
238
239
240
241
242
243
244
  	} else if (strncmp(name, "PARTLABEL=", 10) == 0) {
  		struct device *dev;
  
  		dev = class_find_device(&block_class, NULL, name + 10,
  					&match_dev_by_label);
  		if (!dev)
  			goto fail;
  
  		res = dev->devt;
  		put_device(dev);
  		goto done;
b5af921ec   Will Drewry   init: add support...
245
  	}
6d0aed7a3   Jens Axboe   do_mounts: only e...
246
  #endif
b5af921ec   Will Drewry   init: add support...
247

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248
  	if (strncmp(name, "/dev/", 5) != 0) {
cb31ef485   Chen Yu   init: fix regress...
249
  		unsigned maj, min, offset;
283e7ad02   Dan Ehrenberg   init: stricter ch...
250
  		char dummy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251

cb31ef485   Chen Yu   init: fix regress...
252
253
  		if ((sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2) ||
  		    (sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset, &dummy) == 3)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
256
257
258
259
260
261
262
263
  			res = MKDEV(maj, min);
  			if (maj != MAJOR(res) || min != MINOR(res))
  				goto fail;
  		} else {
  			res = new_decode_dev(simple_strtoul(name, &p, 16));
  			if (*p)
  				goto fail;
  		}
  		goto done;
  	}
edfaa7c36   Kay Sievers   Driver core: conv...
264

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
265
266
267
268
  	name += 5;
  	res = Root_NFS;
  	if (strcmp(name, "nfs") == 0)
  		goto done;
8902dd526   Paulo Alcantara (SUSE)   init: Support mou...
269
270
271
  	res = Root_CIFS;
  	if (strcmp(name, "cifs") == 0)
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
275
276
277
278
279
280
281
  	res = Root_RAM0;
  	if (strcmp(name, "ram") == 0)
  		goto done;
  
  	if (strlen(name) > 31)
  		goto fail;
  	strcpy(s, name);
  	for (p = s; *p; p++)
  		if (*p == '/')
  			*p = '!';
30f2f0eb4   Kay Sievers   block: do_mounts ...
282
283
284
285
286
  	res = blk_lookup_devt(s, 0);
  	if (res)
  		goto done;
  
  	/*
25985edce   Lucas De Marchi   Fix common misspe...
287
  	 * try non-existent, but valid partition, which may only exist
30f2f0eb4   Kay Sievers   block: do_mounts ...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  	 * after revalidating the disk, like partitioned md devices
  	 */
  	while (p > s && isdigit(p[-1]))
  		p--;
  	if (p == s || !*p || *p == '0')
  		goto fail;
  
  	/* try disk name without <part number> */
  	part = simple_strtoul(p, NULL, 10);
  	*p = '\0';
  	res = blk_lookup_devt(s, part);
  	if (res)
  		goto done;
  
  	/* try disk name without p<part number> */
  	if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p')
  		goto fail;
  	p[-1] = '\0';
  	res = blk_lookup_devt(s, part);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
  	if (res)
  		goto done;
edfaa7c36   Kay Sievers   Driver core: conv...
309
310
  fail:
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
  	return res;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
  }
e6e20a7a5   Dan Ehrenberg   init: export name...
314
  EXPORT_SYMBOL_GPL(name_to_dev_t);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
315
316
317
318
319
320
321
322
  
  static int __init root_dev_setup(char *line)
  {
  	strlcpy(saved_root_name, line, sizeof(saved_root_name));
  	return 1;
  }
  
  __setup("root=", root_dev_setup);
cc1ed7542   Pierre Ossman   init: wait for as...
323
324
325
326
327
328
329
330
331
  static int __init rootwait_setup(char *str)
  {
  	if (*str)
  		return 0;
  	root_wait = 1;
  	return 1;
  }
  
  __setup("rootwait", rootwait_setup);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
  static char * __initdata root_mount_data;
  static int __init root_data_setup(char *str)
  {
  	root_mount_data = str;
  	return 1;
  }
  
  static char * __initdata root_fs_names;
  static int __init fs_names_setup(char *str)
  {
  	root_fs_names = str;
  	return 1;
  }
  
  static unsigned int __initdata root_delay;
  static int __init root_delay_setup(char *str)
  {
  	root_delay = simple_strtoul(str, NULL, 0);
  	return 1;
  }
  
  __setup("rootflags=", root_data_setup);
  __setup("rootfstype=", fs_names_setup);
  __setup("rootdelay=", root_delay_setup);
  
  static void __init get_fs_names(char *page)
  {
  	char *s = page;
  
  	if (root_fs_names) {
  		strcpy(page, root_fs_names);
  		while (*s++) {
  			if (s[-1] == ',')
  				s[-1] = '\0';
  		}
  	} else {
  		int len = get_filesystem_list(page);
  		char *p, *next;
  
  		page[len] = '\0';
  		for (p = page-1; p; p = next) {
  			next = strchr(++p, '
  ');
  			if (*p++ != '\t')
  				continue;
  			while ((*s++ = *p++) != '
  ')
  				;
  			s[-1] = '\0';
  		}
  	}
  	*s = '\0';
  }
cccaa5e33   Dominik Brodowski   init: use do_moun...
385
386
  static int __init do_mount_root(const char *name, const char *fs,
  				 const int flags, const void *data)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
  {
d8c9584ea   Al Viro   vfs: prefer ->den...
388
  	struct super_block *s;
7de7de7ca   Linus Torvalds   Fix root mounting...
389
390
  	struct page *p = NULL;
  	char *data_page = NULL;
cccaa5e33   Dominik Brodowski   init: use do_moun...
391
  	int ret;
7de7de7ca   Linus Torvalds   Fix root mounting...
392
  	if (data) {
c60166f04   Christoph Hellwig   init: add an init...
393
  		/* init_mount() requires a full page as fifth argument */
7de7de7ca   Linus Torvalds   Fix root mounting...
394
395
396
397
  		p = alloc_page(GFP_KERNEL);
  		if (!p)
  			return -ENOMEM;
  		data_page = page_address(p);
c60166f04   Christoph Hellwig   init: add an init...
398
  		/* zero-pad. init_mount() will make sure it's terminated */
7de7de7ca   Linus Torvalds   Fix root mounting...
399
400
  		strncpy(data_page, data, PAGE_SIZE);
  	}
cccaa5e33   Dominik Brodowski   init: use do_moun...
401

c60166f04   Christoph Hellwig   init: add an init...
402
  	ret = init_mount(name, "/root", fs, flags, data_page);
cccaa5e33   Dominik Brodowski   init: use do_moun...
403
404
  	if (ret)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405

db63f1e31   Christoph Hellwig   init: add an init...
406
  	init_chdir("/root");
d8c9584ea   Al Viro   vfs: prefer ->den...
407
408
  	s = current->fs->pwd.dentry->d_sb;
  	ROOT_DEV = s->s_dev;
80cdc6dae   Mandeep Singh Baines   fs: use appropria...
409
410
411
  	printk(KERN_INFO
  	       "VFS: Mounted root (%s filesystem)%s on device %u:%u.
  ",
d8c9584ea   Al Viro   vfs: prefer ->den...
412
  	       s->s_type->name,
bc98a42c1   David Howells   VFS: Convert sb->...
413
  	       sb_rdonly(s) ? " readonly" : "",
d8c9584ea   Al Viro   vfs: prefer ->den...
414
  	       MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
cccaa5e33   Dominik Brodowski   init: use do_moun...
415
416
  
  out:
7de7de7ca   Linus Torvalds   Fix root mounting...
417
418
  	if (p)
  		put_page(p);
cccaa5e33   Dominik Brodowski   init: use do_moun...
419
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
  }
  
  void __init mount_block_root(char *name, int flags)
  {
75f296d93   Levin, Alexander (Sasha Levin)   kmemcheck: stop u...
424
  	struct page *page = alloc_page(GFP_KERNEL);
a608ca21f   Jeff Layton   vfs: allocate pag...
425
  	char *fs_names = page_address(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  	char *p;
  	char b[BDEVNAME_SIZE];
ea3edd4dc   Christoph Hellwig   block: remove __b...
428
429
  	scnprintf(b, BDEVNAME_SIZE, "unknown-block(%u,%u)",
  		  MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
430
431
432
433
434
435
436
437
  	get_fs_names(fs_names);
  retry:
  	for (p = fs_names; *p; p += strlen(p)+1) {
  		int err = do_mount_root(name, p, flags, root_mount_data);
  		switch (err) {
  			case 0:
  				goto out;
  			case -EACCES:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
438
439
440
441
442
443
  			case -EINVAL:
  				continue;
  		}
  	        /*
  		 * Allow the user to distinguish between failed sys_open
  		 * and bad superblock on root device.
dd2a345f8   Dave Gilbert   Display all possi...
444
  		 * and give them a list of the available devices
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
445
  		 */
0e0cb892a   Bernhard Walle   init/do_mounts.c:...
446
447
448
  		printk("VFS: Cannot open root device \"%s\" or %s: error %d
  ",
  				root_device_name, b, err);
dd2a345f8   Dave Gilbert   Display all possi...
449
450
  		printk("Please append a correct \"root=\" boot option; here are the available partitions:
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451

dd2a345f8   Dave Gilbert   Display all possi...
452
  		printk_all_partitions();
55dc7db70   Tejun Heo   init: DEBUG_BLOCK...
453
454
455
456
457
  #ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT
  		printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify "
  		       "explicit textual name for \"root=\" boot option.
  ");
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
  		panic("VFS: Unable to mount root fs on %s", b);
  	}
e462ec50c   David Howells   VFS: Differentiat...
460
461
  	if (!(flags & SB_RDONLY)) {
  		flags |= SB_RDONLY;
10975933d   Miklos Szeredi   init: fix read-wr...
462
463
  		goto retry;
  	}
be6e028b6   Andy Whitcroft   [PATCH] root moun...
464

dd2a345f8   Dave Gilbert   Display all possi...
465
466
467
  	printk("List of all partitions:
  ");
  	printk_all_partitions();
be6e028b6   Andy Whitcroft   [PATCH] root moun...
468
469
470
471
472
  	printk("No filesystem could mount root, tried: ");
  	for (p = fs_names; *p; p += strlen(p)+1)
  		printk(" %s", p);
  	printk("
  ");
9361401eb   David Howells   [PATCH] BLOCK: Ma...
473
  	panic("VFS: Unable to mount root fs on %s", b);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
  out:
a608ca21f   Jeff Layton   vfs: allocate pag...
475
  	put_page(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
477
478
  }
   
  #ifdef CONFIG_ROOT_NFS
43717c7da   Chuck Lever   NFS: Retry mounti...
479
480
481
482
  
  #define NFSROOT_TIMEOUT_MIN	5
  #define NFSROOT_TIMEOUT_MAX	30
  #define NFSROOT_RETRY_MAX	5
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
484
  static int __init mount_nfs_root(void)
  {
56463e50d   Chuck Lever   NFS: Use super.c ...
485
  	char *root_dev, *root_data;
43717c7da   Chuck Lever   NFS: Retry mounti...
486
487
  	unsigned int timeout;
  	int try, err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488

43717c7da   Chuck Lever   NFS: Retry mounti...
489
490
  	err = nfs_root_data(&root_dev, &root_data);
  	if (err != 0)
56463e50d   Chuck Lever   NFS: Use super.c ...
491
  		return 0;
43717c7da   Chuck Lever   NFS: Retry mounti...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
  
  	/*
  	 * The server or network may not be ready, so try several
  	 * times.  Stop after a few tries in case the client wants
  	 * to fall back to other boot methods.
  	 */
  	timeout = NFSROOT_TIMEOUT_MIN;
  	for (try = 1; ; try++) {
  		err = do_mount_root(root_dev, "nfs",
  					root_mountflags, root_data);
  		if (err == 0)
  			return 1;
  		if (try > NFSROOT_RETRY_MAX)
  			break;
  
  		/* Wait, in case the server refused us immediately */
  		ssleep(timeout);
  		timeout <<= 1;
  		if (timeout > NFSROOT_TIMEOUT_MAX)
  			timeout = NFSROOT_TIMEOUT_MAX;
  	}
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  }
  #endif
8902dd526   Paulo Alcantara (SUSE)   init: Support mou...
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  #ifdef CONFIG_CIFS_ROOT
  
  extern int cifs_root_data(char **dev, char **opts);
  
  #define CIFSROOT_TIMEOUT_MIN	5
  #define CIFSROOT_TIMEOUT_MAX	30
  #define CIFSROOT_RETRY_MAX	5
  
  static int __init mount_cifs_root(void)
  {
  	char *root_dev, *root_data;
  	unsigned int timeout;
  	int try, err;
  
  	err = cifs_root_data(&root_dev, &root_data);
  	if (err != 0)
  		return 0;
  
  	timeout = CIFSROOT_TIMEOUT_MIN;
  	for (try = 1; ; try++) {
  		err = do_mount_root(root_dev, "cifs", root_mountflags,
  				    root_data);
  		if (err == 0)
  			return 1;
  		if (try > CIFSROOT_RETRY_MAX)
  			break;
  
  		ssleep(timeout);
  		timeout <<= 1;
  		if (timeout > CIFSROOT_TIMEOUT_MAX)
  			timeout = CIFSROOT_TIMEOUT_MAX;
  	}
  	return 0;
  }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
  void __init mount_root(void)
  {
  #ifdef CONFIG_ROOT_NFS
377485f62   Sasha Levin   init: don't try m...
554
  	if (ROOT_DEV == Root_NFS) {
c8376994c   Christoph Hellwig   initrd: remove su...
555
556
557
558
  		if (!mount_nfs_root())
  			printk(KERN_ERR "VFS: Unable to mount root fs via NFS.
  ");
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
  	}
  #endif
8902dd526   Paulo Alcantara (SUSE)   init: Support mou...
561
562
  #ifdef CONFIG_CIFS_ROOT
  	if (ROOT_DEV == Root_CIFS) {
c8376994c   Christoph Hellwig   initrd: remove su...
563
564
565
566
  		if (!mount_cifs_root())
  			printk(KERN_ERR "VFS: Unable to mount root fs via SMB.
  ");
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
  	}
  #endif
9361401eb   David Howells   [PATCH] BLOCK: Ma...
569
  #ifdef CONFIG_BLOCK
c69e3c3a0   Vishnu Pratap Singh   init/do_mounts.c:...
570
571
572
573
574
575
576
577
  	{
  		int err = create_dev("/dev/root", ROOT_DEV);
  
  		if (err < 0)
  			pr_emerg("Failed to create /dev/root: %d
  ", err);
  		mount_block_root("/dev/root", root_mountflags);
  	}
9361401eb   David Howells   [PATCH] BLOCK: Ma...
578
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
582
583
584
585
  }
  
  /*
   * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
   */
  void __init prepare_namespace(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  	if (root_delay) {
ca75b4d87   Toralf Förster   insert missing sp...
587
588
  		printk(KERN_INFO "Waiting %d sec before mounting root device...
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
  		       root_delay);
  		ssleep(root_delay);
  	}
216773a78   Arjan van de Ven   Consolidate drive...
592
593
594
595
596
597
598
599
  	/*
  	 * wait for the known devices to complete their probing
  	 *
  	 * Note: this is a potential source of long boot delays.
  	 * For example, it is not atypical to wait 5 seconds here
  	 * for the touchpad of a laptop to initialize.
  	 */
  	wait_for_device_probe();
d779249ed   Greg Kroah-Hartman   Driver Core: add ...
600

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
602
603
604
  	md_run_setup();
  
  	if (saved_root_name[0]) {
  		root_device_name = saved_root_name;
2d62f4885   Adrian Hunter   do_mounts: allow ...
605
606
  		if (!strncmp(root_device_name, "mtd", 3) ||
  		    !strncmp(root_device_name, "ubi", 3)) {
e9482b437   Joern Engel   [MTD] Allow alter...
607
608
609
  			mount_block_root(root_device_name, root_mountflags);
  			goto out;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
610
611
612
613
  		ROOT_DEV = name_to_dev_t(root_device_name);
  		if (strncmp(root_device_name, "/dev/", 5) == 0)
  			root_device_name += 5;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
614
615
  	if (initrd_load())
  		goto out;
cc1ed7542   Pierre Ossman   init: wait for as...
616
617
618
619
620
621
622
  	/* wait for any asynchronous scanning to complete */
  	if ((ROOT_DEV == 0) && root_wait) {
  		printk(KERN_INFO "Waiting for root device %s...
  ",
  			saved_root_name);
  		while (driver_probe_done() != 0 ||
  			(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
39a0e975c   Jungseung Lee   init: reduce root...
623
  			msleep(5);
216773a78   Arjan van de Ven   Consolidate drive...
624
  		async_synchronize_full();
cc1ed7542   Pierre Ossman   init: wait for as...
625
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
  	mount_root();
  out:
5e787dbf6   Dominik Brodowski   devtmpfs: use do_...
628
  	devtmpfs_mount();
c60166f04   Christoph Hellwig   init: add an init...
629
  	init_mount(".", "/", NULL, MS_MOVE, NULL);
4b7ca5014   Christoph Hellwig   init: add an init...
630
  	init_chroot(".");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  }
57f150a58   Rob Landley   initmpfs: move ro...
632

6e19eded3   Rob Landley   initmpfs: use ini...
633
  static bool is_tmpfs;
f32356261   David Howells   vfs: Convert ramf...
634
  static int rootfs_init_fs_context(struct fs_context *fc)
57f150a58   Rob Landley   initmpfs: move ro...
635
  {
6e19eded3   Rob Landley   initmpfs: use ini...
636
  	if (IS_ENABLED(CONFIG_TMPFS) && is_tmpfs)
f32356261   David Howells   vfs: Convert ramf...
637
  		return shmem_init_fs_context(fc);
6e19eded3   Rob Landley   initmpfs: use ini...
638

f32356261   David Howells   vfs: Convert ramf...
639
  	return ramfs_init_fs_context(fc);
57f150a58   Rob Landley   initmpfs: move ro...
640
  }
fd3e007f6   Al Viro   don't bother with...
641
  struct file_system_type rootfs_fs_type = {
57f150a58   Rob Landley   initmpfs: move ro...
642
  	.name		= "rootfs",
f32356261   David Howells   vfs: Convert ramf...
643
  	.init_fs_context = rootfs_init_fs_context,
57f150a58   Rob Landley   initmpfs: move ro...
644
645
  	.kill_sb	= kill_litter_super,
  };
037f11b47   Al Viro   mnt_init(): call ...
646
  void __init init_rootfs(void)
57f150a58   Rob Landley   initmpfs: move ro...
647
  {
6e19eded3   Rob Landley   initmpfs: use ini...
648
  	if (IS_ENABLED(CONFIG_TMPFS) && !saved_root_name[0] &&
037f11b47   Al Viro   mnt_init(): call ...
649
  		(!root_fs_names || strstr(root_fs_names, "tmpfs")))
6e19eded3   Rob Landley   initmpfs: use ini...
650
  		is_tmpfs = true;
57f150a58   Rob Landley   initmpfs: move ro...
651
  }