diff options
author | NeilBrown <neilb@suse.de> | 2014-02-04 20:17:01 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-22 15:41:29 -0500 |
commit | 9f2d289933e60ec726a7a9522e2dcdfdc82c58de (patch) | |
tree | 37514362cbb644dc0699d7f24a28e8006dbaa7d1 /drivers/md/raid1.c | |
parent | dbd515879a94273d4a6e1e6195d20951af2a65af (diff) |
md/raid1: restore ability for check and repair to fix read errors.
commit 1877db75589a895bbdc4c4c3f23558e57b521141 upstream.
commit 30bc9b53878a9921b02e3b5bc4283ac1c6de102a
md/raid1: fix bio handling problems in process_checks()
Move the bio_reset() to a point before where BIO_UPTODATE is checked,
so that check now always report that the bio is uptodate, even if it is not.
This causes process_check() to sometimes treat read-errors as
successful matches so the good data isn't written out.
This patch preserves the flag until it is needed.
Bug was introduced in 3.11, but backported to 3.10-stable (as it fixed
an even worse bug). So suitable for any -stable since 3.10.
Reported-and-tested-by: Michael Tokarev <mjt@tls.msk.ru>
Fixed: 30bc9b53878a9921b02e3b5bc4283ac1c6de102a
Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md/raid1.c')
-rw-r--r-- | drivers/md/raid1.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index afaa5d425e9a..e73740b55aea 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1854,11 +1854,15 @@ static int process_checks(struct r1bio *r1_bio) | |||
1854 | for (i = 0; i < conf->raid_disks * 2; i++) { | 1854 | for (i = 0; i < conf->raid_disks * 2; i++) { |
1855 | int j; | 1855 | int j; |
1856 | int size; | 1856 | int size; |
1857 | int uptodate; | ||
1857 | struct bio *b = r1_bio->bios[i]; | 1858 | struct bio *b = r1_bio->bios[i]; |
1858 | if (b->bi_end_io != end_sync_read) | 1859 | if (b->bi_end_io != end_sync_read) |
1859 | continue; | 1860 | continue; |
1860 | /* fixup the bio for reuse */ | 1861 | /* fixup the bio for reuse, but preserve BIO_UPTODATE */ |
1862 | uptodate = test_bit(BIO_UPTODATE, &b->bi_flags); | ||
1861 | bio_reset(b); | 1863 | bio_reset(b); |
1864 | if (!uptodate) | ||
1865 | clear_bit(BIO_UPTODATE, &b->bi_flags); | ||
1862 | b->bi_vcnt = vcnt; | 1866 | b->bi_vcnt = vcnt; |
1863 | b->bi_size = r1_bio->sectors << 9; | 1867 | b->bi_size = r1_bio->sectors << 9; |
1864 | b->bi_sector = r1_bio->sector + | 1868 | b->bi_sector = r1_bio->sector + |
@@ -1891,11 +1895,14 @@ static int process_checks(struct r1bio *r1_bio) | |||
1891 | int j; | 1895 | int j; |
1892 | struct bio *pbio = r1_bio->bios[primary]; | 1896 | struct bio *pbio = r1_bio->bios[primary]; |
1893 | struct bio *sbio = r1_bio->bios[i]; | 1897 | struct bio *sbio = r1_bio->bios[i]; |
1898 | int uptodate = test_bit(BIO_UPTODATE, &sbio->bi_flags); | ||
1894 | 1899 | ||
1895 | if (sbio->bi_end_io != end_sync_read) | 1900 | if (sbio->bi_end_io != end_sync_read) |
1896 | continue; | 1901 | continue; |
1902 | /* Now we can 'fixup' the BIO_UPTODATE flag */ | ||
1903 | set_bit(BIO_UPTODATE, &sbio->bi_flags); | ||
1897 | 1904 | ||
1898 | if (test_bit(BIO_UPTODATE, &sbio->bi_flags)) { | 1905 | if (uptodate) { |
1899 | for (j = vcnt; j-- ; ) { | 1906 | for (j = vcnt; j-- ; ) { |
1900 | struct page *p, *s; | 1907 | struct page *p, *s; |
1901 | p = pbio->bi_io_vec[j].bv_page; | 1908 | p = pbio->bi_io_vec[j].bv_page; |
@@ -1910,7 +1917,7 @@ static int process_checks(struct r1bio *r1_bio) | |||
1910 | if (j >= 0) | 1917 | if (j >= 0) |
1911 | atomic64_add(r1_bio->sectors, &mddev->resync_mismatches); | 1918 | atomic64_add(r1_bio->sectors, &mddev->resync_mismatches); |
1912 | if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery) | 1919 | if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery) |
1913 | && test_bit(BIO_UPTODATE, &sbio->bi_flags))) { | 1920 | && uptodate)) { |
1914 | /* No need to write to this device. */ | 1921 | /* No need to write to this device. */ |
1915 | sbio->bi_end_io = NULL; | 1922 | sbio->bi_end_io = NULL; |
1916 | rdev_dec_pending(conf->mirrors[i].rdev, mddev); | 1923 | rdev_dec_pending(conf->mirrors[i].rdev, mddev); |