aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2013-07-17 01:19:29 -0400
committerNeilBrown <neilb@suse.de>2013-07-18 00:18:04 -0400
commit30bc9b53878a9921b02e3b5bc4283ac1c6de102a (patch)
tree715adc122718ac9ea2c49b9953dee29d458d327a
parent5024c298311f3b97c85cb034f9edaa333fdb9338 (diff)
md/raid1: fix bio handling problems in process_checks()
Recent change to use bio_copy_data() in raid1 when repairing an array is faulty. The underlying may have changed the bio in various ways using bio_advance and these need to be undone not just for the 'sbio' which is being copied to, but also the 'pbio' (primary) which is being copied from. So perform the reset on all bios that were read from and do it early. This also ensure that the sbio->bi_io_vec[j].bv_len passed to memcmp is correct. This fixes a crash during a 'check' of a RAID1 array. The crash was introduced in 3.10 so this is suitable for 3.10-stable. Cc: stable@vger.kernel.org (3.10) Reported-by: Joe Lawrence <joe.lawrence@stratus.com> Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/raid1.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index ec734588a1c6..d60412c7f995 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1849,6 +1849,36 @@ static int process_checks(struct r1bio *r1_bio)
1849 int i; 1849 int i;
1850 int vcnt; 1850 int vcnt;
1851 1851
1852 /* Fix variable parts of all bios */
1853 vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
1854 for (i = 0; i < conf->raid_disks * 2; i++) {
1855 int j;
1856 int size;
1857 struct bio *b = r1_bio->bios[i];
1858 if (b->bi_end_io != end_sync_read)
1859 continue;
1860 /* fixup the bio for reuse */
1861 bio_reset(b);
1862 b->bi_vcnt = vcnt;
1863 b->bi_size = r1_bio->sectors << 9;
1864 b->bi_sector = r1_bio->sector +
1865 conf->mirrors[i].rdev->data_offset;
1866 b->bi_bdev = conf->mirrors[i].rdev->bdev;
1867 b->bi_end_io = end_sync_read;
1868 b->bi_private = r1_bio;
1869
1870 size = b->bi_size;
1871 for (j = 0; j < vcnt ; j++) {
1872 struct bio_vec *bi;
1873 bi = &b->bi_io_vec[j];
1874 bi->bv_offset = 0;
1875 if (size > PAGE_SIZE)
1876 bi->bv_len = PAGE_SIZE;
1877 else
1878 bi->bv_len = size;
1879 size -= PAGE_SIZE;
1880 }
1881 }
1852 for (primary = 0; primary < conf->raid_disks * 2; primary++) 1882 for (primary = 0; primary < conf->raid_disks * 2; primary++)
1853 if (r1_bio->bios[primary]->bi_end_io == end_sync_read && 1883 if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
1854 test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) { 1884 test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
@@ -1857,12 +1887,10 @@ static int process_checks(struct r1bio *r1_bio)
1857 break; 1887 break;
1858 } 1888 }
1859 r1_bio->read_disk = primary; 1889 r1_bio->read_disk = primary;
1860 vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
1861 for (i = 0; i < conf->raid_disks * 2; i++) { 1890 for (i = 0; i < conf->raid_disks * 2; i++) {
1862 int j; 1891 int j;
1863 struct bio *pbio = r1_bio->bios[primary]; 1892 struct bio *pbio = r1_bio->bios[primary];
1864 struct bio *sbio = r1_bio->bios[i]; 1893 struct bio *sbio = r1_bio->bios[i];
1865 int size;
1866 1894
1867 if (sbio->bi_end_io != end_sync_read) 1895 if (sbio->bi_end_io != end_sync_read)
1868 continue; 1896 continue;
@@ -1888,27 +1916,6 @@ static int process_checks(struct r1bio *r1_bio)
1888 rdev_dec_pending(conf->mirrors[i].rdev, mddev); 1916 rdev_dec_pending(conf->mirrors[i].rdev, mddev);
1889 continue; 1917 continue;
1890 } 1918 }
1891 /* fixup the bio for reuse */
1892 bio_reset(sbio);
1893 sbio->bi_vcnt = vcnt;
1894 sbio->bi_size = r1_bio->sectors << 9;
1895 sbio->bi_sector = r1_bio->sector +
1896 conf->mirrors[i].rdev->data_offset;
1897 sbio->bi_bdev = conf->mirrors[i].rdev->bdev;
1898 sbio->bi_end_io = end_sync_read;
1899 sbio->bi_private = r1_bio;
1900
1901 size = sbio->bi_size;
1902 for (j = 0; j < vcnt ; j++) {
1903 struct bio_vec *bi;
1904 bi = &sbio->bi_io_vec[j];
1905 bi->bv_offset = 0;
1906 if (size > PAGE_SIZE)
1907 bi->bv_len = PAGE_SIZE;
1908 else
1909 bi->bv_len = size;
1910 size -= PAGE_SIZE;
1911 }
1912 1919
1913 bio_copy_data(sbio, pbio); 1920 bio_copy_data(sbio, pbio);
1914 } 1921 }