aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:20:22 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:04 -0500
commit69382e85371c232df71524137a806b9c210ec021 (patch)
tree03e49cece85cb74ce38e37afbdef718efa2b3695 /drivers/md
parent3e198f7826f830604f3aa7c20359a773e70cbeaa (diff)
[PATCH] md: better handling for read error in raid1 during resync
Handling of read errors during resync is separate from handling of read errors during normal IO in raid1. A previous patch added support for read errors during normal IO. This one adds support for read errors during resync or recovery. The key differences are that we don't need to freeze the array, because the normal handling of resync means that this part of the array will be idle except for resync, and the read/overwrite/re-read is needed in a separate piece of code. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/raid1.c99
1 files changed, 78 insertions, 21 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ea1f1eb93c77..14a8fe0349c7 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1072,9 +1072,7 @@ abort:
1072 1072
1073static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) 1073static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
1074{ 1074{
1075 int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
1076 r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); 1075 r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private);
1077 conf_t *conf = mddev_to_conf(r1_bio->mddev);
1078 1076
1079 if (bio->bi_size) 1077 if (bio->bi_size)
1080 return 1; 1078 return 1;
@@ -1087,10 +1085,7 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
1087 * or re-read if the read failed. 1085 * or re-read if the read failed.
1088 * We don't do much here, just schedule handling by raid1d 1086 * We don't do much here, just schedule handling by raid1d
1089 */ 1087 */
1090 if (!uptodate) { 1088 if (test_bit(BIO_UPTODATE, &bio->bi_flags))
1091 md_error(r1_bio->mddev,
1092 conf->mirrors[r1_bio->read_disk].rdev);
1093 } else
1094 set_bit(R1BIO_Uptodate, &r1_bio->state); 1089 set_bit(R1BIO_Uptodate, &r1_bio->state);
1095 reschedule_retry(r1_bio); 1090 reschedule_retry(r1_bio);
1096 return 0; 1091 return 0;
@@ -1134,27 +1129,89 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
1134 1129
1135 bio = r1_bio->bios[r1_bio->read_disk]; 1130 bio = r1_bio->bios[r1_bio->read_disk];
1136 1131
1137/* 1132
1138 if (r1_bio->sector == 0) printk("First sync write startss\n");
1139*/
1140 /* 1133 /*
1141 * schedule writes 1134 * schedule writes
1142 */ 1135 */
1143 if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) { 1136 if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) {
1144 /* 1137 /* ouch - failed to read all of that.
1145 * There is no point trying a read-for-reconstruct as 1138 * Try some synchronous reads of other devices to get
1146 * reconstruct is about to be aborted 1139 * good data, much like with normal read errors. Only
1140 * read into the pages we already have so they we don't
1141 * need to re-issue the read request.
1142 * We don't need to freeze the array, because being in an
1143 * active sync request, there is no normal IO, and
1144 * no overlapping syncs.
1147 */ 1145 */
1148 char b[BDEVNAME_SIZE]; 1146 sector_t sect = r1_bio->sector;
1149 printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error" 1147 int sectors = r1_bio->sectors;
1150 " for block %llu\n", 1148 int idx = 0;
1151 bdevname(bio->bi_bdev,b), 1149
1152 (unsigned long long)r1_bio->sector); 1150 while(sectors) {
1153 md_done_sync(mddev, r1_bio->sectors, 0); 1151 int s = sectors;
1154 put_buf(r1_bio); 1152 int d = r1_bio->read_disk;
1155 return; 1153 int success = 0;
1154 mdk_rdev_t *rdev;
1155
1156 if (s > (PAGE_SIZE>>9))
1157 s = PAGE_SIZE >> 9;
1158 do {
1159 if (r1_bio->bios[d]->bi_end_io == end_sync_read) {
1160 rdev = conf->mirrors[d].rdev;
1161 if (sync_page_io(rdev->bdev,
1162 sect + rdev->data_offset,
1163 s<<9,
1164 bio->bi_io_vec[idx].bv_page,
1165 READ)) {
1166 success = 1;
1167 break;
1168 }
1169 }
1170 d++;
1171 if (d == conf->raid_disks)
1172 d = 0;
1173 } while (!success && d != r1_bio->read_disk);
1174
1175 if (success) {
1176 /* write it back and re-read */
1177 set_bit(R1BIO_Uptodate, &r1_bio->state);
1178 while (d != r1_bio->read_disk) {
1179 if (d == 0)
1180 d = conf->raid_disks;
1181 d--;
1182 if (r1_bio->bios[d]->bi_end_io != end_sync_read)
1183 continue;
1184 rdev = conf->mirrors[d].rdev;
1185 if (sync_page_io(rdev->bdev,
1186 sect + rdev->data_offset,
1187 s<<9,
1188 bio->bi_io_vec[idx].bv_page,
1189 WRITE) == 0 ||
1190 sync_page_io(rdev->bdev,
1191 sect + rdev->data_offset,
1192 s<<9,
1193 bio->bi_io_vec[idx].bv_page,
1194 READ) == 0) {
1195 md_error(mddev, rdev);
1196 }
1197 }
1198 } else {
1199 char b[BDEVNAME_SIZE];
1200 /* Cannot read from anywhere, array is toast */
1201 md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
1202 printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error"
1203 " for block %llu\n",
1204 bdevname(bio->bi_bdev,b),
1205 (unsigned long long)r1_bio->sector);
1206 md_done_sync(mddev, r1_bio->sectors, 0);
1207 put_buf(r1_bio);
1208 return;
1209 }
1210 sectors -= s;
1211 sect += s;
1212 idx ++;
1213 }
1156 } 1214 }
1157
1158 atomic_set(&r1_bio->remaining, 1); 1215 atomic_set(&r1_bio->remaining, 1);
1159 for (i = 0; i < disks ; i++) { 1216 for (i = 0; i < disks ; i++) {
1160 wbio = r1_bio->bios[i]; 1217 wbio = r1_bio->bios[i];