Home | History | Annotate | Download | only in 4.4
      1 From 6a6a7657c231e947233c43ae0522bbd4edf0139e Mon Sep 17 00:00:00 2001
      2 From: David Zeuthen <zeuthen (a] google.com>
      3 Date: Tue, 24 Jan 2017 13:02:35 -0500
      4 Subject: [PATCH 1/2] ANDROID: Update init/do_mounts_dm.c to the latest
      5  ChromiumOS version.
      6 
      7 This is needed for AVB integration work.
      8 
      9 Bug: 31796270
     10 Test: Manually tested (other arch).
     11 Change-Id: I32fd37c1578c6414e3e6ff277d16ad94df7886b8
     12 Signed-off-by: David Zeuthen <zeuthen (a] google.com>
     13 ---
     14  include/linux/device-mapper.h |   7 +
     15  init/do_mounts_dm.c           | 556 +++++++++++++++++++++++-------------------
     16  2 files changed, 307 insertions(+), 256 deletions(-)
     17 
     18 diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
     19 index b874d5b61ffc..f3f87db34429 100644
     20 --- a/include/linux/device-mapper.h
     21 +++ b/include/linux/device-mapper.h
     22 @@ -415,6 +415,13 @@ union map_info *dm_get_rq_mapinfo(struct request *rq);
     23  
     24  struct queue_limits *dm_get_queue_limits(struct mapped_device *md);
     25  
     26 +void dm_lock_md_type(struct mapped_device *md);
     27 +void dm_unlock_md_type(struct mapped_device *md);
     28 +void dm_set_md_type(struct mapped_device *md, unsigned type);
     29 +unsigned dm_get_md_type(struct mapped_device *md);
     30 +int dm_setup_md_queue(struct mapped_device *md);
     31 +unsigned dm_table_get_type(struct dm_table *t);
     32 +
     33  /*
     34   * Geometry functions.
     35   */
     36 diff --git a/init/do_mounts_dm.c b/init/do_mounts_dm.c
     37 index ecda58df9a19..bce1c2fbb915 100644
     38 --- a/init/do_mounts_dm.c
     39 +++ b/init/do_mounts_dm.c
     40 @@ -5,13 +5,17 @@
     41   *
     42   * This file is released under the GPL.
     43   */
     44 +#include <linux/async.h>
     45 +#include <linux/ctype.h>
     46  #include <linux/device-mapper.h>
     47  #include <linux/fs.h>
     48  #include <linux/string.h>
     49 +#include <linux/delay.h>
     50  
     51  #include "do_mounts.h"
     52 -#include "../drivers/md/dm.h"
     53  
     54 +#define DM_MAX_DEVICES 256
     55 +#define DM_MAX_TARGETS 256
     56  #define DM_MAX_NAME 32
     57  #define DM_MAX_UUID 129
     58  #define DM_NO_UUID "none"
     59 @@ -19,14 +23,47 @@
     60  #define DM_MSG_PREFIX "init"
     61  
     62  /* Separators used for parsing the dm= argument. */
     63 -#define DM_FIELD_SEP ' '
     64 -#define DM_LINE_SEP ','
     65 +#define DM_FIELD_SEP " "
     66 +#define DM_LINE_SEP ","
     67 +#define DM_ANY_SEP DM_FIELD_SEP DM_LINE_SEP
     68  
     69  /*
     70   * When the device-mapper and any targets are compiled into the kernel
     71 - * (not a module), one target may be created and used as the root device at
     72 - * boot time with the parameters given with the boot line dm=...
     73 - * The code for that is here.
     74 + * (not a module), one or more device-mappers may be created and used
     75 + * as the root device at boot time with the parameters given with the
     76 + * boot line dm=...
     77 + *
     78 + * Multiple device-mappers can be stacked specifing the number of
     79 + * devices. A device can have multiple targets if the the number of
     80 + * targets is specified.
     81 + *
     82 + * TODO(taysom:defect 32847)
     83 + * In the future, the <num> field will be mandatory.
     84 + *
     85 + * <device>        ::= [<num>] <device-mapper>+
     86 + * <device-mapper> ::= <head> "," <target>+
     87 + * <head>          ::= <name> <uuid> <mode> [<num>]
     88 + * <target>        ::= <start> <length> <type> <options> ","
     89 + * <mode>          ::= "ro" | "rw"
     90 + * <uuid>          ::= xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | "none"
     91 + * <type>          ::= "verity" | "bootcache" | ...
     92 + *
     93 + * Example:
     94 + * 2 vboot none ro 1,
     95 + *     0 1768000 bootcache
     96 + *       device=aa55b119-2a47-8c45-946a-5ac57765011f+1
     97 + *       signature=76e9be054b15884a9fa85973e9cb274c93afadb6
     98 + *       cache_start=1768000 max_blocks=100000 size_limit=23 max_trace=20000,
     99 + *   vroot none ro 1,
    100 + *     0 1740800 verity payload=254:0 hashtree=254:0 hashstart=1740800 alg=sha1
    101 + *       root_hexdigest=76e9be054b15884a9fa85973e9cb274c93afadb6
    102 + *       salt=5b3549d54d6c7a3837b9b81ed72e49463a64c03680c47835bef94d768e5646fe
    103 + *
    104 + * Notes:
    105 + *  1. uuid is a label for the device and we set it to "none".
    106 + *  2. The <num> field will be optional initially and assumed to be 1.
    107 + *     Once all the scripts that set these fields have been set, it will
    108 + *     be made mandatory.
    109   */
    110  
    111  struct dm_setup_target {
    112 @@ -38,381 +75,388 @@ struct dm_setup_target {
    113  	struct dm_setup_target *next;
    114  };
    115  
    116 -static struct {
    117 +struct dm_device {
    118  	int minor;
    119  	int ro;
    120  	char name[DM_MAX_NAME];
    121  	char uuid[DM_MAX_UUID];
    122 -	char *targets;
    123 +	unsigned long num_targets;
    124  	struct dm_setup_target *target;
    125  	int target_count;
    126 +	struct dm_device *next;
    127 +};
    128 +
    129 +struct dm_option {
    130 +	char *start;
    131 +	char *next;
    132 +	size_t len;
    133 +	char delim;
    134 +};
    135 +
    136 +static struct {
    137 +	unsigned long num_devices;
    138 +	char *str;
    139  } dm_setup_args __initdata;
    140  
    141  static __initdata int dm_early_setup;
    142  
    143 -static size_t __init get_dm_option(char *str, char **next, char sep)
    144 +static int __init get_dm_option(struct dm_option *opt, const char *accept)
    145  {
    146 -	size_t len = 0;
    147 -	char *endp = NULL;
    148 +	char *str = opt->next;
    149 +	char *endp;
    150  
    151  	if (!str)
    152  		return 0;
    153  
    154 -	endp = strchr(str, sep);
    155 +	str = skip_spaces(str);
    156 +	opt->start = str;
    157 +	endp = strpbrk(str, accept);
    158  	if (!endp) {  /* act like strchrnul */
    159 -		len = strlen(str);
    160 -		endp = str + len;
    161 +		opt->len = strlen(str);
    162 +		endp = str + opt->len;
    163  	} else {
    164 -		len = endp - str;
    165 +		opt->len = endp - str;
    166  	}
    167 -
    168 -	if (endp == str)
    169 -		return 0;
    170 -
    171 -	if (!next)
    172 -		return len;
    173 -
    174 +	opt->delim = *endp;
    175  	if (*endp == 0) {
    176  		/* Don't advance past the nul. */
    177 -		*next = endp;
    178 +		opt->next = endp;
    179  	} else {
    180 -		*next = endp + 1;
    181 +		opt->next = endp + 1;
    182  	}
    183 -	return len;
    184 -}
    185 -
    186 -static int __init dm_setup_args_init(void)
    187 -{
    188 -	dm_setup_args.minor = 0;
    189 -	dm_setup_args.ro = 0;
    190 -	dm_setup_args.target = NULL;
    191 -	dm_setup_args.target_count = 0;
    192 -	return 0;
    193 +	return opt->len != 0;
    194  }
    195  
    196 -static int __init dm_setup_cleanup(void)
    197 +static int __init dm_setup_cleanup(struct dm_device *devices)
    198  {
    199 -	struct dm_setup_target *target = dm_setup_args.target;
    200 -	struct dm_setup_target *old_target = NULL;
    201 -	while (target) {
    202 -		kfree(target->type);
    203 -		kfree(target->params);
    204 -		old_target = target;
    205 -		target = target->next;
    206 -		kfree(old_target);
    207 -		dm_setup_args.target_count--;
    208 +	struct dm_device *dev = devices;
    209 +
    210 +	while (dev) {
    211 +		struct dm_device *old_dev = dev;
    212 +		struct dm_setup_target *target = dev->target;
    213 +		while (target) {
    214 +			struct dm_setup_target *old_target = target;
    215 +			kfree(target->type);
    216 +			kfree(target->params);
    217 +			target = target->next;
    218 +			kfree(old_target);
    219 +			dev->target_count--;
    220 +		}
    221 +		BUG_ON(dev->target_count);
    222 +		dev = dev->next;
    223 +		kfree(old_dev);
    224  	}
    225 -	BUG_ON(dm_setup_args.target_count);
    226  	return 0;
    227  }
    228  
    229 -static char * __init dm_setup_parse_device_args(char *str)
    230 +static char * __init dm_parse_device(struct dm_device *dev, char *str)
    231  {
    232 -	char *next = NULL;
    233 -	size_t len = 0;
    234 +	struct dm_option opt;
    235 +	size_t len;
    236  
    237  	/* Grab the logical name of the device to be exported to udev */
    238 -	len = get_dm_option(str, &next, DM_FIELD_SEP);
    239 -	if (!len) {
    240 +	opt.next = str;
    241 +	if (!get_dm_option(&opt, DM_FIELD_SEP)) {
    242  		DMERR("failed to parse device name");
    243  		goto parse_fail;
    244  	}
    245 -	len = min(len + 1, sizeof(dm_setup_args.name));
    246 -	strlcpy(dm_setup_args.name, str, len);  /* includes nul */
    247 -	str = skip_spaces(next);
    248 +	len = min(opt.len + 1, sizeof(dev->name));
    249 +	strlcpy(dev->name, opt.start, len);  /* includes nul */
    250  
    251  	/* Grab the UUID value or "none" */
    252 -	len = get_dm_option(str, &next, DM_FIELD_SEP);
    253 -	if (!len) {
    254 +	if (!get_dm_option(&opt, DM_FIELD_SEP)) {
    255  		DMERR("failed to parse device uuid");
    256  		goto parse_fail;
    257  	}
    258 -	len = min(len + 1, sizeof(dm_setup_args.uuid));
    259 -	strlcpy(dm_setup_args.uuid, str, len);
    260 -	str = skip_spaces(next);
    261 +	len = min(opt.len + 1, sizeof(dev->uuid));
    262 +	strlcpy(dev->uuid, opt.start, len);
    263  
    264  	/* Determine if the table/device will be read only or read-write */
    265 -	if (!strncmp("ro,", str, 3)) {
    266 -		dm_setup_args.ro = 1;
    267 -	} else if (!strncmp("rw,", str, 3)) {
    268 -		dm_setup_args.ro = 0;
    269 +	get_dm_option(&opt, DM_ANY_SEP);
    270 +	if (!strncmp("ro", opt.start, opt.len)) {
    271 +		dev->ro = 1;
    272 +	} else if (!strncmp("rw", opt.start, opt.len)) {
    273 +		dev->ro = 0;
    274  	} else {
    275  		DMERR("failed to parse table mode");
    276  		goto parse_fail;
    277  	}
    278 -	str = skip_spaces(str + 3);
    279  
    280 -	return str;
    281 +	/* Optional number field */
    282 +	/* XXX: The <num> field will be mandatory in the next round */
    283 +	if (opt.delim == DM_FIELD_SEP[0]) {
    284 +		if (!get_dm_option(&opt, DM_LINE_SEP))
    285 +			return NULL;
    286 +		dev->num_targets = simple_strtoul(opt.start, NULL, 10);
    287 +	} else {
    288 +		dev->num_targets = 1;
    289 +	}
    290 +	if (dev->num_targets > DM_MAX_TARGETS) {
    291 +		DMERR("too many targets %lu > %d",
    292 +			dev->num_targets, DM_MAX_TARGETS);
    293 +	}
    294 +	return opt.next;
    295  
    296  parse_fail:
    297  	return NULL;
    298  }
    299  
    300 -static void __init dm_substitute_devices(char *str, size_t str_len)
    301 +static char * __init dm_parse_targets(struct dm_device *dev, char *str)
    302  {
    303 -	char *candidate = str;
    304 -	char *candidate_end = str;
    305 -	char old_char;
    306 -	size_t len = 0;
    307 -	dev_t dev;
    308 -
    309 -	if (str_len < 3)
    310 -		return;
    311 -
    312 -	while (str && *str) {
    313 -		candidate = strchr(str, '/');
    314 -		if (!candidate)
    315 -			break;
    316 -
    317 -		/* Avoid embedded slashes */
    318 -		if (candidate != str && *(candidate - 1) != DM_FIELD_SEP) {
    319 -			str = strchr(candidate, DM_FIELD_SEP);
    320 -			continue;
    321 -		}
    322 -
    323 -		len = get_dm_option(candidate, &candidate_end, DM_FIELD_SEP);
    324 -		str = skip_spaces(candidate_end);
    325 -		if (len < 3 || len > 37)  /* name_to_dev_t max; maj:mix min */
    326 -			continue;
    327 -
    328 -		/* Temporarily terminate with a nul */
    329 -		if (*candidate_end)
    330 -			candidate_end--;
    331 -		old_char = *candidate_end;
    332 -		*candidate_end = '\0';
    333 -
    334 -		DMDEBUG("converting candidate device '%s' to dev_t", candidate);
    335 -		/* Use the boot-time specific device naming */
    336 -		dev = name_to_dev_t(candidate);
    337 -		*candidate_end = old_char;
    338 -
    339 -		DMDEBUG(" -> %u", dev);
    340 -		/* No suitable replacement found */
    341 -		if (!dev)
    342 -			continue;
    343 -
    344 -		/* Rewrite the /dev/path as a major:minor */
    345 -		len = snprintf(candidate, len, "%u:%u", MAJOR(dev), MINOR(dev));
    346 -		if (!len) {
    347 -			DMERR("error substituting device major/minor.");
    348 -			break;
    349 -		}
    350 -		candidate += len;
    351 -		/* Pad out with spaces (fixing our nul) */
    352 -		while (candidate < candidate_end)
    353 -			*(candidate++) = DM_FIELD_SEP;
    354 -	}
    355 -}
    356 -
    357 -static int __init dm_setup_parse_targets(char *str)
    358 -{
    359 -	char *next = NULL;
    360 -	size_t len = 0;
    361 -	struct dm_setup_target **target = NULL;
    362 +	struct dm_option opt;
    363 +	struct dm_setup_target **target = &dev->target;
    364 +	unsigned long num_targets = dev->num_targets;
    365 +	unsigned long i;
    366  
    367  	/* Targets are defined as per the table format but with a
    368  	 * comma as a newline separator. */
    369 -	target = &dm_setup_args.target;
    370 -	while (str && *str) {
    371 +	opt.next = str;
    372 +	for (i = 0; i < num_targets; i++) {
    373  		*target = kzalloc(sizeof(struct dm_setup_target), GFP_KERNEL);
    374  		if (!*target) {
    375 -			DMERR("failed to allocate memory for target %d",
    376 -			      dm_setup_args.target_count);
    377 +			DMERR("failed to allocate memory for target %s<%ld>",
    378 +				dev->name, i);
    379  			goto parse_fail;
    380  		}
    381 -		dm_setup_args.target_count++;
    382 +		dev->target_count++;
    383  
    384 -		(*target)->begin = simple_strtoull(str, &next, 10);
    385 -		if (!next || *next != DM_FIELD_SEP) {
    386 -			DMERR("failed to parse starting sector for target %d",
    387 -			      dm_setup_args.target_count - 1);
    388 +		if (!get_dm_option(&opt, DM_FIELD_SEP)) {
    389 +			DMERR("failed to parse starting sector"
    390 +				" for target %s<%ld>", dev->name, i);
    391  			goto parse_fail;
    392  		}
    393 -		str = skip_spaces(next + 1);
    394 +		(*target)->begin = simple_strtoull(opt.start, NULL, 10);
    395  
    396 -		(*target)->length = simple_strtoull(str, &next, 10);
    397 -		if (!next || *next != DM_FIELD_SEP) {
    398 -			DMERR("failed to parse length for target %d",
    399 -			      dm_setup_args.target_count - 1);
    400 +		if (!get_dm_option(&opt, DM_FIELD_SEP)) {
    401 +			DMERR("failed to parse length for target %s<%ld>",
    402 +				dev->name, i);
    403  			goto parse_fail;
    404  		}
    405 -		str = skip_spaces(next + 1);
    406 -
    407 -		len = get_dm_option(str, &next, DM_FIELD_SEP);
    408 -		if (!len ||
    409 -		    !((*target)->type = kstrndup(str, len, GFP_KERNEL))) {
    410 -			DMERR("failed to parse type for target %d",
    411 -			      dm_setup_args.target_count - 1);
    412 +		(*target)->length = simple_strtoull(opt.start, NULL, 10);
    413 +
    414 +		if (get_dm_option(&opt, DM_FIELD_SEP))
    415 +			(*target)->type = kstrndup(opt.start, opt.len,
    416 +							GFP_KERNEL);
    417 +		if (!((*target)->type)) {
    418 +			DMERR("failed to parse type for target %s<%ld>",
    419 +				dev->name, i);
    420  			goto parse_fail;
    421  		}
    422 -		str = skip_spaces(next);
    423 -
    424 -		len = get_dm_option(str, &next, DM_LINE_SEP);
    425 -		if (!len ||
    426 -		    !((*target)->params = kstrndup(str, len, GFP_KERNEL))) {
    427 -			DMERR("failed to parse params for target %d",
    428 -			      dm_setup_args.target_count - 1);
    429 +		if (get_dm_option(&opt, DM_LINE_SEP))
    430 +			(*target)->params = kstrndup(opt.start, opt.len,
    431 +							GFP_KERNEL);
    432 +		if (!((*target)->params)) {
    433 +			DMERR("failed to parse params for target %s<%ld>",
    434 +				dev->name, i);
    435  			goto parse_fail;
    436  		}
    437 -		str = skip_spaces(next);
    438 -
    439 -		/* Before moving on, walk through the copied target and
    440 -		 * attempt to replace all /dev/xxx with the major:minor number.
    441 -		 * It may not be possible to resolve them traditionally at
    442 -		 * boot-time. */
    443 -		dm_substitute_devices((*target)->params, len);
    444 -
    445  		target = &((*target)->next);
    446  	}
    447 -	DMDEBUG("parsed %d targets", dm_setup_args.target_count);
    448 +	DMDEBUG("parsed %d targets", dev->target_count);
    449  
    450 -	return 0;
    451 +	return opt.next;
    452  
    453  parse_fail:
    454 -	return 1;
    455 +	return NULL;
    456 +}
    457 +
    458 +static struct dm_device * __init dm_parse_args(void)
    459 +{
    460 +	struct dm_device *devices = NULL;
    461 +	struct dm_device **tail = &devices;
    462 +	struct dm_device *dev;
    463 +	char *str = dm_setup_args.str;
    464 +	unsigned long num_devices = dm_setup_args.num_devices;
    465 +	unsigned long i;
    466 +
    467 +	if (!str)
    468 +		return NULL;
    469 +	for (i = 0; i < num_devices; i++) {
    470 +		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    471 +		if (!dev) {
    472 +			DMERR("failed to allocated memory for dev");
    473 +			goto error;
    474 +		}
    475 +		*tail = dev;
    476 +		tail = &dev->next;
    477 +		/*
    478 +		 * devices are given minor numbers 0 - n-1
    479 +		 * in the order they are found in the arg
    480 +		 * string.
    481 +		 */
    482 +		dev->minor = i;
    483 +		str = dm_parse_device(dev, str);
    484 +		if (!str)	/* NULL indicates error in parsing, bail */
    485 +			goto error;
    486 +
    487 +		str = dm_parse_targets(dev, str);
    488 +		if (!str)
    489 +			goto error;
    490 +	}
    491 +	return devices;
    492 +error:
    493 +	dm_setup_cleanup(devices);
    494 +	return NULL;
    495  }
    496  
    497  /*
    498   * Parse the command-line parameters given our kernel, but do not
    499   * actually try to invoke the DM device now; that is handled by
    500 - * dm_setup_drive after the low-level disk drivers have initialised.
    501 - * dm format is as follows:
    502 - *  dm="name uuid fmode,[table line 1],[table line 2],..."
    503 - * May be used with root=/dev/dm-0 as it always uses the first dm minor.
    504 + * dm_setup_drives after the low-level disk drivers have initialised.
    505 + * dm format is described at the top of the file.
    506 + *
    507 + * Because dm minor numbers are assigned in assending order starting with 0,
    508 + * You can assume the first device is /dev/dm-0, the next device is /dev/dm-1,
    509 + * and so forth.
    510   */
    511 -
    512  static int __init dm_setup(char *str)
    513  {
    514 -	dm_setup_args_init();
    515 +	struct dm_option opt;
    516 +	unsigned long num_devices;
    517  
    518 -	str = dm_setup_parse_device_args(str);
    519  	if (!str) {
    520  		DMDEBUG("str is NULL");
    521  		goto parse_fail;
    522  	}
    523 -
    524 -	/* Target parsing is delayed until we have dynamic memory */
    525 -	dm_setup_args.targets = str;
    526 -
    527 -	printk(KERN_INFO "dm: will configure '%s' on dm-%d\n",
    528 -	       dm_setup_args.name, dm_setup_args.minor);
    529 -
    530 +	opt.next = str;
    531 +	if (!get_dm_option(&opt, DM_FIELD_SEP))
    532 +		goto parse_fail;
    533 +	if (isdigit(opt.start[0])) {	/* XXX: Optional number field */
    534 +		num_devices = simple_strtoul(opt.start, NULL, 10);
    535 +		str = opt.next;
    536 +	} else {
    537 +		num_devices = 1;
    538 +		/* Don't advance str */
    539 +	}
    540 +	if (num_devices > DM_MAX_DEVICES) {
    541 +		DMDEBUG("too many devices %lu > %d",
    542 +			num_devices, DM_MAX_DEVICES);
    543 +	}
    544 +	dm_setup_args.str = str;
    545 +	dm_setup_args.num_devices = num_devices;
    546 +	DMINFO("will configure %lu devices", num_devices);
    547  	dm_early_setup = 1;
    548  	return 1;
    549  
    550  parse_fail:
    551 -	printk(KERN_WARNING "dm: Invalid arguments supplied to dm=.\n");
    552 +	DMWARN("Invalid arguments supplied to dm=.");
    553  	return 0;
    554  }
    555  
    556 -
    557 -static void __init dm_setup_drive(void)
    558 +static void __init dm_setup_drives(void)
    559  {
    560  	struct mapped_device *md = NULL;
    561  	struct dm_table *table = NULL;
    562  	struct dm_setup_target *target;
    563 -	char *uuid = dm_setup_args.uuid;
    564 +	struct dm_device *dev;
    565 +	char *uuid;
    566  	fmode_t fmode = FMODE_READ;
    567 +	struct dm_device *devices;
    568  
    569 -	/* Finish parsing the targets. */
    570 -	if (dm_setup_parse_targets(dm_setup_args.targets))
    571 -		goto parse_fail;
    572 -
    573 -	if (dm_create(dm_setup_args.minor, &md)) {
    574 -		DMDEBUG("failed to create the device");
    575 -		goto dm_create_fail;
    576 -	}
    577 -	DMDEBUG("created device '%s'", dm_device_name(md));
    578 -
    579 -	/* In addition to flagging the table below, the disk must be
    580 -	 * set explicitly ro/rw. */
    581 -	set_disk_ro(dm_disk(md), dm_setup_args.ro);
    582 +	devices = dm_parse_args();
    583  
    584 -	if (!dm_setup_args.ro)
    585 -		fmode |= FMODE_WRITE;
    586 -	if (dm_table_create(&table, fmode, dm_setup_args.target_count, md)) {
    587 -		DMDEBUG("failed to create the table");
    588 -		goto dm_table_create_fail;
    589 -	}
    590 +	for (dev = devices; dev; dev = dev->next) {
    591 +		if (dm_create(dev->minor, &md)) {
    592 +			DMDEBUG("failed to create the device");
    593 +			goto dm_create_fail;
    594 +		}
    595 +		DMDEBUG("created device '%s'", dm_device_name(md));
    596 +
    597 +		/*
    598 +		 * In addition to flagging the table below, the disk must be
    599 +		 * set explicitly ro/rw.
    600 +		 */
    601 +		set_disk_ro(dm_disk(md), dev->ro);
    602 +
    603 +		if (!dev->ro)
    604 +			fmode |= FMODE_WRITE;
    605 +		if (dm_table_create(&table, fmode, dev->target_count, md)) {
    606 +			DMDEBUG("failed to create the table");
    607 +			goto dm_table_create_fail;
    608 +		}
    609  
    610 -	dm_lock_md_type(md);
    611 -	target = dm_setup_args.target;
    612 -	while (target) {
    613 -		DMINFO("adding target '%llu %llu %s %s'",
    614 -		       (unsigned long long) target->begin,
    615 -		       (unsigned long long) target->length, target->type,
    616 -		       target->params);
    617 -		if (dm_table_add_target(table, target->type, target->begin,
    618 -					target->length, target->params)) {
    619 -			DMDEBUG("failed to add the target to the table");
    620 -			goto add_target_fail;
    621 +		dm_lock_md_type(md);
    622 +
    623 +		for (target = dev->target; target; target = target->next) {
    624 +			DMINFO("adding target '%llu %llu %s %s'",
    625 +			       (unsigned long long) target->begin,
    626 +			       (unsigned long long) target->length,
    627 +			       target->type, target->params);
    628 +			if (dm_table_add_target(table, target->type,
    629 +						target->begin,
    630 +						target->length,
    631 +						target->params)) {
    632 +				DMDEBUG("failed to add the target"
    633 +					" to the table");
    634 +				goto add_target_fail;
    635 +			}
    636 +		}
    637 +		if (dm_table_complete(table)) {
    638 +			DMDEBUG("failed to complete the table");
    639 +			goto table_complete_fail;
    640  		}
    641 -		target = target->next;
    642 -	}
    643  
    644 -	if (dm_table_complete(table)) {
    645 -		DMDEBUG("failed to complete the table");
    646 -		goto table_complete_fail;
    647 -	}
    648 +		/* Suspend the device so that we can bind it to the table. */
    649 +		if (dm_suspend(md, 0)) {
    650 +			DMDEBUG("failed to suspend the device pre-bind");
    651 +			goto suspend_fail;
    652 +		}
    653  
    654 -	if (dm_get_md_type(md) == DM_TYPE_NONE) {
    655 +		/* Initial table load: acquire type of table. */
    656  		dm_set_md_type(md, dm_table_get_type(table));
    657 +
    658 +		/* Setup md->queue to reflect md's type. */
    659  		if (dm_setup_md_queue(md)) {
    660  			DMWARN("unable to set up device queue for new table.");
    661  			goto setup_md_queue_fail;
    662  		}
    663 -	} else if (dm_get_md_type(md) != dm_table_get_type(table)) {
    664 -		DMWARN("can't change device type after initial table load.");
    665 -		goto setup_md_queue_fail;
    666 -        }
    667 -
    668 -	/* Suspend the device so that we can bind it to the table. */
    669 -	if (dm_suspend(md, 0)) {
    670 -		DMDEBUG("failed to suspend the device pre-bind");
    671 -		goto suspend_fail;
    672 -	}
    673  
    674 -	/* Bind the table to the device. This is the only way to associate
    675 -	 * md->map with the table and set the disk capacity directly. */
    676 -	if (dm_swap_table(md, table)) {  /* should return NULL. */
    677 -		DMDEBUG("failed to bind the device to the table");
    678 -		goto table_bind_fail;
    679 -	}
    680 +		/*
    681 +		 * Bind the table to the device. This is the only way
    682 +		 * to associate md->map with the table and set the disk
    683 +		 * capacity directly.
    684 +		 */
    685 +		if (dm_swap_table(md, table)) {  /* should return NULL. */
    686 +			DMDEBUG("failed to bind the device to the table");
    687 +			goto table_bind_fail;
    688 +		}
    689  
    690 -	/* Finally, resume and the device should be ready. */
    691 -	if (dm_resume(md)) {
    692 -		DMDEBUG("failed to resume the device");
    693 -		goto resume_fail;
    694 -	}
    695 +		/* Finally, resume and the device should be ready. */
    696 +		if (dm_resume(md)) {
    697 +			DMDEBUG("failed to resume the device");
    698 +			goto resume_fail;
    699 +		}
    700  
    701 -	/* Export the dm device via the ioctl interface */
    702 -	if (!strcmp(DM_NO_UUID, dm_setup_args.uuid))
    703 -		uuid = NULL;
    704 -	if (dm_ioctl_export(md, dm_setup_args.name, uuid)) {
    705 -		DMDEBUG("failed to export device with given name and uuid");
    706 -		goto export_fail;
    707 -	}
    708 -	printk(KERN_INFO "dm: dm-%d is ready\n", dm_setup_args.minor);
    709 +		/* Export the dm device via the ioctl interface */
    710 +		if (!strcmp(DM_NO_UUID, dev->uuid))
    711 +			uuid = NULL;
    712 +		if (dm_ioctl_export(md, dev->name, uuid)) {
    713 +			DMDEBUG("failed to export device with given"
    714 +				" name and uuid");
    715 +			goto export_fail;
    716 +		}
    717  
    718 -	dm_unlock_md_type(md);
    719 -	dm_setup_cleanup();
    720 +		dm_unlock_md_type(md);
    721 +
    722 +		DMINFO("dm-%d is ready", dev->minor);
    723 +	}
    724 +	dm_setup_cleanup(devices);
    725  	return;
    726  
    727  export_fail:
    728  resume_fail:
    729  table_bind_fail:
    730 -suspend_fail:
    731  setup_md_queue_fail:
    732 +suspend_fail:
    733  table_complete_fail:
    734  add_target_fail:
    735  	dm_unlock_md_type(md);
    736  dm_table_create_fail:
    737  	dm_put(md);
    738  dm_create_fail:
    739 -	dm_setup_cleanup();
    740 -parse_fail:
    741 -	printk(KERN_WARNING "dm: starting dm-%d (%s) failed\n",
    742 -	       dm_setup_args.minor, dm_setup_args.name);
    743 +	DMWARN("starting dm-%d (%s) failed",
    744 +	       dev->minor, dev->name);
    745 +	dm_setup_cleanup(devices);
    746  }
    747  
    748  __setup("dm=", dm_setup);
    749 @@ -421,6 +465,6 @@ void __init dm_run_setup(void)
    750  {
    751  	if (!dm_early_setup)
    752  		return;
    753 -	printk(KERN_INFO "dm: attempting early device configuration.\n");
    754 -	dm_setup_drive();
    755 +	DMINFO("attempting early device configuration.");
    756 +	dm_setup_drives();
    757  }
    758 -- 
    759 2.14.1.581.gf28d330327-goog
    760 
    761