瀏覽代碼

dm mirror: use all available legs on multiple failures

When any leg(s) have failed, any read will cause a new operational
default leg to be selected and the read is resubmitted to it.  If that
new default leg fails the read too, no other still accessible legs are
used to resubmit the read again -- thus failing the io.

Fix by allowing the read to get resubmitted until all operational legs
have been exhausted.  Also, remove any details.bi_dev use as a flag.

Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Heinz Mauelshagen 8 年之前
父節點
當前提交
12a7cf5ba6
共有 1 個文件被更改,包括 2 次插入19 次删除
  1. 2 19
      drivers/md/dm-raid1.c

+ 2 - 19
drivers/md/dm-raid1.c

@@ -145,7 +145,6 @@ 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;
 };
 };
@@ -1200,8 +1199,6 @@ 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);
@@ -1260,22 +1257,12 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error)
 	}
 	}
 
 
 	if (error == -EOPNOTSUPP)
 	if (error == -EOPNOTSUPP)
-		goto out;
+		return error;
 
 
 	if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
 	if ((error == -EWOULDBLOCK) && (bio->bi_opf & REQ_RAHEAD))
-		goto out;
+		return error;
 
 
 	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.",
@@ -1291,7 +1278,6 @@ 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);
@@ -1300,9 +1286,6 @@ 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;
 }
 }