Messages in this thread Patch in this message |  | | | From | NeilBrown <> | | Date | Tue, 31 Jul 2007 12:18:21 +1000 | | Subject | [PATCH 029 of 35] Teach md/raid10 to split arbitrarily large bios. |
| |
.. using the new bio_multi_split.
Signed-off-by: Neil Brown <neilb@suse.de>
### Diffstat output ./drivers/md/raid10.c | 70 ++++++++++---------------------------------------- 1 file changed, 14 insertions(+), 56 deletions(-) diff .prev/drivers/md/raid10.c ./drivers/md/raid10.c --- .prev/drivers/md/raid10.c 2007-07-31 11:21:22.000000000 +1000 +++ ./drivers/md/raid10.c 2007-07-31 11:21:24.000000000 +1000 @@ -436,33 +436,6 @@ static sector_t raid10_find_virt(conf_t return (vchunk << conf->chunk_shift) + offset; } -/** - * raid10_mergeable_bvec -- tell bio layer if a two requests can be merged - * @q: request queue - * @bio: the buffer head that's been built up so far - * @biovec: the request that could be merged to it. - * - * Return amount of bytes we can accept at this offset - * If near_copies == raid_disk, there are no striping issues, - * but in that case, the function isn't called at all. - */ -static int raid10_mergeable_bvec(struct request_queue *q, struct bio *bio, - struct bio_vec *bio_vec) -{ - mddev_t *mddev = q->queuedata; - sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); - int max; - unsigned int chunk_sectors = mddev->chunk_size >> 9; - unsigned int bio_sectors = bio->bi_size >> 9; - - max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; - if (max < 0) max = 0; /* bio_add cannot handle a negative return */ - if (max <= bio_vec->bv_len && bio_sectors == 0) - return bio_vec->bv_len; - else - return max; -} - /* * This routine returns the disk from which the requested read should * be done. There is a per-array 'next expected sequential IO' sector @@ -772,6 +745,7 @@ static int make_request(struct request_q mirror_info_t *mirror; r10bio_t *r10_bio; struct bio *read_bio; + struct bio *remainder = bio; int i; int chunk_sects = conf->chunk_mask + 1; const int rw = bio_data_dir(bio); @@ -785,35 +759,21 @@ static int make_request(struct request_q } /* If this request crosses a chunk boundary, we need to - * split it. This will only happen for 1 PAGE (or less) requests. + * split it. */ - if (unlikely( (bio->bi_sector & conf->chunk_mask) + (bio->bi_size >> 9) - > chunk_sects && - conf->near_copies < conf->raid_disks)) { - struct bio_pair *bp; - /* Sanity check -- queue functions should prevent this happening */ - if (bio->bi_vcnt != 1) - goto bad_map; - /* This is a one page bio that upper layers - * refuse to split for us, so we need to split it. - */ - bp = bio_split(bio, bio_split_pool, - chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); - if (make_request(q, &bp->bio1)) - generic_make_request(&bp->bio1); - if (make_request(q, &bp->bio2)) - generic_make_request(&bp->bio2); - - bio_pair_release(bp); - return 0; - bad_map: - printk("raid10_make_request bug: can't convert block across chunks" - " or bigger than %dk %llu %d\n", chunk_sects/2, - (unsigned long long)bio->bi_sector, bio->bi_size >> 10); - - bio_io_error(bio); - return 0; + while ((remainder->bi_sector & conf->chunk_mask) + + (remainder->bi_size >> 9) + > chunk_sects && + conf->near_copies < conf->raid_disks) { + struct bio *new = + bio_multi_split(bio, + chunk_sects + - (remainder->bi_sector + & (chunk_sects - 1)), + &remainder); + make_request(q, new); } + bio = remainder; md_write_start(mddev, bio); @@ -2116,8 +2076,6 @@ static int run(mddev_t *mddev) mddev->queue->backing_dev_info.ra_pages = 2* stripe; } - if (conf->near_copies < mddev->raid_disks) - blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); return 0; out_free_conf: - 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/
|  |