summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Snitzer <snitzer@redhat.com>2017-06-15 08:39:15 -0400
committerMike Snitzer <snitzer@redhat.com>2017-06-15 08:39:15 -0400
commitcd15fb64ee56192760ad5c1e2ad97a65e735b18b (patch)
tree971d9033cab38cf860c72d081e57922416ca5b21
parent2ad50606f847a902303a5364b7cad64bdd6246f6 (diff)
Revert "dm mirror: use all available legs on multiple failures"
This reverts commit 12a7cf5ba6c776a2621d8972c7d42e8d3d959d20. This commit apparently attempted to fix an issue that didn't really exist, furthermore: this commit is the source of deadlocks and crashes seen in multiple cases related to failing the primary mirror dev while syncing. Reported-by: Jonathan Brassow <jbrassow@redhat.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r--drivers/md/dm-raid1.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index e61c45047c25..4da8858856fb 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -145,6 +145,7 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
145 145
146struct dm_raid1_bio_record { 146struct dm_raid1_bio_record {
147 struct mirror *m; 147 struct mirror *m;
148 /* if details->bi_bdev == NULL, details were not saved */
148 struct dm_bio_details details; 149 struct dm_bio_details details;
149 region_t write_region; 150 region_t write_region;
150}; 151};
@@ -1198,6 +1199,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
1198 struct dm_raid1_bio_record *bio_record = 1199 struct dm_raid1_bio_record *bio_record =
1199 dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); 1200 dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
1200 1201
1202 bio_record->details.bi_bdev = NULL;
1203
1201 if (rw == WRITE) { 1204 if (rw == WRITE) {
1202 /* Save region for mirror_end_io() handler */ 1205 /* Save region for mirror_end_io() handler */
1203 bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio); 1206 bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
@@ -1256,12 +1259,22 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
1256 } 1259 }
1257 1260
1258 if (error == -EOPNOTSUPP) 1261 if (error == -EOPNOTSUPP)
1259 return error; 1262 goto out;
1260 1263
1261 if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD)) 1264 if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
1262 return error; 1265 goto out;
1263 1266
1264 if (unlikely(error)) { 1267 if (unlikely(error)) {
1268 if (!bio_record->details.bi_bdev) {
1269 /*
1270 * There wasn't enough memory to record necessary
1271 * information for a retry or there was no other
1272 * mirror in-sync.
1273 */
1274 DMERR_LIMIT("Mirror read failed.");
1275 return -EIO;
1276 }
1277
1265 m = bio_record->m; 1278 m = bio_record->m;
1266 1279
1267 DMERR("Mirror read failed from %s. Trying alternative device.", 1280 DMERR("Mirror read failed from %s. Trying alternative device.",
@@ -1277,6 +1290,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
1277 bd = &bio_record->details; 1290 bd = &bio_record->details;
1278 1291
1279 dm_bio_restore(bd, bio); 1292 dm_bio_restore(bd, bio);
1293 bio_record->details.bi_bdev = NULL;
1280 bio->bi_error = 0; 1294 bio->bi_error = 0;
1281 1295
1282 queue_bio(ms, bio, rw); 1296 queue_bio(ms, bio, rw);
@@ -1285,6 +1299,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
1285 DMERR("All replicated volumes dead, failing I/O"); 1299 DMERR("All replicated volumes dead, failing I/O");
1286 } 1300 }
1287 1301
1302out:
1303 bio_record->details.bi_bdev = NULL;
1304
1288 return error; 1305 return error;
1289} 1306}
1290 1307