diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2016-05-19 12:49:25 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2016-06-13 12:00:40 -0400 |
commit | 92c83d79b07ec1c53e0c74b8a7988799e00856db (patch) | |
tree | e2c1e2ffe9727ce5e0e0dee52ba8652f2ab6bafc /drivers/md/dm-raid.c | |
parent | 73c6f239a86271c17d77f826a0c657f3d393a51e (diff) |
dm raid: use dm_arg_set API in constructor
- use dm_arg_set API in ctr and its callees parse_raid_params() and dev_parms()
- introduce _in_range() function to check a value is in a [ min, max ] range;
this is to support more callers in parsing parameters etc. in the future
- correct comment on MAX_RAID_DEVICES
Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid.c')
-rw-r--r-- | drivers/md/dm-raid.c | 145 |
1 files changed, 84 insertions, 61 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 6982e23681be..01aa511ebe44 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/device-mapper.h> | 17 | #include <linux/device-mapper.h> |
18 | 18 | ||
19 | #define DM_MSG_PREFIX "raid" | 19 | #define DM_MSG_PREFIX "raid" |
20 | #define MAX_RAID_DEVICES 253 /* raid4/5/6 limit */ | 20 | #define MAX_RAID_DEVICES 253 /* md-raid kernel limit */ |
21 | 21 | ||
22 | static bool devices_handle_discard_safely = false; | 22 | static bool devices_handle_discard_safely = false; |
23 | 23 | ||
@@ -95,6 +95,12 @@ static struct raid_type { | |||
95 | {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} | 95 | {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} |
96 | }; | 96 | }; |
97 | 97 | ||
98 | /* True, if @v is in inclusive range [@min, @max] */ | ||
99 | static bool _in_range(long v, long min, long max) | ||
100 | { | ||
101 | return v >= min && v <= max; | ||
102 | } | ||
103 | |||
98 | static char *raid10_md_layout_to_format(int layout) | 104 | static char *raid10_md_layout_to_format(int layout) |
99 | { | 105 | { |
100 | /* | 106 | /* |
@@ -135,7 +141,7 @@ static int raid10_format_to_md_layout(char *format, unsigned copies) | |||
135 | return (f << 8) | n; | 141 | return (f << 8) | n; |
136 | } | 142 | } |
137 | 143 | ||
138 | static struct raid_type *get_raid_type(char *name) | 144 | static struct raid_type *get_raid_type(const char *name) |
139 | { | 145 | { |
140 | int i; | 146 | int i; |
141 | 147 | ||
@@ -220,14 +226,20 @@ static void context_free(struct raid_set *rs) | |||
220 | * This code parses those words. If there is a failure, | 226 | * This code parses those words. If there is a failure, |
221 | * the caller must use context_free to unwind the operations. | 227 | * the caller must use context_free to unwind the operations. |
222 | */ | 228 | */ |
223 | static int dev_parms(struct raid_set *rs, char **argv) | 229 | static int parse_dev_parms(struct raid_set *rs, struct dm_arg_set *as) |
224 | { | 230 | { |
225 | int i; | 231 | int i; |
226 | int rebuild = 0; | 232 | int rebuild = 0; |
227 | int metadata_available = 0; | 233 | int metadata_available = 0; |
228 | int r = 0; | 234 | int r = 0; |
235 | const char *arg; | ||
229 | 236 | ||
230 | for (i = 0; i < rs->md.raid_disks; i++, argv += 2) { | 237 | /* Put off the number of raid devices argument to get to dev pairs */ |
238 | arg = dm_shift_arg(as); | ||
239 | if (!arg) | ||
240 | return -EINVAL; | ||
241 | |||
242 | for (i = 0; i < rs->md.raid_disks; i++) { | ||
231 | rs->dev[i].rdev.raid_disk = i; | 243 | rs->dev[i].rdev.raid_disk = i; |
232 | 244 | ||
233 | rs->dev[i].meta_dev = NULL; | 245 | rs->dev[i].meta_dev = NULL; |
@@ -240,8 +252,12 @@ static int dev_parms(struct raid_set *rs, char **argv) | |||
240 | rs->dev[i].rdev.data_offset = 0; | 252 | rs->dev[i].rdev.data_offset = 0; |
241 | rs->dev[i].rdev.mddev = &rs->md; | 253 | rs->dev[i].rdev.mddev = &rs->md; |
242 | 254 | ||
243 | if (strcmp(argv[0], "-")) { | 255 | arg = dm_shift_arg(as); |
244 | r = dm_get_device(rs->ti, argv[0], | 256 | if (!arg) |
257 | return -EINVAL; | ||
258 | |||
259 | if (strcmp(arg, "-")) { | ||
260 | r = dm_get_device(rs->ti, arg, | ||
245 | dm_table_get_mode(rs->ti->table), | 261 | dm_table_get_mode(rs->ti->table), |
246 | &rs->dev[i].meta_dev); | 262 | &rs->dev[i].meta_dev); |
247 | rs->ti->error = "RAID metadata device lookup failure"; | 263 | rs->ti->error = "RAID metadata device lookup failure"; |
@@ -253,7 +269,11 @@ static int dev_parms(struct raid_set *rs, char **argv) | |||
253 | return -ENOMEM; | 269 | return -ENOMEM; |
254 | } | 270 | } |
255 | 271 | ||
256 | if (!strcmp(argv[1], "-")) { | 272 | arg = dm_shift_arg(as); |
273 | if (!arg) | ||
274 | return -EINVAL; | ||
275 | |||
276 | if (!strcmp(arg, "-")) { | ||
257 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) && | 277 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) && |
258 | (!rs->dev[i].rdev.recovery_offset)) { | 278 | (!rs->dev[i].rdev.recovery_offset)) { |
259 | rs->ti->error = "Drive designated for rebuild not specified"; | 279 | rs->ti->error = "Drive designated for rebuild not specified"; |
@@ -267,7 +287,7 @@ static int dev_parms(struct raid_set *rs, char **argv) | |||
267 | continue; | 287 | continue; |
268 | } | 288 | } |
269 | 289 | ||
270 | r = dm_get_device(rs->ti, argv[1], | 290 | r = dm_get_device(rs->ti, arg, |
271 | dm_table_get_mode(rs->ti->table), | 291 | dm_table_get_mode(rs->ti->table), |
272 | &rs->dev[i].data_dev); | 292 | &rs->dev[i].data_dev); |
273 | if (r) { | 293 | if (r) { |
@@ -492,25 +512,30 @@ too_many: | |||
492 | * [raid10_copies <# copies>] Number of copies. (Default: 2) | 512 | * [raid10_copies <# copies>] Number of copies. (Default: 2) |
493 | * [raid10_format <near|far|offset>] Layout algorithm. (Default: near) | 513 | * [raid10_format <near|far|offset>] Layout algorithm. (Default: near) |
494 | */ | 514 | */ |
495 | static int parse_raid_params(struct raid_set *rs, char **argv, | 515 | static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as, |
496 | unsigned num_raid_params) | 516 | unsigned num_raid_params) |
497 | { | 517 | { |
498 | char *raid10_format = "near"; | 518 | char *raid10_format = "near"; |
499 | unsigned raid10_copies = 2; | 519 | unsigned raid10_copies = 2; |
500 | unsigned i; | 520 | unsigned i; |
501 | unsigned long value, region_size = 0; | 521 | unsigned value, region_size = 0; |
502 | sector_t sectors_per_dev = rs->ti->len; | 522 | sector_t sectors_per_dev = rs->ti->len; |
503 | sector_t max_io_len; | 523 | sector_t max_io_len; |
504 | char *key; | 524 | const char *arg, *key; |
525 | |||
526 | arg = dm_shift_arg(as); | ||
527 | num_raid_params--; /* Account for chunk_size argument */ | ||
528 | |||
529 | if (kstrtouint(arg, 10, &value) < 0) { | ||
530 | rs->ti->error = "Bad numerical argument given for chunk_size"; | ||
531 | return -EINVAL; | ||
532 | } | ||
505 | 533 | ||
506 | /* | 534 | /* |
507 | * First, parse the in-order required arguments | 535 | * First, parse the in-order required arguments |
508 | * "chunk_size" is the only argument of this type. | 536 | * "chunk_size" is the only argument of this type. |
509 | */ | 537 | */ |
510 | if ((kstrtoul(argv[0], 10, &value) < 0)) { | 538 | if (rs->raid_type->level == 1) { |
511 | rs->ti->error = "Bad chunk size"; | ||
512 | return -EINVAL; | ||
513 | } else if (rs->raid_type->level == 1) { | ||
514 | if (value) | 539 | if (value) |
515 | DMERR("Ignoring chunk size parameter for RAID 1"); | 540 | DMERR("Ignoring chunk size parameter for RAID 1"); |
516 | value = 0; | 541 | value = 0; |
@@ -523,8 +548,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
523 | } | 548 | } |
524 | 549 | ||
525 | rs->md.new_chunk_sectors = rs->md.chunk_sectors = value; | 550 | rs->md.new_chunk_sectors = rs->md.chunk_sectors = value; |
526 | argv++; | ||
527 | num_raid_params--; | ||
528 | 551 | ||
529 | /* | 552 | /* |
530 | * We set each individual device as In_sync with a completed | 553 | * We set each individual device as In_sync with a completed |
@@ -552,12 +575,18 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
552 | * Second, parse the unordered optional arguments | 575 | * Second, parse the unordered optional arguments |
553 | */ | 576 | */ |
554 | for (i = 0; i < num_raid_params; i++) { | 577 | for (i = 0; i < num_raid_params; i++) { |
555 | if (!strcasecmp(argv[i], "nosync")) { | 578 | arg = dm_shift_arg(as); |
579 | if (!arg) { | ||
580 | rs->ti->error = "Not enough raid parameters given"; | ||
581 | return -EINVAL; | ||
582 | } | ||
583 | |||
584 | if (!strcasecmp(arg, "nosync")) { | ||
556 | rs->md.recovery_cp = MaxSector; | 585 | rs->md.recovery_cp = MaxSector; |
557 | rs->ctr_flags |= CTR_FLAG_NOSYNC; | 586 | rs->ctr_flags |= CTR_FLAG_NOSYNC; |
558 | continue; | 587 | continue; |
559 | } | 588 | } |
560 | if (!strcasecmp(argv[i], "sync")) { | 589 | if (!strcasecmp(arg, "sync")) { |
561 | rs->md.recovery_cp = 0; | 590 | rs->md.recovery_cp = 0; |
562 | rs->ctr_flags |= CTR_FLAG_SYNC; | 591 | rs->ctr_flags |= CTR_FLAG_SYNC; |
563 | continue; | 592 | continue; |
@@ -569,7 +598,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
569 | return -EINVAL; | 598 | return -EINVAL; |
570 | } | 599 | } |
571 | 600 | ||
572 | key = argv[i++]; | 601 | key = arg; |
602 | arg = dm_shift_arg(as); | ||
603 | i++; /* Account for the argument pairs */ | ||
573 | 604 | ||
574 | /* Parameters that take a string value are checked here. */ | 605 | /* Parameters that take a string value are checked here. */ |
575 | if (!strcasecmp(key, "raid10_format")) { | 606 | if (!strcasecmp(key, "raid10_format")) { |
@@ -577,18 +608,18 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
577 | rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; | 608 | rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; |
578 | return -EINVAL; | 609 | return -EINVAL; |
579 | } | 610 | } |
580 | if (strcmp("near", argv[i]) && | 611 | if (strcmp("near", arg) && |
581 | strcmp("far", argv[i]) && | 612 | strcmp("far", arg) && |
582 | strcmp("offset", argv[i])) { | 613 | strcmp("offset", arg)) { |
583 | rs->ti->error = "Invalid 'raid10_format' value given"; | 614 | rs->ti->error = "Invalid 'raid10_format' value given"; |
584 | return -EINVAL; | 615 | return -EINVAL; |
585 | } | 616 | } |
586 | raid10_format = argv[i]; | 617 | raid10_format = (char *) arg; |
587 | rs->ctr_flags |= CTR_FLAG_RAID10_FORMAT; | 618 | rs->ctr_flags |= CTR_FLAG_RAID10_FORMAT; |
588 | continue; | 619 | continue; |
589 | } | 620 | } |
590 | 621 | ||
591 | if (kstrtoul(argv[i], 10, &value) < 0) { | 622 | if (kstrtouint(arg, 10, &value) < 0) { |
592 | rs->ti->error = "Bad numerical argument given in raid params"; | 623 | rs->ti->error = "Bad numerical argument given in raid params"; |
593 | return -EINVAL; | 624 | return -EINVAL; |
594 | } | 625 | } |
@@ -1223,61 +1254,53 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
1223 | { | 1254 | { |
1224 | int r; | 1255 | int r; |
1225 | struct raid_type *rt; | 1256 | struct raid_type *rt; |
1226 | unsigned long num_raid_params, num_raid_devs; | 1257 | unsigned num_raid_params, num_raid_devs; |
1227 | struct raid_set *rs = NULL; | 1258 | struct raid_set *rs = NULL; |
1228 | 1259 | const char *arg; | |
1229 | /* Must have at least <raid_type> <#raid_params> */ | 1260 | struct dm_arg_set as = { argc, argv }, as_nrd; |
1230 | if (argc < 2) { | 1261 | struct dm_arg _args[] = { |
1231 | ti->error = "Too few arguments"; | 1262 | { 0, as.argc, "Cannot understand number of raid parameters" }, |
1263 | { 1, 254, "Cannot understand number of raid devices parameters" } | ||
1264 | }; | ||
1265 | |||
1266 | /* Must have <raid_type> */ | ||
1267 | arg = dm_shift_arg(&as); | ||
1268 | if (!arg) { | ||
1269 | ti->error = "No arguments"; | ||
1232 | return -EINVAL; | 1270 | return -EINVAL; |
1233 | } | 1271 | } |
1234 | 1272 | ||
1235 | /* raid type */ | 1273 | rt = get_raid_type(arg); |
1236 | rt = get_raid_type(argv[0]); | ||
1237 | if (!rt) { | 1274 | if (!rt) { |
1238 | ti->error = "Unrecognised raid_type"; | 1275 | ti->error = "Unrecognised raid_type"; |
1239 | return -EINVAL; | 1276 | return -EINVAL; |
1240 | } | 1277 | } |
1241 | argc--; | ||
1242 | argv++; | ||
1243 | |||
1244 | /* number of RAID parameters */ | ||
1245 | if (kstrtoul(argv[0], 10, &num_raid_params) < 0) { | ||
1246 | ti->error = "Cannot understand number of RAID parameters"; | ||
1247 | return -EINVAL; | ||
1248 | } | ||
1249 | argc--; | ||
1250 | argv++; | ||
1251 | 1278 | ||
1252 | /* Skip over RAID params for now and find out # of devices */ | 1279 | /* Must have <#raid_params> */ |
1253 | if (num_raid_params >= argc) { | 1280 | if (dm_read_arg_group(_args, &as, &num_raid_params, &ti->error)) |
1254 | ti->error = "Arguments do not agree with counts given"; | 1281 | return -EINVAL; |
1255 | return -EINVAL; | ||
1256 | } | ||
1257 | 1282 | ||
1258 | if ((kstrtoul(argv[num_raid_params], 10, &num_raid_devs) < 0) || | 1283 | /* number of raid device tupples <meta_dev data_dev> */ |
1259 | (num_raid_devs > MAX_RAID_DEVICES)) { | 1284 | as_nrd = as; |
1260 | ti->error = "Cannot understand number of raid devices"; | 1285 | dm_consume_args(&as_nrd, num_raid_params); |
1261 | return -EINVAL; | 1286 | _args[1].max = (as_nrd.argc - 1) / 2; |
1262 | } | 1287 | if (dm_read_arg(_args + 1, &as_nrd, &num_raid_devs, &ti->error)) |
1288 | return -EINVAL; | ||
1263 | 1289 | ||
1264 | argc -= num_raid_params + 1; /* +1: we already have num_raid_devs */ | 1290 | if (!_in_range(num_raid_devs, 1, MAX_RAID_DEVICES)) { |
1265 | if (argc != (num_raid_devs * 2)) { | 1291 | ti->error = "Invalid number of supplied raid devices"; |
1266 | ti->error = "Supplied RAID devices does not match the count given"; | 1292 | return -EINVAL; |
1267 | return -EINVAL; | ||
1268 | } | 1293 | } |
1269 | 1294 | ||
1270 | rs = context_alloc(ti, rt, (unsigned)num_raid_devs); | 1295 | rs = context_alloc(ti, rt, num_raid_devs); |
1271 | if (IS_ERR(rs)) | 1296 | if (IS_ERR(rs)) |
1272 | return PTR_ERR(rs); | 1297 | return PTR_ERR(rs); |
1273 | 1298 | ||
1274 | r = parse_raid_params(rs, argv, (unsigned)num_raid_params); | 1299 | r = parse_raid_params(rs, &as, num_raid_params); |
1275 | if (r) | 1300 | if (r) |
1276 | goto bad; | 1301 | goto bad; |
1277 | 1302 | ||
1278 | argv += num_raid_params + 1; | 1303 | r = parse_dev_parms(rs, &as); |
1279 | |||
1280 | r = dev_parms(rs, argv); | ||
1281 | if (r) | 1304 | if (r) |
1282 | goto bad; | 1305 | goto bad; |
1283 | 1306 | ||