From f00b16ad665a9b489d46f612679181f3f914917b Mon Sep 17 00:00:00 2001 From: Heinz Mauelshagen Date: Fri, 8 Dec 2006 02:41:01 -0800 Subject: [PATCH] [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 Signed-off-by: Alasdair G Kergon Cc: Milan Broz Cc: dm-devel@redhat.com Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-io.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index da663d2ff552..4eb73d395213 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages) *---------------------------------------------------------------*/ static inline void bio_set_region(struct bio *bio, unsigned region) { - bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len = region; + bio->bi_io_vec[bio->bi_max_vecs].bv_len = region; } static inline unsigned bio_get_region(struct bio *bio) { - return bio->bi_io_vec[bio->bi_max_vecs - 1].bv_len; + return bio->bi_io_vec[bio->bi_max_vecs].bv_len; } /*----------------------------------------------------------------- @@ -136,6 +136,7 @@ static int endio(struct bio *bio, unsigned int done, int error) zero_fill_bio(bio); dec_count(io, bio_get_region(bio), error); + bio->bi_max_vecs++; bio_put(bio); return 0; @@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where, while (remaining) { /* - * Allocate a suitably sized bio, we add an extra - * bvec for bio_get/set_region(). + * Allocate a suitably sized-bio: we add an extra + * bvec for bio_get/set_region() and decrement bi_max_vecs + * to hide it from bio_add_page(). */ - num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2; + num_bvecs = (remaining / (PAGE_SIZE >> SECTOR_SHIFT)) + 2; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; bio->bi_private = io; bio->bi_destructor = dm_bio_destructor; + bio->bi_max_vecs--; bio_set_region(bio, region); /* @@ -302,7 +305,7 @@ static void dispatch_io(int rw, unsigned int num_regions, } /* - * Drop the extra refence that we were holding to avoid + * Drop the extra reference that we were holding to avoid * the io being completed too early. */ dec_count(io, 0, 0);