From: Mike Snitzer snitzer@redhat.com
[ Upstream commit cd15fb64ee56192760ad5c1e2ad97a65e735b18b ]
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 Signed-off-by: Sasha Levin alexander.levin@microsoft.com --- drivers/md/dm-raid1.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 9a8b71067c6e..7a6254d54baf 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)
struct dm_raid1_bio_record { struct mirror *m; + /* if details->bi_bdev == NULL, details were not saved */ struct dm_bio_details details; region_t write_region; }; @@ -1199,6 +1200,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio) struct dm_raid1_bio_record *bio_record = dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
+ bio_record->details.bi_bdev = NULL; + if (rw == WRITE) { /* Save region for mirror_end_io() handler */ bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio); @@ -1257,12 +1260,22 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) }
if (error == -EOPNOTSUPP) - return error; + goto out;
if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD)) - return error; + goto out;
if (unlikely(error)) { + if (!bio_record->details.bi_bdev) { + /* + * There wasn't enough memory to record necessary + * information for a retry or there was no other + * mirror in-sync. + */ + DMERR_LIMIT("Mirror read failed."); + return -EIO; + } + m = bio_record->m;
DMERR("Mirror read failed from %s. Trying alternative device.", @@ -1278,6 +1291,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) bd = &bio_record->details;
dm_bio_restore(bd, bio); + bio_record->details.bi_bdev = NULL; bio->bi_error = 0;
queue_bio(ms, bio, rw); @@ -1286,6 +1300,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) DMERR("All replicated volumes dead, failing I/O"); }
+out: + bio_record->details.bi_bdev = NULL; + return error; }