simplify block layer based on immutable biovecs
Subsystems (18)
v2 cover simplify block layer based on immutable biovecs
This is the second attempt of simplifying block layer based on immutable biovecs. Immutable biovecs, implemented by Kent Overstreet, have been available in mainline since v3.14. Its original goal was actually making generic_make_request() accept arbitrarily sized bios, and pushing the splitting down to the drivers or wherever it's required. See also discussions in the past, [1] [2] [3] [4].
This will bring not only performance improvements, but also a great amount of reduction in code complexity all over the block layer. Performance gain is possible due to the fact that bio_add_page() does not have to check unnecesary conditions such as queue limits or if biovecs are mergeable. Those will be delegated to the driver level. Kent already said that he actually benchmarked the impact of this with fio on a micron p320h, which showed definitely a positive impact.
Moreover, this patchset also allows a lot of code to be deleted, mainly because of removal of merge_bvec_fn() callbacks. We have been aware that it has been always a delicate issue for stacking block drivers (e.g. md and bcache) to handle merging bio consistently. This simplication will help every individual block driver avoid having such an issue.
- Patch 01/09 allows generic_make_request handle arbitrarily sized bios, by making make_request functions call blk_queue_split().
- Patch 02/09 simplifies __bio_add_page() to avoid calling ->merge_bvec_fn().
- Patch 03/09 allows queue_bounce to handle bios with > BIO_MAX_PAGES
- Patch 04/09 gets rid of workarounds in bcache.
- Patch 05/09 removes unnecessary biovec merging parts in btrfs
- Patch 06/09 removes unnecessary biovec merging parts in MD-RAID5.
- Patch 07/09 removes ->merge_bvec_fn() completely, which affects a lot of block drivers, such as Ceph RBD, DRBD, device mapper, MD, etc.
- Patch 08/09 makes filesystems use helper bio_add_page().
- Patch 09/09 updates document about biovecs.
Patches are against 3.19-rc4. These are also available in my git repo at:
https://github.com/dongsupark/linux.git block-generic-req
It's recommended to apply this patchset on top of its preparation patchset i.e. "preparation for block layer simplification". [5]
This patchset is in turn also a prerequisite of other consecutive patchsets, e.g. multipage biovecs, rewriting plugging, or rewriting direct-IO, which is yet to-be-done. This patchset should not bring any regression to end-users. I already tested it with xfstests multiple times. On the other hand, the multipage biovecs part is currently in heavy development, with help of Kent and Ming Lin. Those experimental patches are also available on other branches on my git tree. Once they are done, I'm also going to post them to get reviews.
Comments are welcome.
Dongsu
Changes in v2:
- split up preparation patches into a separate series
- remove a patch "block: simplify issueing discard, write_same, zeroout", as suggested by Christoph Hellwig.
- move a patch "btrfs: make use of immutable biovecs" to the upcoming series.
- minor change in ps3vram suggested by Geoff Levand
- make bio_add_page() warn once on a cloned bio.
- add more comments and commit messages to patch 02 "block: simplify bio_add_page()"
[1] https://lkml.org/lkml/2014/11/23/263
[2] https://lkml.org/lkml/2013/11/25/732
[3] https://lkml.org/lkml/2014/2/26/618
[4] https://lkml.org/lkml/2014/12/22/128
[5] https://lkml.org/lkml/2015/1/12/255
Dongsu Park (1):
Documentation: update notes in biovecs about arbitrarily sized bios
Kent Overstreet (8):
block: make generic_make_request handle arbitrarily sized bios
block: simplify bio_add_page()
block: allow __blk_queue_bounce() to handle bios larger than
BIO_MAX_PAGES
bcache: clean up hacks around bio_split_pool
btrfs: remove bio splitting and merge_bvec_fn() calls md/raid5: get rid of bio_fits_rdev()
block: kill merge_bvec_fn() completely
fs: use helper bio_add_page() instead of open coding on bi_io_vec
Documentation/block/biovecs.txt | 10 +- block/bio.c | 135 +++++++++++---------------- block/blk-core.c | 19 ++-- block/blk-merge.c | 140 ++++++++++++++++++++++++++-- block/blk-mq.c | 2 + block/blk-settings.c | 22 ----- block/bounce.c | 60 ++++++++++-- drivers/block/drbd/drbd_int.h | 1 - drivers/block/drbd/drbd_main.c | 1 - drivers/block/drbd/drbd_req.c | 37 +------- drivers/block/pktcdvd.c | 27 +----- drivers/block/ps3vram.c | 2 + drivers/block/rbd.c | 47 ---------- drivers/block/rsxx/dev.c | 2 + drivers/block/umem.c | 2 + drivers/block/zram/zram_drv.c | 2 + drivers/md/bcache/bcache.h | 18 ---- drivers/md/bcache/io.c | 100 +------------------- drivers/md/bcache/journal.c | 4 +- drivers/md/bcache/request.c | 16 ++-- drivers/md/bcache/super.c | 32 +------ drivers/md/bcache/util.h | 5 +- drivers/md/bcache/writeback.c | 4 +- drivers/md/dm-cache-target.c | 21 ----- drivers/md/dm-crypt.c | 16 ---- drivers/md/dm-era-target.c | 15 --- drivers/md/dm-flakey.c | 16 ---- drivers/md/dm-linear.c | 16 ---- drivers/md/dm-snap.c | 15 --- drivers/md/dm-stripe.c | 21 ----- drivers/md/dm-table.c | 8 -- drivers/md/dm-thin.c | 31 ------ drivers/md/dm-verity.c | 16 ---- drivers/md/dm.c | 122 +----------------------- drivers/md/dm.h | 2 - drivers/md/linear.c | 46 --------- drivers/md/md.c | 4 +- drivers/md/md.h | 8 -- drivers/md/multipath.c | 21 ----- drivers/md/raid0.c | 57 ----------- drivers/md/raid0.h | 2 - drivers/md/raid1.c | 59 +----------- drivers/md/raid10.c | 122 +----------------------- drivers/md/raid5.c | 51 +--------- drivers/s390/block/dcssblk.c | 2 + drivers/s390/block/xpram.c | 2 + drivers/staging/lustre/lustre/llite/lloop.c | 2 + fs/btrfs/volumes.c | 73 --------------- fs/buffer.c | 7 +- fs/jfs/jfs_logmgr.c | 14 +-- include/linux/blkdev.h | 13 +-- include/linux/device-mapper.h | 4 - mm/page_io.c | 8 +- 53 files changed, 318 insertions(+), 1164 deletions(-)
Signature · 1 line
2.1.0
PATCH v2 1/9 block: make generic_make_request handle arbitrarily sized bios
From: Kent Overstreet <[email protected]>
The way the block layer is currently written, it goes to great lengths to avoid having to split bios; upper layer code (such as bio_add_page()) checks what the underlying device can handle and tries to always create bios that don't need to be split.
But this approach becomes unwieldy and eventually breaks down with stacked devices and devices with dynamic limits, and it adds a lot of complexity. If the block layer could split bios as needed, we could eliminate a lot of complexity elsewhere - particularly in stacked drivers. Code that creates bios can then create whatever size bios are convenient, and more importantly stacked drivers don't have to deal with both their own bio size limitations and the limitations of the (potentially multiple) devices underneath them. In the future this will let us delete merge_bvec_fn and a bunch of other code.
We do this by adding calls to blk_queue_split() to the various make_request functions that need it - a few can already handle arbitrary size bios. Note that we add the call _after_ any call to blk_queue_bounce(); this means that blk_queue_split() and blk_recalc_rq_segments() don't need to be concerned with bouncing affecting segment merging.
Some make_request_fn() callbacks were simple enough to audit and verify they don't need blk_queue_split() calls. The skipped ones are:
* nfhd_make_request (arch/m68k/emu/nfblock.c)
* axon_ram_make_request (arch/powerpc/sysdev/axonram.c)
* simdisk_make_request (arch/xtensa/platforms/iss/simdisk.c)
* brd_make_request (ramdisk - drivers/block/brd.c)
* mtip_submit_request (drivers/block/mtip32xx/mtip32xx.c)
* loop_make_request
* null_queue_bio
* bcache's make_request fns
Some others are almost certainly safe to remove now, but will be left for future patches.
--- block/blk-core.c | 19 ++-- block/blk-merge.c | 151 ++++++++++++++++++++++++++-- block/blk-mq.c | 2 + drivers/block/drbd/drbd_req.c | 2 + drivers/block/pktcdvd.c | 6 +- drivers/block/ps3vram.c | 2 + drivers/block/rsxx/dev.c | 2 + drivers/block/umem.c | 2 + drivers/block/zram/zram_drv.c | 2 + drivers/md/dm.c | 2 + drivers/md/md.c | 2 + drivers/s390/block/dcssblk.c | 2 + drivers/s390/block/xpram.c | 2 + drivers/staging/lustre/lustre/llite/lloop.c | 2 + include/linux/blkdev.h | 3 + 15 files changed, 179 insertions(+), 22 deletions(-)
block/blk-core.c +9 -10
@@ -585,6 +585,10 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)if (q->id <0 ) goto fail_q; + q->bio_split =bioset_create (4 ,0 ); +if (!q->bio_split) + goto fail_id; + q->backing_dev_info.ra_pages = (VM_MAX_READAHEAD *1024 ) /PAGE_CACHE_SIZE ; q->backing_dev_info.state =0 ;
@@ -594,7 +598,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) err =bdi_init (&q->backing_dev_info);if (err) - goto fail_id; + goto fail_split;setup_timer (&q->backing_dev_info.laptop_mode_wb_timer, laptop_mode_timer_fn, (unsigned long ) q);
@@ -636,6 +640,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) fail_bdi:bdi_destroy (&q->backing_dev_info); +fail_split: +bioset_free (q->bio_split); fail_id:ida_simple_remove (&blk_queue_ida, q->id); fail_q:
@@ -1552,6 +1558,8 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio)struct request *req;unsigned int request_count =0 ; +blk_queue_split (q, &bio, q->bio_split); +/* * low level driver can indicate that it wants pages above a * certain limit bounced to low memory (ie for highmem, or even
@@ -1775,15 +1783,6 @@ generic_make_request_checks(struct bio *bio) goto end_io; } -if (likely (bio_is_rw (bio) && - nr_sectors >queue_max_hw_sectors (q))) { -printk (KERN_ERR "bio too big device %s (%u > %u)\n" , -bdevname (bio->bi_bdev, b), -bio_sectors (bio), -queue_max_hw_sectors (q)); - goto end_io; - } - part = bio->bi_bdev->bd_part;if (should_fail_request (part, bio->bi_iter.bi_size) || should_fail_request(&part_to_disk(part)->part0,
block/blk-merge.c +141 -10
181 lines not on this page · raw message
block/blk-mq.c +2 -0
@@ -1259,6 +1259,8 @@ static void blk_sq_make_request(struct request_queue *q, struct bio *bio)return ; } +blk_queue_split (q, &bio, q->bio_split); +if (use_plug && !blk_queue_nomerges (q) &&blk_attempt_plug_merge (q, bio, &request_count))return ;
drivers/block/drbd/drbd_req.c +2 -0
@@ -1496,6 +1496,8 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)struct drbd_device *device = (struct drbd_device *) q->queuedata;unsigned long start_jif; +blk_queue_split (q, &bio, q->bio_split); + start_jif = jiffies;/*
drivers/block/pktcdvd.c +4 -2
@@ -2446,6 +2446,10 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)char b[BDEVNAME_SIZE ];struct bio *split; +blk_queue_bounce (q, &bio); + +blk_queue_split (q, &bio, q->bio_split); + pd = q->queuedata;if (!pd) { pr_err("%s incorrect request queue\n",
@@ -2476,8 +2480,6 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio) goto end_io; } -blk_queue_bounce (q, &bio); - do { sector_t zone = get_zone(bio->bi_iter.bi_sector, pd); sector_t last_zone = get_zone(bio_end_sector(bio) - 1, pd);
drivers/block/ps3vram.c +2 -0
@@ -605,6 +605,8 @@ static void ps3vram_make_request(struct request_queue *q, struct bio *bio)dev_dbg (&dev->core,"%s\n" , __func__); +blk_queue_split (q, &bio, q->bio_split); +spin_lock_irq (&priv->lock); busy = !bio_list_empty (&priv->list);bio_list_add (&priv->list, bio);
drivers/block/rsxx/dev.c +2 -0
@@ -148,6 +148,8 @@ static void rsxx_make_request(struct request_queue *q, struct bio *bio)struct rsxx_bio_meta *bio_meta;int st = -EINVAL ; +blk_queue_split (q, &bio, q->bio_split); +might_sleep ();if (!card)
drivers/block/umem.c +2 -0
@@ -531,6 +531,8 @@ static void mm_make_request(struct request_queue *q, struct bio *bio) (unsigned long long )bio->bi_iter.bi_sector, bio->bi_iter.bi_size); +blk_queue_split (q, &bio, q->bio_split); +spin_lock_irq (&card->lock); *card->biotail = bio; bio->bi_next =NULL ;
drivers/block/zram/zram_drv.c +2 -0
@@ -909,6 +909,8 @@ static void zram_make_request(struct request_queue *queue, struct bio *bio) {struct zram *zram = queue->queuedata; +blk_queue_split (queue, &bio, queue->bio_split); +down_read (&zram->init_lock);if (unlikely (!init_done (zram))) goto error;
drivers/md/dm.c +2 -0
@@ -1680,6 +1680,8 @@ static void dm_request(struct request_queue *q, struct bio *bio) {struct mapped_device *md = q->queuedata; +blk_queue_split (q, &bio, q->bio_split); +if (dm_request_based (md))blk_queue_bio (q, bio);else
drivers/md/md.c +2 -0
@@ -249,6 +249,8 @@ static void md_make_request(struct request_queue *q, struct bio *bio)struct mddev *mddev = q->queuedata;unsigned int sectors; +blk_queue_split (q, &bio, q->bio_split); +if (mddev ==NULL || mddev->pers ==NULL || !mddev->ready) {bio_io_error (bio);
drivers/s390/block/dcssblk.c +2 -0
@@ -815,6 +815,8 @@ dcssblk_make_request(struct request_queue *q, struct bio *bio)unsigned long source_addr;unsigned long bytes_done; +blk_queue_split (q, &bio, q->bio_split); + bytes_done =0 ; dev_info = bio->bi_bdev->bd_disk->private_data;if (dev_info ==NULL )
drivers/s390/block/xpram.c +2 -0
@@ -190,6 +190,8 @@ static void xpram_make_request(struct request_queue *q, struct bio *bio)unsigned long page_addr;unsigned long bytes; +blk_queue_split (q, &bio, q->bio_split); +if ((bio->bi_iter.bi_sector &7 ) !=0 || (bio->bi_iter.bi_size &4095 ) !=0 )/* Request is not page-aligned. */
drivers/staging/lustre/lustre/llite/lloop.c +2 -0
@@ -341,6 +341,8 @@ static void loop_make_request(struct request_queue *q, struct bio *old_bio)int rw =bio_rw (old_bio);int inactive; +blk_queue_split (q, &old_bio, q->bio_split); +if (!lo) goto err;
include/linux/blkdev.h +3 -0
@@ -484,6 +484,7 @@ struct request_queue {struct blk_mq_tag_set *tag_set;struct list_head tag_set_list; +struct bio_set *bio_split; };#define QUEUE_FLAG_QUEUED 1/* uses generic tag queueing */
@@ -807,6 +808,8 @@ extern void blk_rq_unprep_clone(struct request *rq);extern int blk_insert_cloned_request (struct request_queue *q,struct request *rq);extern void blk_delay_queue (struct request_queue *,unsigned long ); +extern void blk_queue_split (struct request_queue *,struct bio **, +struct bio_set *);extern void blk_recount_segments (struct request_queue *,struct bio *);extern int scsi_verify_blk_ioctl (struct block_device *,unsigned int ); extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
Signature · 1 line
2.1.0
PATCH v2 2/9 block: simplify bio_add_page()
From: Kent Overstreet <[email protected]>
Since generic_make_request() can now handle arbitrary size bios, all we have to do is make sure the bvec array doesn't overflow. __bio_add_page() doesn't need to call ->merge_bvec_fn(), where we can get rid of unnecessary code paths.
Note that removing call to ->merge_bvec_fn() is fine for bio_add_pc_page(), as SCSI devices usually don't even need that. Few exceptional cases like pscsi or osd are not affected either.
[dpark: rebase and resolve merge conflicts, change a couple of comments,
make bio_add_page() warn once upon a cloned bio.]
--- block/bio.c | 135 +++++++++++++++++++++++++----------------------------------- 1 file changed, 55 insertions(+), 80 deletions(-)
block/bio.c +55 -80
@@ -700,9 +700,23 @@ int bio_get_nr_vecs(struct block_device *bdev) }EXPORT_SYMBOL (bio_get_nr_vecs); -static int __bio_add_page (struct request_queue *q,struct bio *bio,struct page - *page,unsigned int len,unsigned int offset, -unsigned int max_sectors) +/** +* bio_add_pc_page - attempt to add page to bio +* @q: the target queue +* @bio: destination bio +* @page: page to add +* @len: vec entry length +* @offset: vec entry offset +* +* Attempt to add a page to the bio_vec maplist. This can fail for a +* number of reasons, such as the bio being full or target block device +* limitations. The target block device must allow bio's up to PAGE_SIZE, +* so it is always possible to add a single page to an empty bio. +* +* This should only be used by REQ_PC bios. +*/ +int bio_add_pc_page (struct request_queue *q,struct bio *bio,struct page + *page,unsigned int len,unsigned int offset) {int retried_segments =0 ;struct bio_vec *bvec;
@@ -713,7 +727,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct pageif (unlikely (bio_flagged (bio,BIO_CLONED )))return 0 ; -if (((bio->bi_iter.bi_size + len) >>9 ) > max_sectors) +if (((bio->bi_iter.bi_size + len) >>9 ) >queue_max_hw_sectors (q))return 0 ;/*
@@ -726,28 +740,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct pageif (page == prev->bv_page && offset == prev->bv_offset + prev->bv_len) { -unsigned int prev_bv_len = prev->bv_len; prev->bv_len += len; - -if (q->merge_bvec_fn) { -struct bvec_merge_data bvm = { -/* prev_bvec is already charged in -bi_size, discharge it in order to -simulate merging updated prev_bvec -as new bvec. */ - .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_iter.bi_sector, - .bi_size = bio->bi_iter.bi_size - - prev_bv_len, - .bi_rw = bio->bi_rw, - }; - -if (q->merge_bvec_fn (q, &bvm, prev) < prev->bv_len) { - prev->bv_len -= len; -return 0 ; - } - } - bio->bi_iter.bi_size += len; goto done; }
@@ -790,27 +783,6 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct pageblk_recount_segments (q, bio); } -/* -* if queue has other restrictions (eg varying max sector size -* depending on offset), it can specify a merge_bvec_fn in the -* queue to get further control -*/ -if (q->merge_bvec_fn) { -struct bvec_merge_data bvm = { - .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_iter.bi_sector, - .bi_size = bio->bi_iter.bi_size - len, - .bi_rw = bio->bi_rw, - }; - -/* -* merge_bvec_fn() returns number of bytes it can accept -* at this offset -*/ -if (q->merge_bvec_fn (q, &bvm, bvec) < bvec->bv_len) - goto failed; - } -/* If we may be able to merge these biovecs, force a recount */ if (bio->bi_vcnt >1 && (BIOVEC_PHYS_MERGEABLE (bvec-1 , bvec))) bio->bi_flags &= ~(1 <<BIO_SEG_VALID );
@@ -827,28 +799,6 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct pageblk_recount_segments (q, bio);return 0 ; } - -/** -* bio_add_pc_page - attempt to add page to bio -* @q: the target queue -* @bio: destination bio -* @page: page to add -* @len: vec entry length -* @offset: vec entry offset -* -* Attempt to add a page to the bio_vec maplist. This can fail for a -* number of reasons, such as the bio being full or target block device -* limitations. The target block device must allow bio's up to PAGE_SIZE, -* so it is always possible to add a single page to an empty bio. -* -* This should only be used by REQ_PC bios. -*/ -int bio_add_pc_page (struct request_queue *q,struct bio *bio,struct page *page, -unsigned int len,unsigned int offset) -{ -return __bio_add_page (q, bio, page, len, offset, -queue_max_hw_sectors (q)); -}EXPORT_SYMBOL (bio_add_pc_page);/**
@@ -858,22 +808,47 @@ EXPORT_SYMBOL(bio_add_pc_page);* @len: vec entry length * @offset: vec entry offset * -* Attempt to add a page to the bio_vec maplist. This can fail for a -* number of reasons, such as the bio being full or target block device -* limitations. The target block device must allow bio's up to PAGE_SIZE, -* so it is always possible to add a single page to an empty bio. +* Attempt to add a page to the bio_vec maplist. This will only fail +* if either bio->bi_vcnt == bio->bi_max_vecs or it's a cloned bio. */ -int bio_add_page (struct bio *bio,struct page *page,unsigned int len, -unsigned int offset) +int bio_add_page (struct bio *bio,struct page *page, +unsigned int len,unsigned int offset) { -struct request_queue *q =bdev_get_queue (bio->bi_bdev); -unsigned int max_sectors; +struct bio_vec *bv; - max_sectors =blk_max_size_offset (q, bio->bi_iter.bi_sector); -if ((max_sectors < (len >>9 )) && !bio->bi_iter.bi_size) - max_sectors = len >>9 ; +/* +* cloned bio must not modify vec list +*/ +if (WARN_ON_ONCE (bio_flagged (bio,BIO_CLONED ))) +return 0 ; -return __bio_add_page (q, bio, page, len, offset, max_sectors); +/* +* For filesystems with a blocksize smaller than the pagesize +* we will often be called with the same page as last time and +* a consecutive offset. Optimize this special case. +*/ +if (bio->bi_vcnt >0 ) { + bv = &bio->bi_io_vec[bio->bi_vcnt -1 ]; + +if (page == bv->bv_page && + offset == bv->bv_offset + bv->bv_len) { + bv->bv_len += len; + goto done; + } + } + +if (bio->bi_vcnt >= bio->bi_max_vecs) +return 0 ; + + bv = &bio->bi_io_vec[bio->bi_vcnt]; + bv->bv_page = page; + bv->bv_len = len; + bv->bv_offset = offset; + + bio->bi_vcnt++; +done: + bio->bi_iter.bi_size += len; +return len; }EXPORT_SYMBOL (bio_add_page);
Signature · 1 line
2.1.0
PATCH v2 3/9 block: allow __blk_queue_bounce() to handle bios larger than BIO_MAX_PAGES
From: Kent Overstreet <[email protected]>
Allow __blk_queue_bounce() to handle bios with more than BIO_MAX_PAGES segments. Doing that, it becomes possible to simplify the block layer in the kernel.
The issue is that any code that clones the bio and must clone the biovec (i.e. it can't use bio_clone_fast()) won't be able to allocate a bio with more than BIO_MAX_PAGES - bio_alloc_bioset() always fails in that case.
Fortunately, it's easy to make __blk_queue_bounce() just process part of the bio if necessary, using bi_remaining to count the splits and punting the rest back to generic_make_request().
--- block/bounce.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 8 deletions(-)
block/bounce.c +52 -8
@@ -196,6 +196,43 @@ static int must_snapshot_stable_pages(struct request_queue *q, struct bio *bio) }#endif /* CONFIG_NEED_BOUNCE_POOL */ +static struct bio *bio_clone_segments (struct bio *bio_src,gfp_t gfp_mask, +struct bio_set *bs,unsigned nsegs) +{ +struct bvec_iter iter; +struct bio_vec bv; +struct bio *bio; + + bio =bio_alloc_bioset (gfp_mask, nsegs, bs); +if (!bio) +return NULL ; + + bio->bi_bdev = bio_src->bi_bdev; + bio->bi_rw = bio_src->bi_rw; + bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; + +bio_for_each_segment (bv, bio_src, iter) { + bio->bi_io_vec[bio->bi_vcnt++] = bv; + bio->bi_iter.bi_size += bv.bv_len; +if (!--nsegs) +break ; + } + +if (bio_integrity (bio_src)) { +int ret; + + ret =bio_integrity_clone (bio, bio_src, gfp_mask); +if (ret <0 ) { +bio_put (bio); +return NULL ; + } + } + + bio_src->bi_iter = iter; + +return bio; +} +static void __blk_queue_bounce (struct request_queue *q,struct bio **bio_orig,mempool_t *pool,int force) {
@@ -203,17 +240,24 @@ static void __blk_queue_bounce(struct request_queue *q, struct bio **bio_orig,int rw =bio_data_dir (*bio_orig);struct bio_vec *to, from;struct bvec_iter iter; -unsigned i; +int i, nsegs =0 , bounce = force; -if (force) - goto bounce; -bio_for_each_segment (from, *bio_orig, iter) +bio_for_each_segment (from, *bio_orig, iter) { + nsegs++;if (page_to_pfn (from.bv_page) >queue_bounce_pfn (q)) - goto bounce; + bounce =1 ; + } + +if (!bounce) +return ; -return ; -bounce: - bio =bio_clone_bioset (*bio_orig,GFP_NOIO , fs_bio_set); + bio =bio_clone_segments (*bio_orig,GFP_NOIO , fs_bio_set, +min (nsegs,BIO_MAX_PAGES )); + +if ((*bio_orig)->bi_iter.bi_size) { +atomic_inc (&(*bio_orig)->bi_remaining); +generic_make_request (*bio_orig); + }bio_for_each_segment_all (to, bio, i) {struct page *page = to->bv_page;
Signature · 1 line
2.1.0
PATCH v2 4/9 bcache: clean up hacks around bio_split_pool
From: Kent Overstreet <[email protected]>
There has been workarounds only in bcache, for splitting pool as well as submitting bios. Since generic_make_request() is able to handle arbitrarily sized bios, it's now possible to delete those hacks.
--- drivers/md/bcache/bcache.h | 18 -------- drivers/md/bcache/io.c | 100 +----------------------------------------- drivers/md/bcache/journal.c | 4 +- drivers/md/bcache/request.c | 16 +++---- drivers/md/bcache/super.c | 32 +------------- drivers/md/bcache/util.h | 5 ++- drivers/md/bcache/writeback.c | 4 +- 7 files changed, 18 insertions(+), 161 deletions(-)
drivers/md/bcache/bcache.h +0 -18
@@ -243,19 +243,6 @@ struct keybuf { DECLARE_ARRAY_ALLOCATOR(struct keybuf_key, freelist, KEYBUF_NR); }; -struct bio_split_pool { -struct bio_set *bio_split; -mempool_t *bio_split_hook; -}; - -struct bio_split_hook { -struct closure cl; -struct bio_split_pool *p; -struct bio *bio; -bio_end_io_t *bi_end_io; -void *bi_private; -}; -struct bcache_device {struct closure cl;
@@ -288,8 +275,6 @@ struct bcache_device {int (*cache_miss)(struct btree *,struct search *,struct bio *,unsigned );int (*ioctl) (struct bcache_device *,fmode_t ,unsigned ,unsigned long ); - -struct bio_split_pool bio_split_hook; };struct io {
@@ -454,8 +439,6 @@ struct cache {atomic_long_t meta_sectors_written;atomic_long_t btree_sectors_written;atomic_long_t sectors_written; - -struct bio_split_pool bio_split_hook; };struct gc_stat {
@@ -873,7 +856,6 @@ void bch_bbio_endio(struct cache_set *, struct bio *, int, const char *);void bch_bbio_free (struct bio *,struct cache_set *);struct bio *bch_bbio_alloc (struct cache_set *); -void bch_generic_make_request (struct bio *,struct bio_split_pool *);void __bch_submit_bbio (struct bio *,struct cache_set *);void bch_submit_bbio (struct bio *,struct cache_set *,struct bkey *,unsigned );
drivers/md/bcache/io.c +1 -99
112 lines not on this page · raw message
drivers/md/bcache/journal.c +2 -2
@@ -61,7 +61,7 @@ reread: left = ca->sb.bucket_size - offset; bio->bi_private = &cl;bch_bio_map (bio, data); -closure_bio_submit (bio, &cl, ca); +closure_bio_submit (bio, &cl);closure_sync (&cl);/* This function could be simpler now since we no longer write
@@ -646,7 +646,7 @@ static void journal_write_unlocked(struct closure *cl)spin_unlock (&c->journal.lock);while ((bio =bio_list_pop (&list))) -closure_bio_submit (bio, cl, c->cache[0 ]); +closure_bio_submit (bio, cl);continue_at (cl, journal_write_done,NULL ); }
drivers/md/bcache/request.c +8 -8
@@ -710,7 +710,7 @@ static void cached_dev_read_error(struct closure *cl)/* XXX: invalidate cache */ -closure_bio_submit (bio, cl, s->d); +closure_bio_submit (bio, cl); }continue_at (cl, cached_dev_cache_miss_done,NULL );
@@ -833,7 +833,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s, s->cache_miss = miss; s->iop.bio = cache_bio;bio_get (cache_bio); -closure_bio_submit (cache_bio, &s->cl, s->d); +closure_bio_submit (cache_bio, &s->cl);return ret; out_put:
@@ -841,7 +841,7 @@ out_put: out_submit: miss->bi_end_io = request_endio; miss->bi_private = &s->cl; -closure_bio_submit (miss, &s->cl, s->d); +closure_bio_submit (miss, &s->cl);return ret; }
@@ -906,7 +906,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s)if (!(bio->bi_rw &REQ_DISCARD ) ||blk_queue_discard (bdev_get_queue (dc->bdev))) -closure_bio_submit (bio, cl, s->d); +closure_bio_submit (bio, cl); }else if (s->iop.writeback) {bch_writeback_add (dc); s->iop.bio = bio;
@@ -921,12 +921,12 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) flush->bi_end_io = request_endio; flush->bi_private = cl; -closure_bio_submit (flush, cl, s->d); +closure_bio_submit (flush, cl); } }else { s->iop.bio =bio_clone_fast (bio,GFP_NOIO , dc->disk.bio_split); -closure_bio_submit (bio, cl, s->d); +closure_bio_submit (bio, cl); }closure_call (&s->iop.cl, bch_data_insert,NULL , cl);
@@ -942,7 +942,7 @@ static void cached_dev_nodata(struct closure *cl)bch_journal_meta (s->iop.c, cl);/* If it's a flush, we send the flush to the backing device too */ -closure_bio_submit (bio, cl, s->d); +closure_bio_submit (bio, cl);continue_at (cl, cached_dev_bio_complete,NULL ); }
@@ -986,7 +986,7 @@ static void cached_dev_make_request(struct request_queue *q, struct bio *bio) !blk_queue_discard(bdev_get_queue(dc->bdev)))bio_endio (bio,0 ); else - bch_generic_make_request(bio, &d->bio_split_hook); +generic_make_request (bio ); } }
drivers/md/bcache/super.c +2 -30
@@ -59,29 +59,6 @@ struct workqueue_struct *bcache_wq;#define BTREE_MAX_PAGES (256 * 1024 / PAGE_SIZE) -static void bio_split_pool_free (struct bio_split_pool *p) -{ -if (p->bio_split_hook) -mempool_destroy (p->bio_split_hook); - -if (p->bio_split) -bioset_free (p->bio_split); -} - -static int bio_split_pool_init (struct bio_split_pool *p) -{ - p->bio_split =bioset_create (4 ,0 ); -if (!p->bio_split) -return -ENOMEM ; - - p->bio_split_hook =mempool_create_kmalloc_pool (4 , -sizeof (struct bio_split_hook )); -if (!p->bio_split_hook) -return -ENOMEM ; - -return 0 ; -} -/* Superblock */ static const char *read_super(struct cache_sb *sb, struct block_device *bdev,
@@ -537,7 +514,7 @@ static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw) bio->bi_private = ca;bch_bio_map (bio, ca->disk_buckets); -closure_bio_submit (bio, &ca->prio, ca); +closure_bio_submit (bio, &ca->prio);closure_sync (cl); }
@@ -757,7 +734,6 @@ static void bcache_device_free(struct bcache_device *d)put_disk (d->disk); } -bio_split_pool_free (&d->bio_split_hook);if (d->bio_split)bioset_free (d->bio_split);if (is_vmalloc_addr (d->full_dirty_stripes))
@@ -810,7 +786,6 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,return minor;if (!(d->bio_split =bioset_create (4 , offsetof(struct bbio , bio))) || -bio_split_pool_init (&d->bio_split_hook) || !(d->disk =alloc_disk (1 ))) {ida_simple_remove (&bcache_minor, minor);return -ENOMEM ;
@@ -1799,8 +1774,6 @@ void bch_cache_release(struct kobject *kobj) ca->set->cache[ca->sb.nr_this_dev] =NULL ; } -bio_split_pool_free (&ca->bio_split_hook); -free_pages ((unsigned long ) ca->disk_buckets,ilog2 (bucket_pages (ca)));kfree (ca->prio_buckets);vfree (ca->buckets);
@@ -1845,8 +1818,7 @@ static int cache_alloc(struct cache_sb *sb, struct cache *ca) ca->sb.nbuckets)) || !(ca->prio_buckets =kzalloc (sizeof (uint64_t ) *prio_buckets (ca) *2 ,GFP_KERNEL )) || - !(ca->disk_buckets =alloc_bucket_pages (GFP_KERNEL , ca)) || - bio_split_pool_init(&ca->bio_split_hook)) + !(ca->disk_buckets = alloc_bucket_pages(GFP_KERNEL, ca))) return -ENOMEM; ca->prio_last_buckets = ca->prio_buckets +prio_buckets (ca);
drivers/md/bcache/util.h +3 -2
@@ -4,6 +4,7 @@#include <linux/blkdev.h> #include <linux/errno.h> +#include <linux/blkdev.h> #include <linux/kernel.h> #include <linux/llist.h> #include <linux/ratelimit.h>
@@ -576,10 +577,10 @@ static inline sector_t bdev_sectors(struct block_device *bdev)return bdev->bd_inode->i_size >>9 ; } -#define closure_bio_submit (bio, cl, dev) \ +#define closure_bio_submit (bio, cl) \ do { \ closure_get(cl); \ - bch_generic_make_request(bio, &(dev)->bio_split_hook); \ + generic_make_request(bio); \ } while (0)uint64_t bch_crc64_update (uint64_t ,const void *,size_t );
drivers/md/bcache/writeback.c +2 -2
@@ -188,7 +188,7 @@ static void write_dirty(struct closure *cl) io->bio.bi_bdev = io->dc->bdev; io->bio.bi_end_io = dirty_endio; -closure_bio_submit (&io->bio, cl, &io->dc->disk); +closure_bio_submit (&io->bio, cl);continue_at (cl, write_dirty_finish, system_wq); }
@@ -208,7 +208,7 @@ static void read_dirty_submit(struct closure *cl) { struct dirty_io *io = container_of(cl, struct dirty_io, cl); -closure_bio_submit (&io->bio, cl, &io->dc->disk); +closure_bio_submit (&io->bio, cl);continue_at (cl, write_dirty, system_wq); }
Signature · 1 line
2.1.0
PATCH v2 5/9 btrfs: remove bio splitting and merge_bvec_fn() calls
From: Kent Overstreet <[email protected]>
Btrfs has been doing bio splitting from btrfs_map_bio(), by checking device limits as well as calling ->merge_bvec_fn() etc. That is not necessary any more, because generic_make_request() is now able to handle arbitrarily sized bios. So clean up unnecessary code paths.
--- fs/btrfs/volumes.c | 73 ------------------------------------------------------ 1 file changed, 73 deletions(-)
fs/btrfs/volumes.c +0 -73
@@ -5691,34 +5691,6 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root, &device->work); } -static int bio_size_ok (struct block_device *bdev,struct bio *bio, -sector_t sector) -{ -struct bio_vec *prev; -struct request_queue *q =bdev_get_queue (bdev); -unsigned int max_sectors =queue_max_sectors (q); -struct bvec_merge_data bvm = { - .bi_bdev = bdev, - .bi_sector = sector, - .bi_rw = bio->bi_rw, - }; - -if (WARN_ON (bio->bi_vcnt ==0 )) -return 1 ; - - prev = &bio->bi_io_vec[bio->bi_vcnt -1 ]; -if (bio_sectors (bio) > max_sectors) -return 0 ; - -if (!q->merge_bvec_fn) -return 1 ; - - bvm.bi_size = bio->bi_iter.bi_size - prev->bv_len; -if (q->merge_bvec_fn (q, &bvm, prev) < prev->bv_len) -return 0 ; -return 1 ; -} -static void submit_stripe_bio (struct btrfs_root *root,struct btrfs_bio *bbio,struct bio *bio,u64 physical,int dev_nr,int rw,int async)
@@ -5752,38 +5724,6 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio,btrfsic_submit_bio (rw, bio); } -static int breakup_stripe_bio (struct btrfs_root *root,struct btrfs_bio *bbio, -struct bio *first_bio,struct btrfs_device *dev, -int dev_nr,int rw,int async) -{ -struct bio_vec *bvec = first_bio->bi_io_vec; -struct bio *bio; -int nr_vecs =bio_get_nr_vecs (dev->bdev); -u64 physical = bbio->stripes[dev_nr].physical; - -again: - bio =btrfs_bio_alloc (dev->bdev, physical >>9 , nr_vecs,GFP_NOFS ); -if (!bio) -return -ENOMEM ; - -while (bvec <= (first_bio->bi_io_vec + first_bio->bi_vcnt -1 )) { -if (bio_add_page (bio, bvec->bv_page, bvec->bv_len, - bvec->bv_offset) < bvec->bv_len) { -u64 len = bio->bi_iter.bi_size; - -atomic_inc (&bbio->stripes_pending); -submit_stripe_bio (root, bbio, bio, physical, dev_nr, - rw, async); - physical += len; - goto again; - } - bvec++; - } - -submit_stripe_bio (root, bbio, bio, physical, dev_nr, rw, async); -return 0 ; -} -static void bbio_error (struct btrfs_bio *bbio,struct bio *bio,u64 logical) {atomic_inc (&bbio->error);
@@ -5862,19 +5802,6 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,continue ; } -/* -* Check and see if we're ok with this bio based on it's size -* and offset with the given device. -*/ -if (!bio_size_ok (dev->bdev, first_bio, - bbio->stripes[dev_nr].physical >>9 )) { - ret =breakup_stripe_bio (root, bbio, first_bio, dev, - dev_nr, rw, async_submit); -BUG_ON (ret); - dev_nr++; -continue ; - } -if (dev_nr < total_devs -1 ) { bio =btrfs_bio_clone (first_bio,GFP_NOFS );BUG_ON (!bio);/* -ENOMEM */
Signature · 1 line
2.1.0
PATCH v2 6/9 md/raid5: get rid of bio_fits_rdev()
From: Kent Overstreet <[email protected]>
Remove bio_fits_rdev() completely, because ->merge_bvec_fn() has now gone. There's no point in calling bio_fits_rdev() only for ensuring aligned read from rdev.
--- drivers/md/raid5.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-)
drivers/md/raid5.c +1 -22
@@ -4218,25 +4218,6 @@ static void raid5_align_endio(struct bio *bi, int error)add_bio_to_retry (raid_bi, conf); } -static int bio_fits_rdev (struct bio *bi) -{ -struct request_queue *q =bdev_get_queue (bi->bi_bdev); - -if (bio_sectors (bi) >queue_max_sectors (q)) -return 0 ; -blk_recount_segments (q, bi); -if (bi->bi_phys_segments >queue_max_segments (q)) -return 0 ; - -if (q->merge_bvec_fn) -/* it's too hard to apply the merge_bvec_fn at this stage, -* just just give up -*/ -return 0 ; - -return 1 ; -} -static int chunk_aligned_read (struct mddev *mddev,struct bio * raid_bio) {struct r5conf *conf = mddev->private;
@@ -4290,11 +4271,9 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) align_bi->bi_bdev = rdev->bdev;__clear_bit (BIO_SEG_VALID , &align_bi->bi_flags); -if (!bio_fits_rdev (align_bi) || -is_badblock (rdev, align_bi->bi_iter.bi_sector, +if (is_badblock (rdev, align_bi->bi_iter.bi_sector,bio_sectors (align_bi), &first_bad, &bad_sectors)) { -/* too big in some way, or has a known bad block */ bio_put (align_bi);rdev_dec_pending (rdev, mddev);return 0 ;
Signature · 1 line
2.1.0
PATCH v2 7/9 block: kill merge_bvec_fn() completely
From: Kent Overstreet <[email protected]>
As generic_make_request() is now able to handle arbitrarily sized bios, it's no longer necessary for each individual block driver to define its own ->merge_bvec_fn() callback. Remove every invocation completely.
[dpark: also remove ->merge_bvec_fn() in dm-thin as well as
dm-era-target, and resolve merge conflicts]
--- block/blk-merge.c | 17 +----- block/blk-settings.c | 22 -------- drivers/block/drbd/drbd_int.h | 1 - drivers/block/drbd/drbd_main.c | 1 - drivers/block/drbd/drbd_req.c | 35 ------------ drivers/block/pktcdvd.c | 21 ------- drivers/block/rbd.c | 47 ---------------- drivers/md/dm-cache-target.c | 21 ------- drivers/md/dm-crypt.c | 16 ------ drivers/md/dm-era-target.c | 15 ----- drivers/md/dm-flakey.c | 16 ------ drivers/md/dm-linear.c | 16 ------ drivers/md/dm-snap.c | 15 ----- drivers/md/dm-stripe.c | 21 ------- drivers/md/dm-table.c | 8 --- drivers/md/dm-thin.c | 31 ----------- drivers/md/dm-verity.c | 16 ------ drivers/md/dm.c | 120 +--------------------------------------- drivers/md/dm.h | 2 - drivers/md/linear.c | 46 ---------------- drivers/md/md.c | 2 - drivers/md/md.h | 8 --- drivers/md/multipath.c | 21 ------- drivers/md/raid0.c | 57 ------------------- drivers/md/raid0.h | 2 - drivers/md/raid1.c | 59 +------------------- drivers/md/raid10.c | 122 +---------------------------------------- drivers/md/raid5.c | 28 ---------- include/linux/blkdev.h | 10 ---- include/linux/device-mapper.h | 4 -- 30 files changed, 9 insertions(+), 791 deletions(-)
block/blk-merge.c +3 -14
@@ -69,24 +69,13 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,struct bio *split;struct bio_vec bv = {0 }, bvprv = {0 };struct bvec_iter iter; -unsigned seg_size =0 , nsegs =0 ; +unsigned seg_size =0 , nsegs =0 , sectors =0 ;int prev =0 ; -struct bvec_merge_data bvm = { - .bi_bdev = bio->bi_bdev, - .bi_sector = bio->bi_iter.bi_sector, - .bi_size =0 , - .bi_rw = bio->bi_rw, - }; -bio_for_each_segment (bv, bio, iter) { -if (q->merge_bvec_fn && - q->merge_bvec_fn (q, &bvm, &bv) < (int ) bv.bv_len) - goto split; - - bvm.bi_size += bv.bv_len; + sectors += bv.bv_len >>9 ; -if (bvm.bi_size >>9 >queue_max_sectors (q)) +if (sectors >queue_max_sectors (q)) goto split;if (prev &&blk_queue_cluster (q)) {
block/blk-settings.c +0 -22
@@ -53,28 +53,6 @@ void blk_queue_unprep_rq(struct request_queue *q, unprep_rq_fn *ufn) }EXPORT_SYMBOL (blk_queue_unprep_rq); -/** -* blk_queue_merge_bvec - set a merge_bvec function for queue -* @q: queue -* @mbfn: merge_bvec_fn -* -* Usually queues have static limitations on the max sectors or segments that -* we can put in a request. Stacking drivers may have some settings that -* are dynamic, and thus we have to query the queue whether it is ok to -* add a new bio_vec to a bio at a given offset or not. If the block device -* has such limitations, it needs to register a merge_bvec_fn to control -* the size of bio's sent to it. Note that a block device *must* allow a -* single page to be added to an empty bio. The block device driver may want -* to use the bio_split() function to deal with these bio's. By default -* no merge_bvec_fn is defined for a queue, and only the fixed limits are -* honored. -*/ -void blk_queue_merge_bvec (struct request_queue *q,merge_bvec_fn *mbfn) -{ - q->merge_bvec_fn = mbfn; -} -EXPORT_SYMBOL (blk_queue_merge_bvec); -void blk_queue_softirq_done (struct request_queue *q,softirq_done_fn *fn) { q->softirq_done_fn = fn;
drivers/block/drbd/drbd_int.h +0 -1
@@ -1449,7 +1449,6 @@ extern void do_submit(struct work_struct *ws);extern void __drbd_make_request (struct drbd_device *,struct bio *,unsigned long );extern void drbd_make_request (struct request_queue *q,struct bio *bio);extern int drbd_read_remote (struct drbd_device *device,struct drbd_request *req); -extern int drbd_merge_bvec (struct request_queue *q,struct bvec_merge_data *bvm,struct bio_vec *bvec);extern int is_valid_ar_handle (struct drbd_request *,sector_t );
drivers/block/drbd/drbd_main.c +0 -1
@@ -2775,7 +2775,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsigThis triggers a max_bio_size message upon first attach or connect */ blk_queue_max_hw_sectors (q,DRBD_MAX_BIO_SIZE_SAFE >>8 );blk_queue_bounce_limit (q,BLK_BOUNCE_ANY ); -blk_queue_merge_bvec (q, drbd_merge_bvec); q->queue_lock = &resource->req_lock; device->md_io.page =alloc_page (GFP_KERNEL );
drivers/block/drbd/drbd_req.c +0 -35
@@ -1509,41 +1509,6 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)__drbd_make_request (device, bio, start_jif); } -/* This is called by bio_add_page(). -* -* q->max_hw_sectors and other global limits are already enforced there. -* -* We need to call down to our lower level device, -* in case it has special restrictions. -* -* We also may need to enforce configured max-bio-bvecs limits. -* -* As long as the BIO is empty we have to allow at least one bvec, -* regardless of size and offset, so no need to ask lower levels. -*/ -int drbd_merge_bvec (struct request_queue *q,struct bvec_merge_data *bvm,struct bio_vec *bvec) -{ -struct drbd_device *device = (struct drbd_device *) q->queuedata; -unsigned int bio_size = bvm->bi_size; -int limit =DRBD_MAX_BIO_SIZE ; -int backing_limit; - -if (bio_size &&get_ldev (device)) { -unsigned int max_hw_sectors =queue_max_hw_sectors (q); -struct request_queue *const b = - device->ldev->backing_bdev->bd_disk->queue; -if (b->merge_bvec_fn) { - bvm->bi_bdev = device->ldev->backing_bdev; - backing_limit = b->merge_bvec_fn (b, bvm, bvec); - limit =min (limit, backing_limit); - } -put_ldev (device); -if ((limit >>9 ) > max_hw_sectors) - limit = max_hw_sectors <<9 ; - } -return limit; -} -void request_timer_fn (unsigned long data) {struct drbd_device *device = (struct drbd_device *) data;
drivers/block/pktcdvd.c +0 -21
@@ -2505,26 +2505,6 @@ end_io: -static int pkt_merge_bvec (struct request_queue *q,struct bvec_merge_data *bmd, -struct bio_vec *bvec) -{ -struct pktcdvd_device *pd = q->queuedata; -sector_t zone =get_zone (bmd->bi_sector, pd); -int used = ((bmd->bi_sector - zone) <<9 ) + bmd->bi_size; -int remaining = (pd->settings.size <<9 ) - used; -int remaining2; - -/* -* A bio <= PAGE_SIZE must be allowed. If it crosses a packet -* boundary, pkt_make_request() will split the bio. -*/ - remaining2 =PAGE_SIZE - bmd->bi_size; - remaining =max (remaining, remaining2); - -BUG_ON (remaining <0 ); -return remaining; -} -static void pkt_init_queue (struct pktcdvd_device *pd) {struct request_queue *q = pd->disk->queue;
@@ -2532,7 +2512,6 @@ static void pkt_init_queue(struct pktcdvd_device *pd)blk_queue_make_request (q, pkt_make_request);blk_queue_logical_block_size (q,CD_FRAMESIZE );blk_queue_max_hw_sectors (q,PACKET_MAX_SECTORS ); -blk_queue_merge_bvec (q, pkt_merge_bvec); q->queuedata = pd; }
drivers/block/rbd.c +0 -47
59 lines not on this page · raw message
drivers/md/dm-cache-target.c +0 -21
@@ -3277,26 +3277,6 @@ static int cache_iterate_devices(struct dm_target *ti,return r; } -/* -* We assume I/O is going to the origin (which is the volume -* more likely to have restrictions e.g. by being striped). -* (Looking up the exact location of the data would be expensive -* and could always be out of date by the time the bio is submitted.) -*/ -static int cache_bvec_merge (struct dm_target *ti, -struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct cache *cache = ti->private; -struct request_queue *q =bdev_get_queue (cache->origin_dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = cache->origin_dev->bdev; -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static void set_discard_limits (struct cache *cache,struct queue_limits *limits) {/*
@@ -3340,7 +3320,6 @@ static struct target_type cache_target = { .status = cache_status, .message = cache_message, .iterate_devices = cache_iterate_devices, - .merge = cache_bvec_merge, .io_hints = cache_io_hints, };
drivers/md/dm-crypt.c +0 -16
@@ -1951,21 +1951,6 @@ error:return -EINVAL ; } -static int crypt_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct crypt_config *cc = ti->private; -struct request_queue *q =bdev_get_queue (cc->dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = cc->dev->bdev; - bvm->bi_sector = cc->start +dm_target_offset (ti, bvm->bi_sector); - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static int crypt_iterate_devices (struct dm_target *ti,iterate_devices_callout_fn fn,void *data) {
@@ -1986,7 +1971,6 @@ static struct target_type crypt_target = { .preresume = crypt_preresume, .resume = crypt_resume, .message = crypt_message, - .merge = crypt_merge, .iterate_devices = crypt_iterate_devices, };
drivers/md/dm-era-target.c +0 -15
@@ -1673,20 +1673,6 @@ static int era_iterate_devices(struct dm_target *ti,return fn (ti, era->origin_dev,0 ,get_dev_size (era->origin_dev), data); } -static int era_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct era *era = ti->private; -struct request_queue *q =bdev_get_queue (era->origin_dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = era->origin_dev->bdev; - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static void era_io_hints (struct dm_target *ti,struct queue_limits *limits) {struct era *era = ti->private;
@@ -1717,7 +1703,6 @@ static struct target_type era_target = { .status = era_status, .message = era_message, .iterate_devices = era_iterate_devices, - .merge = era_merge, .io_hints = era_io_hints };
drivers/md/dm-flakey.c +0 -16
@@ -387,21 +387,6 @@ static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arreturn r ? :__blkdev_driver_ioctl (dev->bdev, dev->mode, cmd, arg); } -static int flakey_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct flakey_c *fc = ti->private; -struct request_queue *q =bdev_get_queue (fc->dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = fc->dev->bdev; - bvm->bi_sector =flakey_map_sector (ti, bvm->bi_sector); - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static int flakey_iterate_devices (struct dm_target *ti,iterate_devices_callout_fn fn,void *data) {struct flakey_c *fc = ti->private;
@@ -419,7 +404,6 @@ static struct target_type flakey_target = { .end_io = flakey_end_io, .status = flakey_status, .ioctl = flakey_ioctl, - .merge = flakey_merge, .iterate_devices = flakey_iterate_devices, };
drivers/md/dm-linear.c +0 -16
@@ -130,21 +130,6 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd,return r ? :__blkdev_driver_ioctl (dev->bdev, dev->mode, cmd, arg); } -static int linear_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct linear_c *lc = ti->private; -struct request_queue *q =bdev_get_queue (lc->dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = lc->dev->bdev; - bvm->bi_sector =linear_map_sector (ti, bvm->bi_sector); - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static int linear_iterate_devices (struct dm_target *ti,iterate_devices_callout_fn fn,void *data) {
@@ -162,7 +147,6 @@ static struct target_type linear_target = { .map = linear_map, .status = linear_status, .ioctl = linear_ioctl, - .merge = linear_merge, .iterate_devices = linear_iterate_devices, };
drivers/md/dm-snap.c +0 -15
@@ -2234,20 +2234,6 @@ static void origin_status(struct dm_target *ti, status_type_t type, } } -static int origin_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct dm_origin *o = ti->private; -struct request_queue *q =bdev_get_queue (o->dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = o->dev->bdev; - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static int origin_iterate_devices (struct dm_target *ti,iterate_devices_callout_fn fn,void *data) {
@@ -2265,7 +2251,6 @@ static struct target_type origin_target = { .map = origin_map, .resume = origin_resume, .status = origin_status, - .merge = origin_merge, .iterate_devices = origin_iterate_devices, };
drivers/md/dm-stripe.c +0 -21
@@ -412,26 +412,6 @@ static void stripe_io_hints(struct dm_target *ti,blk_limits_io_opt (limits, chunk_size * sc->stripes); } -static int stripe_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct stripe_c *sc = ti->private; -sector_t bvm_sector = bvm->bi_sector; -uint32_t stripe; -struct request_queue *q; - -stripe_map_sector (sc, bvm_sector, &stripe, &bvm_sector); - - q =bdev_get_queue (sc->stripe[stripe].dev->bdev); -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = sc->stripe[stripe].dev->bdev; - bvm->bi_sector = sc->stripe[stripe].physical_start + bvm_sector; - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static struct target_type stripe_target = { .name ="striped" , .version = {1 ,5 ,1 },
@@ -443,7 +423,6 @@ static struct target_type stripe_target = { .status = stripe_status, .iterate_devices = stripe_iterate_devices, .io_hints = stripe_io_hints, - .merge = stripe_merge, };int __init dm_stripe_init (void )
drivers/md/dm-table.c +0 -8
@@ -443,14 +443,6 @@ static int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, q->limits.alignment_offset, (unsigned long long) start << SECTOR_SHIFT); -/* -* Check if merge fn is supported. -* If not we'll force DM to use PAGE_SIZE or -* smaller I/O, just to be safe. -*/ -if (dm_queue_merge_is_compulsory (q) && !ti->type->merge) -blk_limits_max_hw_sectors (limits, - (unsigned int ) (PAGE_SIZE >>9 ));return 0 ; }
drivers/md/dm-thin.c +0 -31
@@ -3566,20 +3566,6 @@ static int pool_iterate_devices(struct dm_target *ti,return fn (ti, pt->data_dev,0 , ti->len, data); } -static int pool_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct pool_c *pt = ti->private; -struct request_queue *q =bdev_get_queue (pt->data_dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = pt->data_dev->bdev; - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static void set_discard_limits (struct pool_c *pt,struct queue_limits *limits) {struct pool *pool = pt->pool;
@@ -3671,7 +3657,6 @@ static struct target_type pool_target = { .resume = pool_resume, .message = pool_message, .status = pool_status, - .merge = pool_merge, .iterate_devices = pool_iterate_devices, .io_hints = pool_io_hints, };
@@ -3996,21 +3981,6 @@ err:DMEMIT ("Error" ); } -static int thin_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct thin_c *tc = ti->private; -struct request_queue *q =bdev_get_queue (tc->pool_dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = tc->pool_dev->bdev; - bvm->bi_sector =dm_target_offset (ti, bvm->bi_sector); - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static int thin_iterate_devices (struct dm_target *ti,iterate_devices_callout_fn fn,void *data) {
@@ -4045,7 +4015,6 @@ static struct target_type thin_target = { .presuspend = thin_presuspend, .postsuspend = thin_postsuspend, .status = thin_status, - .merge = thin_merge, .iterate_devices = thin_iterate_devices, };
drivers/md/dm-verity.c +0 -16
@@ -564,21 +564,6 @@ static int verity_ioctl(struct dm_target *ti, unsigned cmd, cmd, arg); } -static int verity_merge (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size) -{ -struct dm_verity *v = ti->private; -struct request_queue *q =bdev_get_queue (v->data_dev->bdev); - -if (!q->merge_bvec_fn) -return max_size; - - bvm->bi_bdev = v->data_dev->bdev; - bvm->bi_sector =verity_map_sector (v, bvm->bi_sector); - -return min (max_size, q->merge_bvec_fn (q, bvm, biovec)); -} -static int verity_iterate_devices (struct dm_target *ti,iterate_devices_callout_fn fn,void *data) {
@@ -872,7 +857,6 @@ static struct target_type verity_target = { .map = verity_map, .status = verity_status, .ioctl = verity_ioctl, - .merge = verity_merge, .iterate_devices = verity_iterate_devices, .io_hints = verity_io_hints, };
drivers/md/dm.c +2 -118
161 lines not on this page · raw message
drivers/md/dm.h +0 -2
@@ -76,8 +76,6 @@ bool dm_table_request_based(struct dm_table *t);void dm_table_free_md_mempools (struct dm_table *t);struct dm_md_mempools *dm_table_get_md_mempools (struct dm_table *t); -int dm_queue_merge_is_compulsory (struct request_queue *q); -void dm_lock_md_type (struct mapped_device *md);void dm_unlock_md_type (struct mapped_device *md);void dm_set_md_type (struct mapped_device *md,unsigned type);
drivers/md/linear.c +0 -46
58 lines not on this page · raw message
drivers/md/md.c +0 -2
@@ -5033,7 +5033,6 @@ static void md_clean(struct mddev *mddev) mddev->changed =0 ; mddev->degraded =0 ; mddev->safemode =0 ; - mddev->merge_check_needed =0 ; mddev->bitmap_info.offset =0 ; mddev->bitmap_info.default_offset =0 ; mddev->bitmap_info.default_space =0 ;
@@ -5201,7 +5200,6 @@ static int do_md_stop(struct mddev *mddev, int mode,__md_stop_writes (mddev);__md_stop (mddev); - mddev->queue->merge_bvec_fn =NULL ; mddev->queue->backing_dev_info.congested_fn =NULL ;/* tell userspace to handle 'inactive' */
drivers/md/md.h +0 -8
@@ -132,10 +132,6 @@ enum flag_bits { Bitmap_sync,/* ..actually, not quite In_sync. Need a * bitmap-based recovery to get fully in sync */ - Unmerged,/* device is being added to array and should -* be considerred for bvec_merge_fn but not -* yet for actual IO -*/ WriteMostly,/* Avoid reading if at all possible */ AutoDetected,/* added by auto-detect */ Blocked, /* An error occurred but has not yet
@@ -366,10 +362,6 @@ struct mddev {int degraded;/* whether md should consider * adding a spare */ -int merge_check_needed;/* at least one -* member device -* has a -* merge_bvec_fn */ atomic_t recovery_active;/* blocks scheduled, but not written */ wait_queue_head_t recovery_wait;
drivers/md/multipath.c +0 -21
@@ -261,18 +261,6 @@ static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)disk_stack_limits (mddev->gendisk, rdev->bdev, rdev->data_offset <<9 ); -/* as we don't honour merge_bvec_fn, we must never risk -* violating it, so limit ->max_segments to one, lying -* within a single page. -* (Note: it is very unlikely that a device with -* merge_bvec_fn will be involved in multipath.) -*/ -if (q->merge_bvec_fn) { -blk_queue_max_segments (mddev->queue,1 ); -blk_queue_segment_boundary (mddev->queue, -PAGE_CACHE_SIZE -1 ); - } -spin_lock_irq (&conf->device_lock); mddev->degraded--; rdev->raid_disk = path;
@@ -436,15 +424,6 @@ static int multipath_run (struct mddev *mddev)disk_stack_limits (mddev->gendisk, rdev->bdev, rdev->data_offset <<9 ); -/* as we don't honour merge_bvec_fn, we must never risk -* violating it, not that we ever expect a device with -* a merge_bvec_fn to be involved in multipath */ -if (rdev->bdev->bd_disk->queue->merge_bvec_fn) { -blk_queue_max_segments (mddev->queue,1 ); -blk_queue_segment_boundary (mddev->queue, -PAGE_CACHE_SIZE -1 ); - } -if (!test_bit (Faulty, &rdev->flags)) working_disks++; }
drivers/md/raid0.c +0 -57
75 lines not on this page · raw message
drivers/md/raid0.h +0 -2
@@ -12,8 +12,6 @@ struct r0conf {struct md_rdev **devlist;/* lists of rdevs, pointed to * by strip_zone->dev */ int nr_strip_zones; -int has_merge_bvec;/* at least one member has - * a merge_bvec_fn */ };#endif
drivers/md/raid1.c +1 -58
107 lines not on this page · raw message
drivers/md/raid10.c +3 -119
186 lines not on this page · raw message
drivers/md/raid5.c +0 -28
@@ -4103,32 +4103,6 @@ static int raid5_congested(void *data, int bits)md_raid5_congested (mddev, bits); } -/* We want read requests to align with chunks where possible, -* but write requests don't need to. -*/ -static int raid5_mergeable_bvec (struct request_queue *q, -struct bvec_merge_data *bvm, -struct bio_vec *biovec) -{ -struct mddev *mddev = q->queuedata; -sector_t sector = bvm->bi_sector +get_start_sect (bvm->bi_bdev); -int max; -unsigned int chunk_sectors = mddev->chunk_sectors; -unsigned int bio_sectors = bvm->bi_size >>9 ; - -if ((bvm->bi_rw &1 ) ==WRITE ) -return biovec->bv_len;/* always allow writes to be mergeable */ - -if (mddev->new_chunk_sectors < mddev->chunk_sectors) - chunk_sectors = mddev->new_chunk_sectors; - max = (chunk_sectors - ((sector & (chunk_sectors -1 )) + bio_sectors)) <<9 ; -if (max <0 ) max =0 ; -if (max <= biovec->bv_len && bio_sectors ==0 ) -return biovec->bv_len; -else -return max; -} -static int in_chunk_boundary (struct mddev *mddev,struct bio *bio) {sector_t sector = bio->bi_iter.bi_sector +get_start_sect (bio->bi_bdev);
@@ -6152,8 +6126,6 @@ static int run(struct mddev *mddev)if (mddev->queue->backing_dev_info.ra_pages <2 * stripe) mddev->queue->backing_dev_info.ra_pages =2 * stripe; -blk_queue_merge_bvec (mddev->queue, raid5_mergeable_bvec); - mddev->queue->backing_dev_info.congested_data = mddev; mddev->queue->backing_dev_info.congested_fn = raid5_congested;
include/linux/blkdev.h +0 -10
@@ -239,14 +239,6 @@ typedef int (prep_rq_fn) (struct request_queue *, struct request *);typedef void (unprep_rq_fn ) (struct request_queue *,struct request *);struct bio_vec ; -struct bvec_merge_data { -struct block_device *bi_bdev; -sector_t bi_sector; -unsigned bi_size; -unsigned long bi_rw; -}; -typedef int (merge_bvec_fn ) (struct request_queue *,struct bvec_merge_data *, -struct bio_vec *);typedef void (softirq_done_fn )(struct request *);typedef int (dma_drain_needed_fn )(struct request *);typedef int (lld_busy_fn ) (struct request_queue *q);
@@ -327,7 +319,6 @@ struct request_queue {make_request_fn *make_request_fn;prep_rq_fn *prep_rq_fn;unprep_rq_fn *unprep_rq_fn; -merge_bvec_fn *merge_bvec_fn;softirq_done_fn *softirq_done_fn;rq_timed_out_fn *rq_timed_out_fn;dma_drain_needed_fn *dma_drain_needed;
@@ -1036,7 +1027,6 @@ extern void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn);extern void blk_queue_segment_boundary (struct request_queue *,unsigned long );extern void blk_queue_prep_rq (struct request_queue *,prep_rq_fn *pfn);extern void blk_queue_unprep_rq (struct request_queue *,unprep_rq_fn *ufn); -extern void blk_queue_merge_bvec (struct request_queue *,merge_bvec_fn *);extern void blk_queue_dma_alignment (struct request_queue *,int );extern void blk_queue_update_dma_alignment (struct request_queue *,int );extern void blk_queue_softirq_done (struct request_queue *,softirq_done_fn *);
include/linux/device-mapper.h +0 -4
@@ -77,9 +77,6 @@ typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv);typedef int (*dm_ioctl_fn ) (struct dm_target *ti,unsigned int cmd,unsigned long arg); -typedef int (*dm_merge_fn ) (struct dm_target *ti,struct bvec_merge_data *bvm, -struct bio_vec *biovec,int max_size); -/* * These iteration functions are typically used to check (and combine) * properties of underlying devices.
@@ -153,7 +150,6 @@ struct target_type {dm_status_fn status;dm_message_fn message;dm_ioctl_fn ioctl; -dm_merge_fn merge;dm_busy_fn busy;dm_iterate_devices_fn iterate_devices;dm_io_hints_fn io_hints;
Signature · 1 line
2.1.0
PATCH v2 8/9 fs: use helper bio_add_page() instead of open coding on bi_io_vec
From: Kent Overstreet <[email protected]>
Call pre-defined helper bio_add_page() instead of open coding for iterating through bi_io_vec[]. Doing that, it's possible to make some parts in filesystems and mm/page_io.c simpler than before.
--- fs/buffer.c | 7 ++----- fs/jfs/jfs_logmgr.c | 14 ++++---------- mm/page_io.c | 8 +++----- 3 files changed, 9 insertions(+), 20 deletions(-)
fs/buffer.c +2 -5
@@ -3022,12 +3022,9 @@ int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >>9 ); bio->bi_bdev = bh->b_bdev; - bio->bi_io_vec[0 ].bv_page = bh->b_page; - bio->bi_io_vec[0 ].bv_len = bh->b_size; - bio->bi_io_vec[0 ].bv_offset =bh_offset (bh); - bio->bi_vcnt =1 ; - bio->bi_iter.bi_size = bh->b_size; +bio_add_page (bio, bh->b_page, bh->b_size,bh_offset (bh)); +BUG_ON (bio->bi_iter.bi_size != bh->b_size); bio->bi_end_io = end_bio_bh_io_sync; bio->bi_private = bh;
fs/jfs/jfs_logmgr.c +4 -10
@@ -1999,12 +1999,9 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize -9 ); bio->bi_bdev = log->bdev; - bio->bi_io_vec[0 ].bv_page = bp->l_page; - bio->bi_io_vec[0 ].bv_len =LOGPSIZE ; - bio->bi_io_vec[0 ].bv_offset = bp->l_offset; - bio->bi_vcnt =1 ; - bio->bi_iter.bi_size =LOGPSIZE ; +bio_add_page (bio, bp->l_page,LOGPSIZE , bp->l_offset); +BUG_ON (bio->bi_iter.bi_size !=LOGPSIZE ); bio->bi_end_io = lbmIODone; bio->bi_private = bp;
@@ -2145,12 +2142,9 @@ static void lbmStartIO(struct lbuf * bp) bio =bio_alloc (GFP_NOFS ,1 ); bio->bi_iter.bi_sector = bp->l_blkno << (log->l2bsize -9 ); bio->bi_bdev = log->bdev; - bio->bi_io_vec[0 ].bv_page = bp->l_page; - bio->bi_io_vec[0 ].bv_len =LOGPSIZE ; - bio->bi_io_vec[0 ].bv_offset = bp->l_offset; - bio->bi_vcnt =1 ; - bio->bi_iter.bi_size =LOGPSIZE ; +bio_add_page (bio, bp->l_page,LOGPSIZE , bp->l_offset); +BUG_ON (bio->bi_iter.bi_size !=LOGPSIZE ); bio->bi_end_io = lbmIODone; bio->bi_private = bp;
mm/page_io.c +3 -5
@@ -33,12 +33,10 @@ static struct bio *get_swap_bio(gfp_t gfp_flags,if (bio) { bio->bi_iter.bi_sector =map_swap_page (page, &bio->bi_bdev); bio->bi_iter.bi_sector <<=PAGE_SHIFT -9 ; - bio->bi_io_vec[0 ].bv_page = page; - bio->bi_io_vec[0 ].bv_len =PAGE_SIZE ; - bio->bi_io_vec[0 ].bv_offset =0 ; - bio->bi_vcnt =1 ; - bio->bi_iter.bi_size =PAGE_SIZE ; bio->bi_end_io = end_io; + +bio_add_page (bio, page,PAGE_SIZE ,0 ); +BUG_ON (bio->bi_iter.bi_size !=PAGE_SIZE ); }return bio; }
Signature · 1 line
2.1.0
PATCH v2 9/9 Documentation: update notes in biovecs about arbitrarily sized bios
Update block/biovecs.txt so that it includes a note on what kind of effects arbitrarily sized bios would bring to the block layer. Also fix a trivial typo, bio_iter_iovec.
--- Documentation/block/biovecs.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/block/biovecs.txt +9 -1
@@ -24,7 +24,7 @@ particular, presenting the illusion of partially completed biovecs so that normal code doesn't have to deal with bi_bvec_done. * Driver code should no longer refer to biovecs directly; we now have - bio_iovec() and bio_iovec_iter() macros that return literal struct biovecs, + bio_iovec() and bio_iter_iovec() macros that return literal struct biovecs, constructed from the raw biovecs but taking into account bi_bvec_done and bi_size.
@@ -109,3 +109,11 @@ Other implications: over all the biovecs in the new bio - which is silly as it's not needed. So, don't use bi_vcnt anymore. + + * The current interface allows the block layer to split bios as needed, so we + could eliminate a lot of complexity particularly in stacked drivers. Code + that creates bios can then create whatever size bios are convenient, and + more importantly stacked drivers don't have to deal with both their own bio + size limitations and the limitations of the underlying devices. Thus + there's no need to define ->merge_bvec_fn() callbacks for individual block + drivers.
Signature · 1 line
2.1.0
Quoted 1 line
- move a patch "btrfs: make use of immutable biovecs" to the upcoming series.
which upcoming series is that?