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

dm flakey: add an "error_reads" option

dm-flakey returns error on reads if no other argument is specified.
This commit simplifies associated logic while formalizing an
"error_reads" argument and an ERROR_READS flag.

If no argument is specified, set ERROR_READS flag so that it behaves
just like before this commit.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>

authored by

Mikulas Patocka and committed by
Mike Snitzer
aa7d7bc9 e3675dc1

+31 -12
+4
Documentation/admin-guide/device-mapper/dm-flakey.rst
··· 39 39 If no feature parameters are present, during the periods of 40 40 unreliability, all I/O returns errors. 41 41 42 + error_reads: 43 + All read I/O is failed with an error signalled. 44 + Write I/O is handled correctly. 45 + 42 46 drop_writes: 43 47 All write I/O is silently ignored. 44 48 Read I/O is handled correctly.
+27 -12
drivers/md/dm-flakey.c
··· 37 37 }; 38 38 39 39 enum feature_flag_bits { 40 + ERROR_READS, 40 41 DROP_WRITES, 41 42 ERROR_WRITES 42 43 }; ··· 54 53 const char *arg_name; 55 54 56 55 static const struct dm_arg _args[] = { 57 - {0, 6, "Invalid number of feature args"}, 56 + {0, 7, "Invalid number of feature args"}, 58 57 {1, UINT_MAX, "Invalid corrupt bio byte"}, 59 58 {0, 255, "Invalid corrupt value to write into bio byte (0-255)"}, 60 59 {0, UINT_MAX, "Invalid corrupt bio flags mask"}, ··· 75 74 if (!arg_name) { 76 75 ti->error = "Insufficient feature arguments"; 77 76 return -EINVAL; 77 + } 78 + 79 + /* 80 + * error_reads 81 + */ 82 + if (!strcasecmp(arg_name, "error_reads")) { 83 + if (test_and_set_bit(ERROR_READS, &fc->flags)) { 84 + ti->error = "Feature error_reads duplicated"; 85 + return -EINVAL; 86 + } 87 + continue; 78 88 } 79 89 80 90 /* ··· 181 169 } else if (test_bit(ERROR_WRITES, &fc->flags) && (fc->corrupt_bio_rw == WRITE)) { 182 170 ti->error = "error_writes is incompatible with corrupt_bio_byte with the WRITE flag set"; 183 171 return -EINVAL; 172 + } 173 + 174 + if (!fc->corrupt_bio_byte && !test_bit(ERROR_READS, &fc->flags) && 175 + !test_bit(DROP_WRITES, &fc->flags) && !test_bit(ERROR_WRITES, &fc->flags)) { 176 + set_bit(ERROR_WRITES, &fc->flags); 177 + set_bit(ERROR_READS, &fc->flags); 184 178 } 185 179 186 180 return 0; ··· 364 346 * Otherwise, flakey_end_io() will decide if the reads should be modified. 365 347 */ 366 348 if (bio_data_dir(bio) == READ) { 367 - if (!fc->corrupt_bio_byte && !test_bit(DROP_WRITES, &fc->flags) && 368 - !test_bit(ERROR_WRITES, &fc->flags)) 349 + if (test_bit(ERROR_READS, &fc->flags)) 369 350 return DM_MAPIO_KILL; 370 351 goto map_bio; 371 352 } ··· 390 373 } 391 374 goto map_bio; 392 375 } 393 - 394 - /* 395 - * By default, error all I/O. 396 - */ 397 - return DM_MAPIO_KILL; 398 376 } 399 377 400 378 map_bio: ··· 416 404 */ 417 405 corrupt_bio_data(bio, fc); 418 406 } 419 - } else if (!test_bit(DROP_WRITES, &fc->flags) && 420 - !test_bit(ERROR_WRITES, &fc->flags)) { 407 + } 408 + if (test_bit(ERROR_READS, &fc->flags)) { 421 409 /* 422 410 * Error read during the down_interval if drop_writes 423 411 * and error_writes were not configured. ··· 434 422 { 435 423 unsigned int sz = 0; 436 424 struct flakey_c *fc = ti->private; 437 - unsigned int drop_writes, error_writes; 425 + unsigned int error_reads, drop_writes, error_writes; 438 426 439 427 switch (type) { 440 428 case STATUSTYPE_INFO: ··· 446 434 (unsigned long long)fc->start, fc->up_interval, 447 435 fc->down_interval); 448 436 437 + error_reads = test_bit(ERROR_READS, &fc->flags); 449 438 drop_writes = test_bit(DROP_WRITES, &fc->flags); 450 439 error_writes = test_bit(ERROR_WRITES, &fc->flags); 451 - DMEMIT(" %u", drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5); 440 + DMEMIT(" %u", error_reads + drop_writes + error_writes + (fc->corrupt_bio_byte > 0) * 5); 452 441 442 + if (error_reads) 443 + DMEMIT(" error_reads"); 453 444 if (drop_writes) 454 445 DMEMIT(" drop_writes"); 455 446 else if (error_writes)