diff options
author | NeilBrown <neilb@suse.de> | 2011-07-27 21:39:25 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2011-07-27 21:39:25 -0400 |
commit | 1a0b7cd82657a590f163b090bd9123a3a6b9aae4 (patch) | |
tree | 0dc3ccf6ad6ad88283e6d7924c38524865866cba /drivers | |
parent | f84ee364dd15af11cada1e673f94128f62db189e (diff) |
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: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/raid10.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 10415ddfcb42..e54ff3274eda 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1452,9 +1452,10 @@ static void end_sync_write(struct bio *bio, int error) | |||
1452 | 1452 | ||
1453 | d = find_bio_disk(conf, r10_bio, bio, &slot); | 1453 | d = find_bio_disk(conf, r10_bio, bio, &slot); |
1454 | 1454 | ||
1455 | if (!uptodate) | 1455 | if (!uptodate) { |
1456 | md_error(mddev, conf->mirrors[d].rdev); | 1456 | set_bit(WriteErrorSeen, &conf->mirrors[d].rdev->flags); |
1457 | else if (is_badblock(conf->mirrors[d].rdev, | 1457 | set_bit(R10BIO_WriteError, &r10_bio->state); |
1458 | } else if (is_badblock(conf->mirrors[d].rdev, | ||
1458 | r10_bio->devs[slot].addr, | 1459 | r10_bio->devs[slot].addr, |
1459 | r10_bio->sectors, | 1460 | r10_bio->sectors, |
1460 | &first_bad, &bad_sectors)) | 1461 | &first_bad, &bad_sectors)) |
@@ -1465,7 +1466,8 @@ static void end_sync_write(struct bio *bio, int error) | |||
1465 | if (r10_bio->master_bio == NULL) { | 1466 | if (r10_bio->master_bio == NULL) { |
1466 | /* the primary of several recovery bios */ | 1467 | /* the primary of several recovery bios */ |
1467 | sector_t s = r10_bio->sectors; | 1468 | sector_t s = r10_bio->sectors; |
1468 | if (test_bit(R10BIO_MadeGood, &r10_bio->state)) | 1469 | if (test_bit(R10BIO_MadeGood, &r10_bio->state) || |
1470 | test_bit(R10BIO_WriteError, &r10_bio->state)) | ||
1469 | reschedule_retry(r10_bio); | 1471 | reschedule_retry(r10_bio); |
1470 | else | 1472 | else |
1471 | put_buf(r10_bio); | 1473 | put_buf(r10_bio); |
@@ -1473,7 +1475,8 @@ static void end_sync_write(struct bio *bio, int error) | |||
1473 | break; | 1475 | break; |
1474 | } else { | 1476 | } else { |
1475 | r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio; | 1477 | r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio; |
1476 | if (test_bit(R10BIO_MadeGood, &r10_bio->state)) | 1478 | if (test_bit(R10BIO_MadeGood, &r10_bio->state) || |
1479 | test_bit(R10BIO_WriteError, &r10_bio->state)) | ||
1477 | reschedule_retry(r10_bio); | 1480 | reschedule_retry(r10_bio); |
1478 | else | 1481 | else |
1479 | put_buf(r10_bio); | 1482 | put_buf(r10_bio); |
@@ -2029,23 +2032,33 @@ static void handle_write_completed(conf_t *conf, r10bio_t *r10_bio) | |||
2029 | /* Some sort of write request has finished and it | 2032 | /* Some sort of write request has finished and it |
2030 | * succeeded in writing where we thought there was a | 2033 | * succeeded in writing where we thought there was a |
2031 | * bad block. So forget the bad block. | 2034 | * bad block. So forget the bad block. |
2035 | * Or possibly if failed and we need to record | ||
2036 | * a bad block. | ||
2032 | */ | 2037 | */ |
2033 | int m; | 2038 | int m; |
2034 | mdk_rdev_t *rdev; | 2039 | mdk_rdev_t *rdev; |
2035 | 2040 | ||
2036 | if (test_bit(R10BIO_IsSync, &r10_bio->state) || | 2041 | if (test_bit(R10BIO_IsSync, &r10_bio->state) || |
2037 | test_bit(R10BIO_IsRecover, &r10_bio->state)) { | 2042 | test_bit(R10BIO_IsRecover, &r10_bio->state)) { |
2038 | for (m = 0; m < conf->copies; m++) | 2043 | for (m = 0; m < conf->copies; m++) { |
2039 | if (r10_bio->devs[m].bio && | 2044 | int dev = r10_bio->devs[m].devnum; |
2040 | test_bit(BIO_UPTODATE, | 2045 | rdev = conf->mirrors[dev].rdev; |
2046 | if (r10_bio->devs[m].bio == NULL) | ||
2047 | continue; | ||
2048 | if (test_bit(BIO_UPTODATE, | ||
2041 | &r10_bio->devs[m].bio->bi_flags)) { | 2049 | &r10_bio->devs[m].bio->bi_flags)) { |
2042 | int dev = r10_bio->devs[m].devnum; | ||
2043 | rdev = conf->mirrors[dev].rdev; | ||
2044 | rdev_clear_badblocks( | 2050 | rdev_clear_badblocks( |
2045 | rdev, | 2051 | rdev, |
2046 | r10_bio->devs[m].addr, | 2052 | r10_bio->devs[m].addr, |
2047 | r10_bio->sectors); | 2053 | r10_bio->sectors); |
2054 | } else { | ||
2055 | if (!rdev_set_badblocks( | ||
2056 | rdev, | ||
2057 | r10_bio->devs[m].addr, | ||
2058 | r10_bio->sectors, 0)) | ||
2059 | md_error(conf->mddev, rdev); | ||
2048 | } | 2060 | } |
2061 | } | ||
2049 | put_buf(r10_bio); | 2062 | put_buf(r10_bio); |
2050 | } else { | 2063 | } else { |
2051 | for (m = 0; m < conf->copies; m++) { | 2064 | for (m = 0; m < conf->copies; m++) { |