diff options
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 089d62751f7f..d83696bf403b 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
@@ -23,8 +23,10 @@ | |||
23 | 23 | ||
24 | #define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */ | 24 | #define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */ |
25 | 25 | ||
26 | #define DM_RAID1_HANDLE_ERRORS 0x01 | 26 | #define DM_RAID1_HANDLE_ERRORS 0x01 |
27 | #define DM_RAID1_KEEP_LOG 0x02 | ||
27 | #define errors_handled(p) ((p)->features & DM_RAID1_HANDLE_ERRORS) | 28 | #define errors_handled(p) ((p)->features & DM_RAID1_HANDLE_ERRORS) |
29 | #define keep_log(p) ((p)->features & DM_RAID1_KEEP_LOG) | ||
28 | 30 | ||
29 | static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); | 31 | static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); |
30 | 32 | ||
@@ -229,7 +231,7 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type) | |||
229 | if (m != get_default_mirror(ms)) | 231 | if (m != get_default_mirror(ms)) |
230 | goto out; | 232 | goto out; |
231 | 233 | ||
232 | if (!ms->in_sync) { | 234 | if (!ms->in_sync && !keep_log(ms)) { |
233 | /* | 235 | /* |
234 | * Better to issue requests to same failing device | 236 | * Better to issue requests to same failing device |
235 | * than to risk returning corrupt data. | 237 | * than to risk returning corrupt data. |
@@ -370,6 +372,17 @@ static int recover(struct mirror_set *ms, struct dm_region *reg) | |||
370 | return r; | 372 | return r; |
371 | } | 373 | } |
372 | 374 | ||
375 | static void reset_ms_flags(struct mirror_set *ms) | ||
376 | { | ||
377 | unsigned int m; | ||
378 | |||
379 | ms->leg_failure = 0; | ||
380 | for (m = 0; m < ms->nr_mirrors; m++) { | ||
381 | atomic_set(&(ms->mirror[m].error_count), 0); | ||
382 | ms->mirror[m].error_type = 0; | ||
383 | } | ||
384 | } | ||
385 | |||
373 | static void do_recovery(struct mirror_set *ms) | 386 | static void do_recovery(struct mirror_set *ms) |
374 | { | 387 | { |
375 | struct dm_region *reg; | 388 | struct dm_region *reg; |
@@ -398,6 +411,7 @@ static void do_recovery(struct mirror_set *ms) | |||
398 | /* the sync is complete */ | 411 | /* the sync is complete */ |
399 | dm_table_event(ms->ti->table); | 412 | dm_table_event(ms->ti->table); |
400 | ms->in_sync = 1; | 413 | ms->in_sync = 1; |
414 | reset_ms_flags(ms); | ||
401 | } | 415 | } |
402 | } | 416 | } |
403 | 417 | ||
@@ -759,7 +773,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) | |||
759 | dm_rh_delay(ms->rh, bio); | 773 | dm_rh_delay(ms->rh, bio); |
760 | 774 | ||
761 | while ((bio = bio_list_pop(&nosync))) { | 775 | while ((bio = bio_list_pop(&nosync))) { |
762 | if (unlikely(ms->leg_failure) && errors_handled(ms)) { | 776 | if (unlikely(ms->leg_failure) && errors_handled(ms) && !keep_log(ms)) { |
763 | spin_lock_irq(&ms->lock); | 777 | spin_lock_irq(&ms->lock); |
764 | bio_list_add(&ms->failures, bio); | 778 | bio_list_add(&ms->failures, bio); |
765 | spin_unlock_irq(&ms->lock); | 779 | spin_unlock_irq(&ms->lock); |
@@ -803,15 +817,21 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures) | |||
803 | 817 | ||
804 | /* | 818 | /* |
805 | * If all the legs are dead, fail the I/O. | 819 | * If all the legs are dead, fail the I/O. |
806 | * If we have been told to handle errors, hold the bio | 820 | * If the device has failed and keep_log is enabled, |
807 | * and wait for userspace to deal with the problem. | 821 | * fail the I/O. |
822 | * | ||
823 | * If we have been told to handle errors, and keep_log | ||
824 | * isn't enabled, hold the bio and wait for userspace to | ||
825 | * deal with the problem. | ||
826 | * | ||
808 | * Otherwise pretend that the I/O succeeded. (This would | 827 | * Otherwise pretend that the I/O succeeded. (This would |
809 | * be wrong if the failed leg returned after reboot and | 828 | * be wrong if the failed leg returned after reboot and |
810 | * got replicated back to the good legs.) | 829 | * got replicated back to the good legs.) |
811 | */ | 830 | */ |
812 | if (!get_valid_mirror(ms)) | 831 | |
832 | if (unlikely(!get_valid_mirror(ms) || (keep_log(ms) && ms->log_failure))) | ||
813 | bio_endio(bio, -EIO); | 833 | bio_endio(bio, -EIO); |
814 | else if (errors_handled(ms)) | 834 | else if (errors_handled(ms) && !keep_log(ms)) |
815 | hold_bio(ms, bio); | 835 | hold_bio(ms, bio); |
816 | else | 836 | else |
817 | bio_endio(bio, 0); | 837 | bio_endio(bio, 0); |
@@ -987,6 +1007,7 @@ static int parse_features(struct mirror_set *ms, unsigned argc, char **argv, | |||
987 | unsigned num_features; | 1007 | unsigned num_features; |
988 | struct dm_target *ti = ms->ti; | 1008 | struct dm_target *ti = ms->ti; |
989 | char dummy; | 1009 | char dummy; |
1010 | int i; | ||
990 | 1011 | ||
991 | *args_used = 0; | 1012 | *args_used = 0; |
992 | 1013 | ||
@@ -1007,15 +1028,25 @@ static int parse_features(struct mirror_set *ms, unsigned argc, char **argv, | |||
1007 | return -EINVAL; | 1028 | return -EINVAL; |
1008 | } | 1029 | } |
1009 | 1030 | ||
1010 | if (!strcmp("handle_errors", argv[0])) | 1031 | for (i = 0; i < num_features; i++) { |
1011 | ms->features |= DM_RAID1_HANDLE_ERRORS; | 1032 | if (!strcmp("handle_errors", argv[0])) |
1012 | else { | 1033 | ms->features |= DM_RAID1_HANDLE_ERRORS; |
1013 | ti->error = "Unrecognised feature requested"; | 1034 | else if (!strcmp("keep_log", argv[0])) |
1035 | ms->features |= DM_RAID1_KEEP_LOG; | ||
1036 | else { | ||
1037 | ti->error = "Unrecognised feature requested"; | ||
1038 | return -EINVAL; | ||
1039 | } | ||
1040 | |||
1041 | argc--; | ||
1042 | argv++; | ||
1043 | (*args_used)++; | ||
1044 | } | ||
1045 | if (!errors_handled(ms) && keep_log(ms)) { | ||
1046 | ti->error = "keep_log feature requires the handle_errors feature"; | ||
1014 | return -EINVAL; | 1047 | return -EINVAL; |
1015 | } | 1048 | } |
1016 | 1049 | ||
1017 | (*args_used)++; | ||
1018 | |||
1019 | return 0; | 1050 | return 0; |
1020 | } | 1051 | } |
1021 | 1052 | ||
@@ -1029,7 +1060,7 @@ static int parse_features(struct mirror_set *ms, unsigned argc, char **argv, | |||
1029 | * log_type is "core" or "disk" | 1060 | * log_type is "core" or "disk" |
1030 | * #log_params is between 1 and 3 | 1061 | * #log_params is between 1 and 3 |
1031 | * | 1062 | * |
1032 | * If present, features must be "handle_errors". | 1063 | * If present, supported features are "handle_errors" and "keep_log". |
1033 | */ | 1064 | */ |
1034 | static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 1065 | static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) |
1035 | { | 1066 | { |
@@ -1254,8 +1285,6 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) | |||
1254 | dm_bio_restore(bd, bio); | 1285 | dm_bio_restore(bd, bio); |
1255 | bio_record->details.bi_bdev = NULL; | 1286 | bio_record->details.bi_bdev = NULL; |
1256 | 1287 | ||
1257 | atomic_inc(&bio->bi_remaining); | ||
1258 | |||
1259 | queue_bio(ms, bio, rw); | 1288 | queue_bio(ms, bio, rw); |
1260 | return DM_ENDIO_INCOMPLETE; | 1289 | return DM_ENDIO_INCOMPLETE; |
1261 | } | 1290 | } |
@@ -1365,6 +1394,7 @@ static void mirror_status(struct dm_target *ti, status_type_t type, | |||
1365 | unsigned status_flags, char *result, unsigned maxlen) | 1394 | unsigned status_flags, char *result, unsigned maxlen) |
1366 | { | 1395 | { |
1367 | unsigned int m, sz = 0; | 1396 | unsigned int m, sz = 0; |
1397 | int num_feature_args = 0; | ||
1368 | struct mirror_set *ms = (struct mirror_set *) ti->private; | 1398 | struct mirror_set *ms = (struct mirror_set *) ti->private; |
1369 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); | 1399 | struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); |
1370 | char buffer[ms->nr_mirrors + 1]; | 1400 | char buffer[ms->nr_mirrors + 1]; |
@@ -1394,8 +1424,17 @@ static void mirror_status(struct dm_target *ti, status_type_t type, | |||
1394 | DMEMIT(" %s %llu", ms->mirror[m].dev->name, | 1424 | DMEMIT(" %s %llu", ms->mirror[m].dev->name, |
1395 | (unsigned long long)ms->mirror[m].offset); | 1425 | (unsigned long long)ms->mirror[m].offset); |
1396 | 1426 | ||
1397 | if (ms->features & DM_RAID1_HANDLE_ERRORS) | 1427 | num_feature_args += !!errors_handled(ms); |
1398 | DMEMIT(" 1 handle_errors"); | 1428 | num_feature_args += !!keep_log(ms); |
1429 | if (num_feature_args) { | ||
1430 | DMEMIT(" %d", num_feature_args); | ||
1431 | if (errors_handled(ms)) | ||
1432 | DMEMIT(" handle_errors"); | ||
1433 | if (keep_log(ms)) | ||
1434 | DMEMIT(" keep_log"); | ||
1435 | } | ||
1436 | |||
1437 | break; | ||
1399 | } | 1438 | } |
1400 | } | 1439 | } |
1401 | 1440 | ||
@@ -1415,7 +1454,7 @@ static int mirror_iterate_devices(struct dm_target *ti, | |||
1415 | 1454 | ||
1416 | static struct target_type mirror_target = { | 1455 | static struct target_type mirror_target = { |
1417 | .name = "mirror", | 1456 | .name = "mirror", |
1418 | .version = {1, 13, 2}, | 1457 | .version = {1, 14, 0}, |
1419 | .module = THIS_MODULE, | 1458 | .module = THIS_MODULE, |
1420 | .ctr = mirror_ctr, | 1459 | .ctr = mirror_ctr, |
1421 | .dtr = mirror_dtr, | 1460 | .dtr = mirror_dtr, |