Commit f00b16ad authored by Heinz Mauelshagen's avatar Heinz Mauelshagen Committed by Linus Torvalds

[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: default avatarHeinz Mauelshagen <hjm@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
Cc: Milan Broz <mbroz@redhat.com>
Cc: dm-devel@redhat.com
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 5cd307c5
...@@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages) ...@@ -92,12 +92,12 @@ void dm_io_put(unsigned int num_pages)
*---------------------------------------------------------------*/ *---------------------------------------------------------------*/
static inline void bio_set_region(struct bio *bio, unsigned region) 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) 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) ...@@ -136,6 +136,7 @@ static int endio(struct bio *bio, unsigned int done, int error)
zero_fill_bio(bio); zero_fill_bio(bio);
dec_count(io, bio_get_region(bio), error); dec_count(io, bio_get_region(bio), error);
bio->bi_max_vecs++;
bio_put(bio); bio_put(bio);
return 0; return 0;
...@@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where, ...@@ -250,16 +251,18 @@ static void do_region(int rw, unsigned int region, struct io_region *where,
while (remaining) { while (remaining) {
/* /*
* Allocate a suitably sized bio, we add an extra * Allocate a suitably sized-bio: we add an extra
* bvec for bio_get/set_region(). * 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 = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios);
bio->bi_sector = where->sector + (where->count - remaining); bio->bi_sector = where->sector + (where->count - remaining);
bio->bi_bdev = where->bdev; bio->bi_bdev = where->bdev;
bio->bi_end_io = endio; bio->bi_end_io = endio;
bio->bi_private = io; bio->bi_private = io;
bio->bi_destructor = dm_bio_destructor; bio->bi_destructor = dm_bio_destructor;
bio->bi_max_vecs--;
bio_set_region(bio, region); bio_set_region(bio, region);
/* /*
...@@ -302,7 +305,7 @@ static void dispatch_io(int rw, unsigned int num_regions, ...@@ -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. * the io being completed too early.
*/ */
dec_count(io, 0, 0); dec_count(io, 0, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment