Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mikulas Patocka and committed by
Mike Snitzer
56b1ebf2 99eb1908

+59 -2
+12
Documentation/device-mapper/switch.txt
··· 106 106 The path number in the range 0 ... (<num_paths> - 1). 107 107 Expressed in hexadecimal (WITHOUT any prefix like 0x). 108 108 109 + R<n>,<m> 110 + This parameter allows repetitive patterns to be loaded quickly. <n> and <m> 111 + are hexadecimal numbers. The last <n> mappings are repeated in the next <m> 112 + slots. 113 + 109 114 Status 110 115 ====== 111 116 ··· 129 124 Set mappings for the first 7 entries to point to devices switch0, switch1, 130 125 switch2, switch0, switch1, switch2, switch1: 131 126 dmsetup message switch 0 set_region_mappings 0:0 :1 :2 :0 :1 :2 :1 127 + 128 + Set repetitive mapping. This command: 129 + dmsetup message switch 0 set_region_mappings 1000:1 :2 R2,10 130 + is equivalent to: 131 + dmsetup message switch 0 set_region_mappings 1000:1 :2 :1 :2 :1 :2 :1 :2 \ 132 + :1 :2 :1 :2 :1 :2 :1 :2 :1 :2 133 +
+47 -2
drivers/md/dm-switch.c
··· 371 371 } 372 372 373 373 static int process_set_region_mappings(struct switch_ctx *sctx, 374 - unsigned argc, char **argv) 374 + unsigned argc, char **argv) 375 375 { 376 376 unsigned i; 377 377 unsigned long region_index = 0; ··· 379 379 for (i = 1; i < argc; i++) { 380 380 unsigned long path_nr; 381 381 const char *string = argv[i]; 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 + } 382 427 383 428 if (*string == ':') 384 429 region_index++; ··· 553 508 554 509 static struct target_type switch_target = { 555 510 .name = "switch", 556 - .version = {1, 0, 0}, 511 + .version = {1, 1, 0}, 557 512 .module = THIS_MODULE, 558 513 .ctr = switch_ctr, 559 514 .dtr = switch_dtr,