aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-raid1.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r--drivers/md/dm-raid1.c77
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
29static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); 31static 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
375static 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
373static void do_recovery(struct mirror_set *ms) 386static 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 */
1034static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) 1065static 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
1416static struct target_type mirror_target = { 1455static 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,