Commit 1a0b7cd8 authored by NeilBrown's avatar NeilBrown

md/raid10: record bad blocks due to write errors during resync/recovery.

If we get a write error during resync/recovery don't fail the device
but instead record a bad block.  If that fails we can then fail the
device.
Signed-off-by: default avatarNeilBrown <neilb@suse.de>
parent f84ee364
...@@ -1452,9 +1452,10 @@ static void end_sync_write(struct bio *bio, int error) ...@@ -1452,9 +1452,10 @@ static void end_sync_write(struct bio *bio, int error)
d = find_bio_disk(conf, r10_bio, bio, &slot); d = find_bio_disk(conf, r10_bio, bio, &slot);
if (!uptodate) if (!uptodate) {
md_error(mddev, conf->mirrors[d].rdev); set_bit(WriteErrorSeen, &conf->mirrors[d].rdev->flags);
else if (is_badblock(conf->mirrors[d].rdev, set_bit(R10BIO_WriteError, &r10_bio->state);
} else if (is_badblock(conf->mirrors[d].rdev,
r10_bio->devs[slot].addr, r10_bio->devs[slot].addr,
r10_bio->sectors, r10_bio->sectors,
&first_bad, &bad_sectors)) &first_bad, &bad_sectors))
...@@ -1465,7 +1466,8 @@ static void end_sync_write(struct bio *bio, int error) ...@@ -1465,7 +1466,8 @@ static void end_sync_write(struct bio *bio, int error)
if (r10_bio->master_bio == NULL) { if (r10_bio->master_bio == NULL) {
/* the primary of several recovery bios */ /* the primary of several recovery bios */
sector_t s = r10_bio->sectors; sector_t s = r10_bio->sectors;
if (test_bit(R10BIO_MadeGood, &r10_bio->state)) if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
test_bit(R10BIO_WriteError, &r10_bio->state))
reschedule_retry(r10_bio); reschedule_retry(r10_bio);
else else
put_buf(r10_bio); put_buf(r10_bio);
...@@ -1473,7 +1475,8 @@ static void end_sync_write(struct bio *bio, int error) ...@@ -1473,7 +1475,8 @@ static void end_sync_write(struct bio *bio, int error)
break; break;
} else { } else {
r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio; r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio;
if (test_bit(R10BIO_MadeGood, &r10_bio->state)) if (test_bit(R10BIO_MadeGood, &r10_bio->state) ||
test_bit(R10BIO_WriteError, &r10_bio->state))
reschedule_retry(r10_bio); reschedule_retry(r10_bio);
else else
put_buf(r10_bio); put_buf(r10_bio);
...@@ -2029,23 +2032,33 @@ static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio) ...@@ -2029,23 +2032,33 @@ static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio)
/* Some sort of write request has finished and it /* Some sort of write request has finished and it
* succeeded in writing where we thought there was a * succeeded in writing where we thought there was a
* bad block. So forget the bad block. * bad block. So forget the bad block.
* Or possibly if failed and we need to record
* a bad block.
*/ */
int m; int m;
mdk_rdev_t *rdev; mdk_rdev_t *rdev;
if (test_bit(R10BIO_IsSync, &r10_bio->state) || if (test_bit(R10BIO_IsSync, &r10_bio->state) ||
test_bit(R10BIO_IsRecover, &r10_bio->state)) { test_bit(R10BIO_IsRecover, &r10_bio->state)) {
for (m = 0; m < conf->copies; m++) for (m = 0; m < conf->copies; m++) {
if (r10_bio->devs[m].bio && int dev = r10_bio->devs[m].devnum;
test_bit(BIO_UPTODATE, rdev = conf->mirrors[dev].rdev;
if (r10_bio->devs[m].bio == NULL)
continue;
if (test_bit(BIO_UPTODATE,
&r10_bio->devs[m].bio->bi_flags)) { &r10_bio->devs[m].bio->bi_flags)) {
int dev = r10_bio->devs[m].devnum;
rdev = conf->mirrors[dev].rdev;
rdev_clear_badblocks( rdev_clear_badblocks(
rdev, rdev,
r10_bio->devs[m].addr, r10_bio->devs[m].addr,
r10_bio->sectors); r10_bio->sectors);
} else {
if (!rdev_set_badblocks(
rdev,
r10_bio->devs[m].addr,
r10_bio->sectors, 0))
md_error(conf->mddev, rdev);
} }
}
put_buf(r10_bio); put_buf(r10_bio);
} else { } else {
for (m = 0; m < conf->copies; m++) { for (m = 0; m < conf->copies; m++) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment