Revert "dm mirror: use all available legs on multiple failures"
This reverts commit 12a7cf5ba6
.
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>
This commit is contained in:
@@ -145,6 +145,7 @@ static void dispatch_bios(void *context, struct bio_list *bio_list)
|
|||||||
|
|
||||||
struct dm_raid1_bio_record {
|
struct dm_raid1_bio_record {
|
||||||
struct mirror *m;
|
struct mirror *m;
|
||||||
|
/* if details->bi_bdev == NULL, details were not saved */
|
||||||
struct dm_bio_details details;
|
struct dm_bio_details details;
|
||||||
region_t write_region;
|
region_t write_region;
|
||||||
};
|
};
|
||||||
@@ -1198,6 +1199,8 @@ static int mirror_map(struct dm_target *ti, struct bio *bio)
|
|||||||
struct dm_raid1_bio_record *bio_record =
|
struct dm_raid1_bio_record *bio_record =
|
||||||
dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
|
dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record));
|
||||||
|
|
||||||
|
bio_record->details.bi_bdev = NULL;
|
||||||
|
|
||||||
if (rw == WRITE) {
|
if (rw == WRITE) {
|
||||||
/* Save region for mirror_end_io() handler */
|
/* Save region for mirror_end_io() handler */
|
||||||
bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio);
|
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error == -EOPNOTSUPP)
|
if (error == -EOPNOTSUPP)
|
||||||
return error;
|
goto out;
|
||||||
|
|
||||||
if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
|
if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
|
||||||
return error;
|
goto out;
|
||||||
|
|
||||||
if (unlikely(error)) {
|
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;
|
m = bio_record->m;
|
||||||
|
|
||||||
DMERR("Mirror read failed from %s. Trying alternative device.",
|
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)
|
|||||||
bd = &bio_record->details;
|
bd = &bio_record->details;
|
||||||
|
|
||||||
dm_bio_restore(bd, bio);
|
dm_bio_restore(bd, bio);
|
||||||
|
bio_record->details.bi_bdev = NULL;
|
||||||
bio->bi_error = 0;
|
bio->bi_error = 0;
|
||||||
|
|
||||||
queue_bio(ms, bio, rw);
|
queue_bio(ms, bio, rw);
|
||||||
@@ -1285,6 +1299,9 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
|
|||||||
DMERR("All replicated volumes dead, failing I/O");
|
DMERR("All replicated volumes dead, failing I/O");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
bio_record->details.bi_bdev = NULL;
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user