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

[PATCH] dm io: fix bi_max_vecs

The existing code allocates an extra slot in bi_io_vec[] and uses it to store
the region number.

This patch hides the extra slot from bio_add_page() so the region number can't
get overwritten.

Also remove a hard-coded SECTOR_SHIFT and fix a typo in a comment.

Signed-off-by: Heinz Mauelshagen <hjm@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Cc: Milan Broz <mbroz@redhat.com>
Cc: dm-devel@redhat.com
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Heinz Mauelshagen and committed by
Linus Torvalds
f00b16ad 5cd307c5

+9 -6
+9 -6
drivers/md/dm-io.c
··· 92 92 *---------------------------------------------------------------*/ 93 93 static inline void bio_set_region(struct bio *bio, unsigned region) 94 94 { 95 - bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region; 95 + bio->bi_io_vec[bio->bi_max_vecs].bv_len = region; 96 96 } 97 97 98 98 static inline unsigned bio_get_region(struct bio *bio) 99 99 { 100 - return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len; 100 + return bio->bi_io_vec[bio->bi_max_vecs].bv_len; 101 101 } 102 102 103 103 /*----------------------------------------------------------------- ··· 136 136 zero_fill_bio(bio); 137 137 138 138 dec_count(io, bio_get_region(bio), error); 139 + bio->bi_max_vecs++; 139 140 bio_put(bio); 140 141 141 142 return 0; ··· 251 250 252 251 while (remaining) { 253 252 /* 254 - * Allocate a suitably sized bio, we add an extra 255 - * bvec for bio_get/set_region(). 253 + * Allocate a suitably sized-bio: we add an extra 254 + * bvec for bio_get/set_region() and decrement bi_max_vecs 255 + * to hide it from bio_add_page(). 256 256 */ 257 - num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2; 257 + num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; 258 258 bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios); 259 259 bio->bi_sector = where->sector + (where->count - remaining); 260 260 bio->bi_bdev = where->bdev; 261 261 bio->bi_end_io = endio; 262 262 bio->bi_private = io; 263 263 bio->bi_destructor = dm_bio_destructor; 264 + bio->bi_max_vecs--; 264 265 bio_set_region(bio, region); 265 266 266 267 /* ··· 305 302 } 306 303 307 304 /* 308 - * Drop the extra refence that we were holding to avoid 305 + * Drop the extra reference that we were holding to avoid 309 306 * the io being completed too early. 310 307 */ 311 308 dec_count(io, 0, 0);