diff options
author | Mike Accetta <maccetta@laurelnetworks.com> | 2007-06-12 11:09:35 +1000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-08-04 09:10:23 -0700 |
commit | 56d39b59e95b269654940a0d26904229781380e6 (patch) | |
tree | 089fd5fbed105471e2e2c5a4615e78e66eedfca6 | |
parent | 9711bd8cc17e4f0791536d72c7f330af91672b86 (diff) |
md: Fix bug in error handling during raid1 repair.
If raid1/repair (which reads all block and fixes any differences
it finds) hits a read error, it doesn't reset the bio for writing
before writing correct data back, so the read error isn't fixed,
and the device probably gets a zero-length write which it might
complain about.
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/md/raid1.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 3a95cc5e029..46677d7d998 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1240,17 +1240,24 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) } r1_bio->read_disk = primary; for (i=0; i<mddev->raid_disks; i++) - if (r1_bio->bios[i]->bi_end_io == end_sync_read && - test_bit(BIO_UPTODATE, &r1_bio->bios[i]->bi_flags)) { + if (r1_bio->bios[i]->bi_end_io == end_sync_read) { int j; int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9); struct bio *pbio = r1_bio->bios[primary]; struct bio *sbio = r1_bio->bios[i]; - for (j = vcnt; j-- ; ) - if (memcmp(page_address(pbio->bi_io_vec[j].bv_page), - page_address(sbio->bi_io_vec[j].bv_page), - PAGE_SIZE)) - break; + + if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) { + for (j = vcnt; j-- ; ) { + struct page *p, *s; + p = pbio->bi_io_vec[j].bv_page; + s = sbio->bi_io_vec[j].bv_page; + if (memcmp(page_address(p), + page_address(s), + PAGE_SIZE)) + break; + } + } else + j = 0; if (j >= 0) mddev->resync_mismatches += r1_bio->sectors; if (j < 0 || test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) { |