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