Skip to content

Commit 30bc9b5

Browse files
committed
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: [email protected] (3.10) Reported-by: Joe Lawrence <[email protected]> Signed-off-by: NeilBrown <[email protected]>
1 parent 5024c29 commit 30bc9b5

File tree

1 file changed

+30
-23
lines changed

1 file changed

+30
-23
lines changed

drivers/md/raid1.c

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,6 +1849,36 @@ static int process_checks(struct r1bio *r1_bio)
18491849
int i;
18501850
int vcnt;
18511851

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+
}
18521882
for (primary = 0; primary < conf->raid_disks * 2; primary++)
18531883
if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
18541884
test_bit(BIO_UPTODATE, &r1_bio->bios[primary]->bi_flags)) {
@@ -1857,12 +1887,10 @@ static int process_checks(struct r1bio *r1_bio)
18571887
break;
18581888
}
18591889
r1_bio->read_disk = primary;
1860-
vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
18611890
for (i = 0; i < conf->raid_disks * 2; i++) {
18621891
int j;
18631892
struct bio *pbio = r1_bio->bios[primary];
18641893
struct bio *sbio = r1_bio->bios[i];
1865-
int size;
18661894

18671895
if (sbio->bi_end_io != end_sync_read)
18681896
continue;
@@ -1888,27 +1916,6 @@ static int process_checks(struct r1bio *r1_bio)
18881916
rdev_dec_pending(conf->mirrors[i].rdev, mddev);
18891917
continue;
18901918
}
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-
}
19121919

19131920
bio_copy_data(sbio, pbio);
19141921
}

0 commit comments

Comments
 (0)