mirror of
https://github.com/torvalds/linux.git
synced 2026-06-04 04:23:35 +02:00
md/raid1: improve handling of read failure during recovery.
If we cannot read a block from anywhere during recovery, there is now a better approach than just giving up. We can record a bad block on each device and keep going - being careful not to clear the bad block when a write succeeds as it might - it will be a write of incorrect data. We have now reached the state where - for raid1 - we only call md_error if md_set_badblocks has failed. Signed-off-by: NeilBrown <neilb@suse.de> Reviewed-by: Namhyung Kim <namhyung@gmail.com>
This commit is contained in:
parent
d8f05d2995
commit
3a9f28a511
|
|
@ -1392,7 +1392,12 @@ static void end_sync_write(struct bio *bio, int error)
|
||||||
} else if (is_badblock(conf->mirrors[mirror].rdev,
|
} else if (is_badblock(conf->mirrors[mirror].rdev,
|
||||||
r1_bio->sector,
|
r1_bio->sector,
|
||||||
r1_bio->sectors,
|
r1_bio->sectors,
|
||||||
&first_bad, &bad_sectors))
|
&first_bad, &bad_sectors) &&
|
||||||
|
!is_badblock(conf->mirrors[r1_bio->read_disk].rdev,
|
||||||
|
r1_bio->sector,
|
||||||
|
r1_bio->sectors,
|
||||||
|
&first_bad, &bad_sectors)
|
||||||
|
)
|
||||||
set_bit(R1BIO_MadeGood, &r1_bio->state);
|
set_bit(R1BIO_MadeGood, &r1_bio->state);
|
||||||
|
|
||||||
update_head_pos(mirror, r1_bio);
|
update_head_pos(mirror, r1_bio);
|
||||||
|
|
@ -1473,16 +1478,36 @@ static int fix_sync_read_error(r1bio_t *r1_bio)
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
char b[BDEVNAME_SIZE];
|
char b[BDEVNAME_SIZE];
|
||||||
/* Cannot read from anywhere, array is toast */
|
int abort = 0;
|
||||||
md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
|
/* Cannot read from anywhere, this block is lost.
|
||||||
|
* Record a bad block on each device. If that doesn't
|
||||||
|
* work just disable and interrupt the recovery.
|
||||||
|
* Don't fail devices as that won't really help.
|
||||||
|
*/
|
||||||
printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O read error"
|
printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O read error"
|
||||||
" for block %llu\n",
|
" for block %llu\n",
|
||||||
mdname(mddev),
|
mdname(mddev),
|
||||||
bdevname(bio->bi_bdev, b),
|
bdevname(bio->bi_bdev, b),
|
||||||
(unsigned long long)r1_bio->sector);
|
(unsigned long long)r1_bio->sector);
|
||||||
md_done_sync(mddev, r1_bio->sectors, 0);
|
for (d = 0; d < conf->raid_disks; d++) {
|
||||||
put_buf(r1_bio);
|
rdev = conf->mirrors[d].rdev;
|
||||||
return 0;
|
if (!rdev || test_bit(Faulty, &rdev->flags))
|
||||||
|
continue;
|
||||||
|
if (!rdev_set_badblocks(rdev, sect, s, 0))
|
||||||
|
abort = 1;
|
||||||
|
}
|
||||||
|
if (abort) {
|
||||||
|
mddev->recovery_disabled = 1;
|
||||||
|
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
||||||
|
md_done_sync(mddev, r1_bio->sectors, 0);
|
||||||
|
put_buf(r1_bio);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Try next page */
|
||||||
|
sectors -= s;
|
||||||
|
sect += s;
|
||||||
|
idx++;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
start = d;
|
start = d;
|
||||||
|
|
@ -1879,7 +1904,9 @@ static void raid1d(mddev_t *mddev)
|
||||||
if (bio->bi_end_io == NULL)
|
if (bio->bi_end_io == NULL)
|
||||||
continue;
|
continue;
|
||||||
if (test_bit(BIO_UPTODATE,
|
if (test_bit(BIO_UPTODATE,
|
||||||
&bio->bi_flags)) {
|
&bio->bi_flags) &&
|
||||||
|
test_bit(R1BIO_MadeGood,
|
||||||
|
&r1_bio->state)) {
|
||||||
rdev_clear_badblocks(
|
rdev_clear_badblocks(
|
||||||
rdev,
|
rdev,
|
||||||
r1_bio->sector,
|
r1_bio->sector,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user