diff options
| -rw-r--r-- | drivers/md/dm-raid1.c | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index cb3f318a3692..2a3e2f80aa4b 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | #define DM_MSG_PREFIX "raid1" | 23 | #define DM_MSG_PREFIX "raid1" |
| 24 | 24 | ||
| 25 | #define DM_RAID1_HANDLE_ERRORS 0x01 | ||
| 26 | |||
| 25 | static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); | 27 | static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); |
| 26 | 28 | ||
| 27 | /*----------------------------------------------------------------- | 29 | /*----------------------------------------------------------------- |
| @@ -118,6 +120,7 @@ struct mirror_set { | |||
| 118 | struct list_head list; | 120 | struct list_head list; |
| 119 | struct region_hash rh; | 121 | struct region_hash rh; |
| 120 | struct kcopyd_client *kcopyd_client; | 122 | struct kcopyd_client *kcopyd_client; |
| 123 | uint64_t features; | ||
| 121 | 124 | ||
| 122 | spinlock_t lock; /* protects the next two lists */ | 125 | spinlock_t lock; /* protects the next two lists */ |
| 123 | struct bio_list reads; | 126 | struct bio_list reads; |
| @@ -1010,14 +1013,54 @@ static struct dirty_log *create_dirty_log(struct dm_target *ti, | |||
| 1010 | return dl; | 1013 | return dl; |
| 1011 | } | 1014 | } |
| 1012 | 1015 | ||
| 1016 | static int parse_features(struct mirror_set *ms, unsigned argc, char **argv, | ||
| 1017 | unsigned *args_used) | ||
| 1018 | { | ||
| 1019 | unsigned num_features; | ||
| 1020 | struct dm_target *ti = ms->ti; | ||
| 1021 | |||
| 1022 | *args_used = 0; | ||
| 1023 | |||
| 1024 | if (!argc) | ||
| 1025 | return 0; | ||
| 1026 | |||
| 1027 | if (sscanf(argv[0], "%u", &num_features) != 1) { | ||
| 1028 | ti->error = "Invalid number of features"; | ||
| 1029 | return -EINVAL; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | argc--; | ||
| 1033 | argv++; | ||
| 1034 | (*args_used)++; | ||
| 1035 | |||
| 1036 | if (num_features > argc) { | ||
| 1037 | ti->error = "Not enough arguments to support feature count"; | ||
| 1038 | return -EINVAL; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | if (!strcmp("handle_errors", argv[0])) | ||
| 1042 | ms->features |= DM_RAID1_HANDLE_ERRORS; | ||
| 1043 | else { | ||
| 1044 | ti->error = "Unrecognised feature requested"; | ||
| 1045 | return -EINVAL; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | (*args_used)++; | ||
| 1049 | |||
| 1050 | return 0; | ||
| 1051 | } | ||
| 1052 | |||
| 1013 | /* | 1053 | /* |
| 1014 | * Construct a mirror mapping: | 1054 | * Construct a mirror mapping: |
| 1015 | * | 1055 | * |
| 1016 | * log_type #log_params <log_params> | 1056 | * log_type #log_params <log_params> |
| 1017 | * #mirrors [mirror_path offset]{2,} | 1057 | * #mirrors [mirror_path offset]{2,} |
| 1058 | * [#features <features>] | ||
| 1018 | * | 1059 | * |
| 1019 | * log_type is "core" or "disk" | 1060 | * log_type is "core" or "disk" |
| 1020 | * #log_params is between 1 and 3 | 1061 | * #log_params is between 1 and 3 |
| 1062 | * | ||
| 1063 | * If present, features must be "handle_errors". | ||
| 1021 | */ | 1064 | */ |
| 1022 | #define DM_IO_PAGES 64 | 1065 | #define DM_IO_PAGES 64 |
| 1023 | static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | 1066 | static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) |
| @@ -1043,8 +1086,8 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1043 | 1086 | ||
| 1044 | argv++, argc--; | 1087 | argv++, argc--; |
| 1045 | 1088 | ||
| 1046 | if (argc != nr_mirrors * 2) { | 1089 | if (argc < nr_mirrors * 2) { |
| 1047 | ti->error = "Wrong number of mirror arguments"; | 1090 | ti->error = "Too few mirror arguments"; |
| 1048 | dm_destroy_dirty_log(dl); | 1091 | dm_destroy_dirty_log(dl); |
| 1049 | return -EINVAL; | 1092 | return -EINVAL; |
| 1050 | } | 1093 | } |
| @@ -1077,6 +1120,21 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 1077 | } | 1120 | } |
| 1078 | INIT_WORK(&ms->kmirrord_work, do_mirror); | 1121 | INIT_WORK(&ms->kmirrord_work, do_mirror); |
| 1079 | 1122 | ||
| 1123 | r = parse_features(ms, argc, argv, &args_used); | ||
| 1124 | if (r) { | ||
| 1125 | free_context(ms, ti, ms->nr_mirrors); | ||
| 1126 | return r; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | argv += args_used; | ||
| 1130 | argc -= args_used; | ||
| 1131 | |||
| 1132 | if (argc) { | ||
| 1133 | ti->error = "Too many mirror arguments"; | ||
| 1134 | free_context(ms, ti, ms->nr_mirrors); | ||
| 1135 | return -EINVAL; | ||
| 1136 | } | ||
| 1137 | |||
| 1080 | r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); | 1138 | r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); |
| 1081 | if (r) { | 1139 | if (r) { |
| 1082 | destroy_workqueue(ms->kmirrord_wq); | 1140 | destroy_workqueue(ms->kmirrord_wq); |
| @@ -1230,6 +1288,9 @@ static int mirror_status(struct dm_target *ti, status_type_t type, | |||
| 1230 | for (m = 0; m < ms->nr_mirrors; m++) | 1288 | for (m = 0; m < ms->nr_mirrors; m++) |
| 1231 | DMEMIT(" %s %llu", ms->mirror[m].dev->name, | 1289 | DMEMIT(" %s %llu", ms->mirror[m].dev->name, |
| 1232 | (unsigned long long)ms->mirror[m].offset); | 1290 | (unsigned long long)ms->mirror[m].offset); |
| 1291 | |||
| 1292 | if (ms->features & DM_RAID1_HANDLE_ERRORS) | ||
| 1293 | DMEMIT(" 1 handle_errors"); | ||
| 1233 | } | 1294 | } |
| 1234 | 1295 | ||
| 1235 | return 0; | 1296 | return 0; |
