Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dm: preserve bi_io_vec when resubmitting bios

Device mapper saves and restores various fields in the bio, but it doesn't save
bi_io_vec. If the device driver modifies this after a partially successful
request, dm-raid1 and dm-multipath may attempt to resubmit a bio that has
bi_size inconsistent with the size of vector.

To make requests resubmittable in dm-raid1 and dm-multipath, we must save
and restore the bio vector as well.

To reduce the memory overhead involved in this, we do not save the pages in a
vector and use a 16-bit field size if the page size is less than 65536.

Cc: stable@kernel.org
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

authored by

Mikulas Patocka and committed by
Alasdair G Kergon
a920f6b3 833bb304

+26
+26
drivers/md/dm-bio-record.h
··· 16 16 * functions in this file help the target record and restore the 17 17 * original bio state. 18 18 */ 19 + 20 + struct dm_bio_vec_details { 21 + #if PAGE_SIZE < 65536 22 + __u16 bv_len; 23 + __u16 bv_offset; 24 + #else 25 + unsigned bv_len; 26 + unsigned bv_offset; 27 + #endif 28 + }; 29 + 19 30 struct dm_bio_details { 20 31 sector_t bi_sector; 21 32 struct block_device *bi_bdev; 22 33 unsigned int bi_size; 23 34 unsigned short bi_idx; 24 35 unsigned long bi_flags; 36 + struct dm_bio_vec_details bi_io_vec[BIO_MAX_PAGES]; 25 37 }; 26 38 27 39 static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio) 28 40 { 41 + unsigned i; 42 + 29 43 bd->bi_sector = bio->bi_sector; 30 44 bd->bi_bdev = bio->bi_bdev; 31 45 bd->bi_size = bio->bi_size; 32 46 bd->bi_idx = bio->bi_idx; 33 47 bd->bi_flags = bio->bi_flags; 48 + 49 + for (i = 0; i < bio->bi_vcnt; i++) { 50 + bd->bi_io_vec[i].bv_len = bio->bi_io_vec[i].bv_len; 51 + bd->bi_io_vec[i].bv_offset = bio->bi_io_vec[i].bv_offset; 52 + } 34 53 } 35 54 36 55 static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio) 37 56 { 57 + unsigned i; 58 + 38 59 bio->bi_sector = bd->bi_sector; 39 60 bio->bi_bdev = bd->bi_bdev; 40 61 bio->bi_size = bd->bi_size; 41 62 bio->bi_idx = bd->bi_idx; 42 63 bio->bi_flags = bd->bi_flags; 64 + 65 + for (i = 0; i < bio->bi_vcnt; i++) { 66 + bio->bi_io_vec[i].bv_len = bd->bi_io_vec[i].bv_len; 67 + bio->bi_io_vec[i].bv_offset = bd->bi_io_vec[i].bv_offset; 68 + } 43 69 } 44 70 45 71 #endif