md: fix bug in error handling during raid1 repair
authorMike Accetta <maccetta@laurelnetworks.com>
Sat, 16 Jun 2007 17:16:07 +0000 (10:16 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Sat, 16 Jun 2007 20:16:15 +0000 (13:16 -0700)
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>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/md/raid1.c

index 3a95cc5e029c932eaddf0b85df6d6b0f744c36b8..46677d7d9980521802dc71355bb9c6478a103383 100644 (file)
@@ -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)) {