aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid10.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:20:37 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:06 -0500
commit097426f689f179747f3cd6b4749eb2a6b605702d (patch)
tree92b0a78f8aebedd4afdb52dfa23b311a4468719d /drivers/md/raid10.c
parent2604b703b6b3db80e3c75ce472a54dfd0b7bf9f4 (diff)
[PATCH] md: fix possible problem in raid1/raid10 error overwriting
The code to overwrite/reread for addressing read errors in raid1/raid10 currently assumes that the read will not alter the buffer which could be used to write to the next device. This is not a safe assumption to make. So we split the loops into a overwrite loop and a separate re-read loop, so that the writing is complete before reading is attempted. Cc: Paul Clements <paul.clements@steeleye.com> 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/raid10.c')
-rw-r--r--drivers/md/raid10.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index f23d52c5df94..9647ebb0983a 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1421,6 +1421,7 @@ static void raid10d(mddev_t *mddev)
1421 } while (!success && sl != r10_bio->read_slot); 1421 } while (!success && sl != r10_bio->read_slot);
1422 1422
1423 if (success) { 1423 if (success) {
1424 int start = sl;
1424 /* write it back and re-read */ 1425 /* write it back and re-read */
1425 while (sl != r10_bio->read_slot) { 1426 while (sl != r10_bio->read_slot) {
1426 int d; 1427 int d;
@@ -1434,14 +1435,27 @@ static void raid10d(mddev_t *mddev)
1434 if (sync_page_io(rdev->bdev, 1435 if (sync_page_io(rdev->bdev,
1435 r10_bio->devs[sl].addr + 1436 r10_bio->devs[sl].addr +
1436 sect + rdev->data_offset, 1437 sect + rdev->data_offset,
1437 s<<9, conf->tmppage, WRITE) == 0 || 1438 s<<9, conf->tmppage, WRITE) == 0)
1438 sync_page_io(rdev->bdev, 1439 /* Well, this device is dead */
1440 md_error(mddev, rdev);
1441 }
1442 }
1443 sl = start;
1444 while (sl != r10_bio->read_slot) {
1445 int d;
1446 if (sl==0)
1447 sl = conf->copies;
1448 sl--;
1449 d = r10_bio->devs[sl].devnum;
1450 rdev = conf->mirrors[d].rdev;
1451 if (rdev &&
1452 test_bit(In_sync, &rdev->flags)) {
1453 if (sync_page_io(rdev->bdev,
1439 r10_bio->devs[sl].addr + 1454 r10_bio->devs[sl].addr +
1440 sect + rdev->data_offset, 1455 sect + rdev->data_offset,
1441 s<<9, conf->tmppage, READ) == 0) { 1456 s<<9, conf->tmppage, READ) == 0)
1442 /* Well, this device is dead */ 1457 /* Well, this device is dead */
1443 md_error(mddev, rdev); 1458 md_error(mddev, rdev);
1444 }
1445 } 1459 }
1446 } 1460 }
1447 } else { 1461 } else {