summaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-switch.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2014-07-28 18:11:25 -0400
committerMike Snitzer <snitzer@redhat.com>2014-08-01 12:30:37 -0400
commit56b1ebf2d9798257c5932c8a0dd9da16796dbf36 (patch)
tree79baf7a2894d3390e3c59c164382a481984a2a0c /drivers/md/dm-switch.c
parent99eb1908e643609e83454c6fbcbb59f9055abf09 (diff)
dm switch: efficiently support repetitive patterns
Add support for quickly loading a repetitive pattern into the dm-switch target. In the "set_regions_mappings" message, the user may now use "Rn,m" as one of the arguments. "n" and "m" are hexadecimal numbers. The "Rn,m" argument repeats the last "n" arguments in the following "m" slots. For example: dmsetup message switch 0 set_region_mappings 1000:1 :2 R2,10 is equivalent to dmsetup message switch 0 set_region_mappings 1000:1 :2 :1 :2 :1 :2 :1 :2 \ :1 :2 :1 :2 :1 :2 :1 :2 :1 :2 Requested-by: Jay Wang <jwang@nimblestorage.com> Tested-by: Jay Wang <jwang@nimblestorage.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md/dm-switch.c')
-rw-r--r--drivers/md/dm-switch.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index c40e0954cec8..50fca469cafd 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -371,7 +371,7 @@ static __always_inline unsigned long parse_hex(const char **string)
371} 371}
372 372
373static int process_set_region_mappings(struct switch_ctx *sctx, 373static int process_set_region_mappings(struct switch_ctx *sctx,
374 unsigned argc, char **argv) 374 unsigned argc, char **argv)
375{ 375{
376 unsigned i; 376 unsigned i;
377 unsigned long region_index = 0; 377 unsigned long region_index = 0;
@@ -380,6 +380,51 @@ static int process_set_region_mappings(struct switch_ctx *sctx,
380 unsigned long path_nr; 380 unsigned long path_nr;
381 const char *string = argv[i]; 381 const char *string = argv[i];
382 382
383 if ((*string & 0xdf) == 'R') {
384 unsigned long cycle_length, num_write;
385
386 string++;
387 if (unlikely(*string == ',')) {
388 DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
389 return -EINVAL;
390 }
391 cycle_length = parse_hex(&string);
392 if (unlikely(*string != ',')) {
393 DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
394 return -EINVAL;
395 }
396 string++;
397 if (unlikely(!*string)) {
398 DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
399 return -EINVAL;
400 }
401 num_write = parse_hex(&string);
402 if (unlikely(*string)) {
403 DMWARN("invalid set_region_mappings argument: '%s'", argv[i]);
404 return -EINVAL;
405 }
406
407 if (unlikely(!cycle_length) || unlikely(cycle_length - 1 > region_index)) {
408 DMWARN("invalid set_region_mappings cycle length: %lu > %lu",
409 cycle_length - 1, region_index);
410 return -EINVAL;
411 }
412 if (unlikely(region_index + num_write < region_index) ||
413 unlikely(region_index + num_write >= sctx->nr_regions)) {
414 DMWARN("invalid set_region_mappings region number: %lu + %lu >= %lu",
415 region_index, num_write, sctx->nr_regions);
416 return -EINVAL;
417 }
418
419 while (num_write--) {
420 region_index++;
421 path_nr = switch_region_table_read(sctx, region_index - cycle_length);
422 switch_region_table_write(sctx, region_index, path_nr);
423 }
424
425 continue;
426 }
427
383 if (*string == ':') 428 if (*string == ':')
384 region_index++; 429 region_index++;
385 else { 430 else {
@@ -508,7 +553,7 @@ static int switch_iterate_devices(struct dm_target *ti,
508 553
509static struct target_type switch_target = { 554static struct target_type switch_target = {
510 .name = "switch", 555 .name = "switch",
511 .version = {1, 0, 0}, 556 .version = {1, 1, 0},
512 .module = THIS_MODULE, 557 .module = THIS_MODULE,
513 .ctr = switch_ctr, 558 .ctr = switch_ctr,
514 .dtr = switch_dtr, 559 .dtr = switch_dtr,