Messages in this thread Patch in this message | | | From | NeilBrown <> | Date | Tue, 31 Jul 2007 12:18:52 +1000 | Subject | [PATCH 035 of 35] Simplify bio splitting in dm. |
| |
Use the new bio_multi_split to simplify dm bio splitting.
Signed-off-by: Neil Brown <neilb@suse.de>
### Diffstat output ./drivers/md/dm.c | 166 ++++++------------------------------------------------ 1 file changed, 20 insertions(+), 146 deletions(-)
diff .prev/drivers/md/dm.c ./drivers/md/dm.c --- .prev/drivers/md/dm.c 2007-07-31 11:21:22.000000000 +1000 +++ ./drivers/md/dm.c 2007-07-31 11:21:30.000000000 +1000 @@ -526,11 +526,6 @@ static void clone_endio(struct bio *bio, dec_pending(tio->io, error); - /* - * Store md for cleanup instead of tio which is about to get freed. - */ - bio->bi_private = md->bs; - bio_put(bio); free_tio(md, tio); } @@ -590,10 +585,6 @@ static void __map_bio(struct dm_target * /* error the io and bail out, or requeue it if needed */ md = tio->io->md; dec_pending(tio->io, r); - /* - * Store bio_set for cleanup. - */ - clone->bi_private = md->bs; bio_put(clone); free_tio(md, tio); } else if (r) { @@ -607,149 +598,35 @@ struct clone_info { struct dm_table *map; struct bio *bio; struct dm_io *io; - sector_t sector; - sector_t sector_count; - unsigned short idx; }; -static void dm_bio_destructor(struct bio *bio) -{ - struct bio_set *bs = bio->bi_private; - - bio_free(bio, bs); -} - -/* - * Creates a little bio that is just does part of a bvec. - */ -static struct bio *split_bvec(struct bio *bio, sector_t sector, - unsigned short idx, unsigned int offset, - unsigned int len, struct bio_set *bs) -{ - struct bio *clone; - struct bio_vec *bv = bio->bi_io_vec + idx; - - clone = bio_alloc_bioset(GFP_NOIO, 1, bs); - clone->bi_destructor = dm_bio_destructor; - *clone->bi_io_vec = *bv; - - clone->bi_sector = sector; - clone->bi_bdev = bio->bi_bdev; - clone->bi_rw = bio->bi_rw; - clone->bi_vcnt = 1; - clone->bi_size = to_bytes(len); - clone->bi_io_vec->bv_offset = offset; - clone->bi_io_vec->bv_len = clone->bi_size; - - return clone; -} - -/* - * Creates a bio that consists of range of complete bvecs. - */ -static struct bio *clone_bio(struct bio *bio, sector_t sector, - unsigned short idx, unsigned short bv_count, - unsigned int len, struct bio_set *bs) -{ - struct bio *clone; - - clone = bio_alloc_bioset(GFP_NOIO, bio->bi_max_vecs, bs); - __bio_clone(clone, bio); - clone->bi_destructor = dm_bio_destructor; - clone->bi_sector = sector; - clone->bi_io_vec += idx; - clone->bi_vcnt = bv_count; - clone->bi_size = to_bytes(len); - - return clone; -} - static void __clone_and_map(struct clone_info *ci) { - struct bio *clone, *bio = ci->bio; - struct dm_target *ti = dm_table_find_target(ci->map, ci->sector); - sector_t len = 0, max = max_io_len(ci->md, ci->sector, ti); - struct dm_target_io *tio; + struct bio *bio = ci->bio; + struct bio *remainder = bio; - /* - * Allocate a target io object. - */ - tio = alloc_tio(ci->md); - tio->io = ci->io; - tio->ti = ti; - memset(&tio->info, 0, sizeof(tio->info)); + while (remainder) { + struct bio *clone; + struct dm_target *ti = + dm_table_find_target(ci->map, + remainder->bi_sector); + sector_t len = 0; + sector_t max = max_io_len(ci->md, remainder->bi_sector, ti); + struct dm_target_io *tio; - if (ci->sector_count <= max) { /* - * Optimise for the simple case where we can do all of - * the remaining io with a single clone. + * Allocate a target io object. */ - clone = clone_bio(bio, ci->sector, ci->idx, - bio->bi_vcnt - ci->idx, ci->sector_count, - ci->md->bs); - __map_bio(ti, clone, tio); - ci->sector_count = 0; - - } else if (to_sector(bio->bi_io_vec[ci->idx].bv_len) <= max) { - /* - * There are some bvecs that don't span targets. - * Do as many of these as possible. - */ - int i; - sector_t remaining = max; - sector_t bv_len; - - for (i = ci->idx; remaining && (i < bio->bi_vcnt); i++) { - bv_len = to_sector(bio->bi_io_vec[i].bv_len); + tio = alloc_tio(ci->md); + tio->io = ci->io; + tio->ti = ti; + memset(&tio->info, 0, sizeof(tio->info)); - if (bv_len > remaining) - break; + len = min_t(unsigned int, remainder->bi_size>>9, max); - remaining -= bv_len; - len += bv_len; - } - - clone = clone_bio(bio, ci->sector, ci->idx, i - ci->idx, len, - ci->md->bs); + clone = bio_multi_split(bio, len, &remainder); __map_bio(ti, clone, tio); - - ci->sector += len; - ci->sector_count -= len; - ci->idx = i; - - } else { - /* - * Handle a bvec that must be split between two or more targets. - */ - struct bio_vec *bv = bio->bi_io_vec + ci->idx; - sector_t remaining = to_sector(bv->bv_len); - unsigned int offset = 0; - - do { - if (offset) { - ti = dm_table_find_target(ci->map, ci->sector); - max = max_io_len(ci->md, ci->sector, ti); - - tio = alloc_tio(ci->md); - tio->io = ci->io; - tio->ti = ti; - memset(&tio->info, 0, sizeof(tio->info)); - } - - len = min(remaining, max); - - clone = split_bvec(bio, ci->sector, ci->idx, - bv->bv_offset + offset, len, - ci->md->bs); - - __map_bio(ti, clone, tio); - - ci->sector += len; - ci->sector_count -= len; - offset += to_bytes(len); - } while (remaining -= len); - - ci->idx++; + atomic_dec(&bio->bi_iocnt); } } @@ -773,13 +650,10 @@ static void __split_bio(struct mapped_de atomic_set(&ci.io->io_count, 1); ci.io->bio = bio; ci.io->md = md; - ci.sector = bio->bi_sector; - ci.sector_count = bio_sectors(bio); - ci.idx = 0; start_io_acct(ci.io); - while (ci.sector_count) - __clone_and_map(&ci); + + __clone_and_map(&ci); /* drop the extra reference count */ dec_pending(ci.io, 0); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |