OSDN Git Service

Merge 4.4.186 into android-4.4
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / init / do_mounts_dm.c
1 /* do_mounts_dm.c
2  * Copyright (C) 2010 The Chromium OS Authors <chromium-os-dev@chromium.org>
3  *                    All Rights Reserved.
4  * Based on do_mounts_md.c
5  *
6  * This file is released under the GPL.
7  */
8 #include <linux/async.h>
9 #include <linux/ctype.h>
10 #include <linux/device-mapper.h>
11 #include <linux/fs.h>
12 #include <linux/string.h>
13 #include <linux/delay.h>
14
15 #include "do_mounts.h"
16
17 #define DM_MAX_DEVICES 256
18 #define DM_MAX_TARGETS 256
19 #define DM_MAX_NAME 32
20 #define DM_MAX_UUID 129
21 #define DM_NO_UUID "none"
22
23 #define DM_MSG_PREFIX "init"
24
25 /* Separators used for parsing the dm= argument. */
26 #define DM_FIELD_SEP " "
27 #define DM_LINE_SEP ","
28 #define DM_ANY_SEP DM_FIELD_SEP DM_LINE_SEP
29
30 /*
31  * When the device-mapper and any targets are compiled into the kernel
32  * (not a module), one or more device-mappers may be created and used
33  * as the root device at boot time with the parameters given with the
34  * boot line dm=...
35  *
36  * Multiple device-mappers can be stacked specifing the number of
37  * devices. A device can have multiple targets if the the number of
38  * targets is specified.
39  *
40  * TODO(taysom:defect 32847)
41  * In the future, the <num> field will be mandatory.
42  *
43  * <device>        ::= [<num>] <device-mapper>+
44  * <device-mapper> ::= <head> "," <target>+
45  * <head>          ::= <name> <uuid> <mode> [<num>]
46  * <target>        ::= <start> <length> <type> <options> ","
47  * <mode>          ::= "ro" | "rw"
48  * <uuid>          ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | "none"
49  * <type>          ::= "verity" | "bootcache" | ...
50  *
51  * Example:
52  * 2 vboot none ro 1,
53  *     0 1768000 bootcache
54  *       device=aa55b119-2a47-8c45-946a-5ac57765011f+1
55  *       signature=76e9be054b15884a9fa85973e9cb274c93afadb6
56  *       cache_start=1768000 max_blocks=100000 size_limit=23 max_trace=20000,
57  *   vroot none ro 1,
58  *     0 1740800 verity payload=254:0 hashtree=254:0 hashstart=1740800 alg=sha1
59  *       root_hexdigest=76e9be054b15884a9fa85973e9cb274c93afadb6
60  *       salt=5b3549d54d6c7a3837b9b81ed72e49463a64c03680c47835bef94d768e5646fe
61  *
62  * Notes:
63  *  1. uuid is a label for the device and we set it to "none".
64  *  2. The <num> field will be optional initially and assumed to be 1.
65  *     Once all the scripts that set these fields have been set, it will
66  *     be made mandatory.
67  */
68
69 struct dm_setup_target {
70         sector_t begin;
71         sector_t length;
72         char *type;
73         char *params;
74         /* simple singly linked list */
75         struct dm_setup_target *next;
76 };
77
78 struct dm_device {
79         int minor;
80         int ro;
81         char name[DM_MAX_NAME];
82         char uuid[DM_MAX_UUID];
83         unsigned long num_targets;
84         struct dm_setup_target *target;
85         int target_count;
86         struct dm_device *next;
87 };
88
89 struct dm_option {
90         char *start;
91         char *next;
92         size_t len;
93         char delim;
94 };
95
96 static struct {
97         unsigned long num_devices;
98         char *str;
99 } dm_setup_args __initdata;
100
101 static __initdata int dm_early_setup;
102
103 static int __init get_dm_option(struct dm_option *opt, const char *accept)
104 {
105         char *str = opt->next;
106         char *endp;
107
108         if (!str)
109                 return 0;
110
111         str = skip_spaces(str);
112         opt->start = str;
113         endp = strpbrk(str, accept);
114         if (!endp) {  /* act like strchrnul */
115                 opt->len = strlen(str);
116                 endp = str + opt->len;
117         } else {
118                 opt->len = endp - str;
119         }
120         opt->delim = *endp;
121         if (*endp == 0) {
122                 /* Don't advance past the nul. */
123                 opt->next = endp;
124         } else {
125                 opt->next = endp + 1;
126         }
127         return opt->len != 0;
128 }
129
130 static int __init dm_setup_cleanup(struct dm_device *devices)
131 {
132         struct dm_device *dev = devices;
133
134         while (dev) {
135                 struct dm_device *old_dev = dev;
136                 struct dm_setup_target *target = dev->target;
137                 while (target) {
138                         struct dm_setup_target *old_target = target;
139                         kfree(target->type);
140                         kfree(target->params);
141                         target = target->next;
142                         kfree(old_target);
143                         dev->target_count--;
144                 }
145                 BUG_ON(dev->target_count);
146                 dev = dev->next;
147                 kfree(old_dev);
148         }
149         return 0;
150 }
151
152 static char * __init dm_parse_device(struct dm_device *dev, char *str)
153 {
154         struct dm_option opt;
155         size_t len;
156
157         /* Grab the logical name of the device to be exported to udev */
158         opt.next = str;
159         if (!get_dm_option(&opt, DM_FIELD_SEP)) {
160                 DMERR("failed to parse device name");
161                 goto parse_fail;
162         }
163         len = min(opt.len + 1, sizeof(dev->name));
164         strlcpy(dev->name, opt.start, len);  /* includes nul */
165
166         /* Grab the UUID value or "none" */
167         if (!get_dm_option(&opt, DM_FIELD_SEP)) {
168                 DMERR("failed to parse device uuid");
169                 goto parse_fail;
170         }
171         len = min(opt.len + 1, sizeof(dev->uuid));
172         strlcpy(dev->uuid, opt.start, len);
173
174         /* Determine if the table/device will be read only or read-write */
175         get_dm_option(&opt, DM_ANY_SEP);
176         if (!strncmp("ro", opt.start, opt.len)) {
177                 dev->ro = 1;
178         } else if (!strncmp("rw", opt.start, opt.len)) {
179                 dev->ro = 0;
180         } else {
181                 DMERR("failed to parse table mode");
182                 goto parse_fail;
183         }
184
185         /* Optional number field */
186         /* XXX: The <num> field will be mandatory in the next round */
187         if (opt.delim == DM_FIELD_SEP[0]) {
188                 if (!get_dm_option(&opt, DM_LINE_SEP))
189                         return NULL;
190                 dev->num_targets = simple_strtoul(opt.start, NULL, 10);
191         } else {
192                 dev->num_targets = 1;
193         }
194         if (dev->num_targets > DM_MAX_TARGETS) {
195                 DMERR("too many targets %lu > %d",
196                         dev->num_targets, DM_MAX_TARGETS);
197         }
198         return opt.next;
199
200 parse_fail:
201         return NULL;
202 }
203
204 static char * __init dm_parse_targets(struct dm_device *dev, char *str)
205 {
206         struct dm_option opt;
207         struct dm_setup_target **target = &dev->target;
208         unsigned long num_targets = dev->num_targets;
209         unsigned long i;
210
211         /* Targets are defined as per the table format but with a
212          * comma as a newline separator. */
213         opt.next = str;
214         for (i = 0; i < num_targets; i++) {
215                 *target = kzalloc(sizeof(struct dm_setup_target), GFP_KERNEL);
216                 if (!*target) {
217                         DMERR("failed to allocate memory for target %s<%ld>",
218                                 dev->name, i);
219                         goto parse_fail;
220                 }
221                 dev->target_count++;
222
223                 if (!get_dm_option(&opt, DM_FIELD_SEP)) {
224                         DMERR("failed to parse starting sector"
225                                 " for target %s<%ld>", dev->name, i);
226                         goto parse_fail;
227                 }
228                 (*target)->begin = simple_strtoull(opt.start, NULL, 10);
229
230                 if (!get_dm_option(&opt, DM_FIELD_SEP)) {
231                         DMERR("failed to parse length for target %s<%ld>",
232                                 dev->name, i);
233                         goto parse_fail;
234                 }
235                 (*target)->length = simple_strtoull(opt.start, NULL, 10);
236
237                 if (get_dm_option(&opt, DM_FIELD_SEP))
238                         (*target)->type = kstrndup(opt.start, opt.len,
239                                                         GFP_KERNEL);
240                 if (!((*target)->type)) {
241                         DMERR("failed to parse type for target %s<%ld>",
242                                 dev->name, i);
243                         goto parse_fail;
244                 }
245                 if (get_dm_option(&opt, DM_LINE_SEP))
246                         (*target)->params = kstrndup(opt.start, opt.len,
247                                                         GFP_KERNEL);
248                 if (!((*target)->params)) {
249                         DMERR("failed to parse params for target %s<%ld>",
250                                 dev->name, i);
251                         goto parse_fail;
252                 }
253                 target = &((*target)->next);
254         }
255         DMDEBUG("parsed %d targets", dev->target_count);
256
257         return opt.next;
258
259 parse_fail:
260         return NULL;
261 }
262
263 static struct dm_device * __init dm_parse_args(void)
264 {
265         struct dm_device *devices = NULL;
266         struct dm_device **tail = &devices;
267         struct dm_device *dev;
268         char *str = dm_setup_args.str;
269         unsigned long num_devices = dm_setup_args.num_devices;
270         unsigned long i;
271
272         if (!str)
273                 return NULL;
274         for (i = 0; i < num_devices; i++) {
275                 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
276                 if (!dev) {
277                         DMERR("failed to allocated memory for dev");
278                         goto error;
279                 }
280                 *tail = dev;
281                 tail = &dev->next;
282                 /*
283                  * devices are given minor numbers 0 - n-1
284                  * in the order they are found in the arg
285                  * string.
286                  */
287                 dev->minor = i;
288                 str = dm_parse_device(dev, str);
289                 if (!str)       /* NULL indicates error in parsing, bail */
290                         goto error;
291
292                 str = dm_parse_targets(dev, str);
293                 if (!str)
294                         goto error;
295         }
296         return devices;
297 error:
298         dm_setup_cleanup(devices);
299         return NULL;
300 }
301
302 /*
303  * Parse the command-line parameters given our kernel, but do not
304  * actually try to invoke the DM device now; that is handled by
305  * dm_setup_drives after the low-level disk drivers have initialised.
306  * dm format is described at the top of the file.
307  *
308  * Because dm minor numbers are assigned in assending order starting with 0,
309  * You can assume the first device is /dev/dm-0, the next device is /dev/dm-1,
310  * and so forth.
311  */
312 static int __init dm_setup(char *str)
313 {
314         struct dm_option opt;
315         unsigned long num_devices;
316
317         if (!str) {
318                 DMDEBUG("str is NULL");
319                 goto parse_fail;
320         }
321         opt.next = str;
322         if (!get_dm_option(&opt, DM_FIELD_SEP))
323                 goto parse_fail;
324         if (isdigit(opt.start[0])) {    /* XXX: Optional number field */
325                 num_devices = simple_strtoul(opt.start, NULL, 10);
326                 str = opt.next;
327         } else {
328                 num_devices = 1;
329                 /* Don't advance str */
330         }
331         if (num_devices > DM_MAX_DEVICES) {
332                 DMDEBUG("too many devices %lu > %d",
333                         num_devices, DM_MAX_DEVICES);
334         }
335         dm_setup_args.str = str;
336         dm_setup_args.num_devices = num_devices;
337         DMINFO("will configure %lu devices", num_devices);
338         dm_early_setup = 1;
339         return 1;
340
341 parse_fail:
342         DMWARN("Invalid arguments supplied to dm=.");
343         return 0;
344 }
345
346 static void __init dm_setup_drives(void)
347 {
348         struct mapped_device *md = NULL;
349         struct dm_table *table = NULL;
350         struct dm_setup_target *target;
351         struct dm_device *dev;
352         char *uuid;
353         fmode_t fmode = FMODE_READ;
354         struct dm_device *devices;
355
356         devices = dm_parse_args();
357
358         for (dev = devices; dev; dev = dev->next) {
359                 if (dm_create(dev->minor, &md)) {
360                         DMDEBUG("failed to create the device");
361                         goto dm_create_fail;
362                 }
363                 DMDEBUG("created device '%s'", dm_device_name(md));
364
365                 /*
366                  * In addition to flagging the table below, the disk must be
367                  * set explicitly ro/rw.
368                  */
369                 set_disk_ro(dm_disk(md), dev->ro);
370
371                 if (!dev->ro)
372                         fmode |= FMODE_WRITE;
373                 if (dm_table_create(&table, fmode, dev->target_count, md)) {
374                         DMDEBUG("failed to create the table");
375                         goto dm_table_create_fail;
376                 }
377
378                 dm_lock_md_type(md);
379
380                 for (target = dev->target; target; target = target->next) {
381                         DMINFO("adding target '%llu %llu %s %s'",
382                                (unsigned long long) target->begin,
383                                (unsigned long long) target->length,
384                                target->type, target->params);
385                         if (dm_table_add_target(table, target->type,
386                                                 target->begin,
387                                                 target->length,
388                                                 target->params)) {
389                                 DMDEBUG("failed to add the target"
390                                         " to the table");
391                                 goto add_target_fail;
392                         }
393                 }
394                 if (dm_table_complete(table)) {
395                         DMDEBUG("failed to complete the table");
396                         goto table_complete_fail;
397                 }
398
399                 /* Suspend the device so that we can bind it to the table. */
400                 if (dm_suspend(md, 0)) {
401                         DMDEBUG("failed to suspend the device pre-bind");
402                         goto suspend_fail;
403                 }
404
405                 /* Initial table load: acquire type of table. */
406                 dm_set_md_type(md, dm_table_get_type(table));
407
408                 /* Setup md->queue to reflect md's type. */
409                 if (dm_setup_md_queue(md)) {
410                         DMWARN("unable to set up device queue for new table.");
411                         goto setup_md_queue_fail;
412                 }
413
414                 /*
415                  * Bind the table to the device. This is the only way
416                  * to associate md->map with the table and set the disk
417                  * capacity directly.
418                  */
419                 if (dm_swap_table(md, table)) {  /* should return NULL. */
420                         DMDEBUG("failed to bind the device to the table");
421                         goto table_bind_fail;
422                 }
423
424                 /* Finally, resume and the device should be ready. */
425                 if (dm_resume(md)) {
426                         DMDEBUG("failed to resume the device");
427                         goto resume_fail;
428                 }
429
430                 /* Export the dm device via the ioctl interface */
431                 if (!strcmp(DM_NO_UUID, dev->uuid))
432                         uuid = NULL;
433                 if (dm_ioctl_export(md, dev->name, uuid)) {
434                         DMDEBUG("failed to export device with given"
435                                 " name and uuid");
436                         goto export_fail;
437                 }
438
439                 dm_unlock_md_type(md);
440
441                 DMINFO("dm-%d is ready", dev->minor);
442         }
443         dm_setup_cleanup(devices);
444         return;
445
446 export_fail:
447 resume_fail:
448 table_bind_fail:
449 setup_md_queue_fail:
450 suspend_fail:
451 table_complete_fail:
452 add_target_fail:
453         dm_unlock_md_type(md);
454 dm_table_create_fail:
455         dm_put(md);
456 dm_create_fail:
457         DMWARN("starting dm-%d (%s) failed",
458                dev->minor, dev->name);
459         dm_setup_cleanup(devices);
460 }
461
462 __setup("dm=", dm_setup);
463
464 void __init dm_run_setup(void)
465 {
466         if (!dm_early_setup)
467                 return;
468         DMINFO("attempting early device configuration.");
469         dm_setup_drives();
470 }