[PATCH 1/9] block: Make generic_make_request handle arbitrary sized bios

Muthu Kumar muthu.lkml at gmail.com
Sun Mar 2 15:50:00 EST 2014


Never mind...

The following code covers it:


+       if (split) {
+               bio_chain(split, *bio);
+               generic_make_request(*bio);
+               *bio = split;
+       }


My other question is, can we avoid calling the queue_split from
individual drivers make_request()? Can we move the functionality into
generic_make_request()?

Thanks.

Regards,
Muthu


On Sun, Mar 2, 2014 at 12:31 PM, Muthu Kumar <muthu.lkml at gmail.com> wrote:
> Kent,
> The blk_queue_split(), splits a bio into at most two bios right? So,
> if the original bio spans larger space than two bios can cover
> (restriction by the lower driver in the stack), this might not work?
> Am I reading it incorrectly?
>
> Thanks!
>
> Regards,
> Muthu
>
>
>
> On Wed, Feb 26, 2014 at 3:39 PM, Kent Overstreet <kmo at daterainc.com> wrote:
>> 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_fns 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)
>>  * 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.
>>
>> Signed-off-by: Kent Overstreet <kmo at daterainc.com>
>> Cc: Jens Axboe <axboe at kernel.dk>
>> Cc: Neil Brown <neilb at suse.de>
>> Cc: Alasdair Kergon <agk at redhat.com>
>> Cc: dm-devel at redhat.com
>> Cc: Lars Ellenberg <drbd-dev at lists.linbit.com>
>> Cc: drbd-user at lists.linbit.com
>> Cc: Asai Thambi S P <asamymuthupa at micron.com>
>> Cc: Sam Bradshaw <sbradshaw at micron.com>
>> Cc: Matthew Wilcox <willy at linux.intel.com>
>> Cc: linux-nvme at lists.infradead.org
>> Cc: Jiri Kosina <jkosina at suse.cz>
>> Cc: Geoff Levand <geoff at infradead.org>
>> Cc: Jim Paris <jim at jtan.com>
>> Cc: Joshua Morris <josh.h.morris at us.ibm.com>
>> Cc: Philip Kelleher <pjk1939 at linux.vnet.ibm.com>
>> Cc: Minchan Kim <minchan at kernel.org>
>> Cc: Nitin Gupta <ngupta at vflare.org>
>> Cc: Martin Schwidefsky <schwidefsky at de.ibm.com>
>> Cc: Heiko Carstens <heiko.carstens at de.ibm.com>
>> Cc: Peng Tao <bergwolf at gmail.com>
>> ---
>>  block/blk-core.c                            |  19 ++--
>>  block/blk-merge.c                           | 150 ++++++++++++++++++++++++++--
>>  block/blk-mq.c                              |   2 +
>>  drivers/block/drbd/drbd_req.c               |   2 +
>>  drivers/block/mtip32xx/mtip32xx.c           |   6 +-
>>  drivers/block/nvme-core.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 +
>>  17 files changed, 185 insertions(+), 23 deletions(-)
>>
>> diff --git a/block/blk-core.c b/block/blk-core.c
>> index 853f927492..d3b0782ec3 100644
>> --- a/block/blk-core.c
>> +++ b/block/blk-core.c
>> @@ -581,6 +581,10 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
>>         if (q->id < 0)
>>                 goto fail_c;
>>
>> +       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;
>> @@ -590,7 +594,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);
>> @@ -635,6 +639,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_c:
>> @@ -1501,6 +1507,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
>> @@ -1723,15 +1731,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,
>> diff --git a/block/blk-merge.c b/block/blk-merge.c
>> index 6c583f9c5b..0afbe3f1c2 100644
>> --- a/block/blk-merge.c
>> +++ b/block/blk-merge.c
>> @@ -9,11 +9,149 @@
>>
>>  #include "blk.h"
>>
>> +static struct bio *blk_bio_discard_split(struct request_queue *q,
>> +                                        struct bio *bio,
>> +                                        struct bio_set *bs)
>> +{
>> +       unsigned int max_discard_sectors, granularity;
>> +       int alignment;
>> +       sector_t tmp;
>> +       unsigned split_sectors;
>> +
>> +       /* Zero-sector (unknown) and one-sector granularities are the same.  */
>> +       granularity = max(q->limits.discard_granularity >> 9, 1U);
>> +
>> +       max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
>> +       max_discard_sectors -= max_discard_sectors % granularity;
>> +
>> +       if (unlikely(!max_discard_sectors)) {
>> +               /* XXX: warn */
>> +               return NULL;
>> +       }
>> +
>> +       if (bio_sectors(bio) <= max_discard_sectors)
>> +               return NULL;
>> +
>> +       split_sectors = max_discard_sectors;
>> +
>> +       /*
>> +        * If the next starting sector would be misaligned, stop the discard at
>> +        * the previous aligned sector.
>> +        */
>> +       alignment = (q->limits.discard_alignment >> 9) % granularity;
>> +
>> +       tmp = bio->bi_iter.bi_sector + split_sectors - alignment;
>> +       tmp = sector_div(tmp, granularity);
>> +
>> +       if (split_sectors > tmp)
>> +               split_sectors -= tmp;
>> +
>> +       return bio_split(bio, split_sectors, GFP_NOIO, bs);
>> +}
>> +
>> +static struct bio *blk_bio_write_same_split(struct request_queue *q,
>> +                                           struct bio *bio,
>> +                                           struct bio_set *bs)
>> +{
>> +       if (!q->limits.max_write_same_sectors)
>> +               return NULL;
>> +
>> +       if (bio_sectors(bio) <= q->limits.max_write_same_sectors)
>> +               return NULL;
>> +
>> +       return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
>> +}
>> +
>> +static struct bio *blk_bio_segment_split(struct request_queue *q,
>> +                                        struct bio *bio,
>> +                                        struct bio_set *bs)
>> +{
>> +       struct bio *split;
>> +       struct bio_vec bv, bvprv;
>> +       struct bvec_iter iter;
>> +       unsigned seg_size = 0, nsegs = 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;
>> +
>> +               if (bvm.bi_size >> 9 > queue_max_sectors(q))
>> +                       goto split;
>> +
>> +               if (prev && blk_queue_cluster(q)) {
>> +                       if (seg_size + bv.bv_len > queue_max_segment_size(q))
>> +                               goto new_segment;
>> +                       if (!BIOVEC_PHYS_MERGEABLE(&bvprv, &bv))
>> +                               goto new_segment;
>> +                       if (!BIOVEC_SEG_BOUNDARY(q, &bvprv, &bv))
>> +                               goto new_segment;
>> +
>> +                       seg_size += bv.bv_len;
>> +                       bvprv = bv;
>> +                       prev = 1;
>> +                       continue;
>> +               }
>> +new_segment:
>> +               if (nsegs == queue_max_segments(q))
>> +                       goto split;
>> +
>> +               nsegs++;
>> +               bvprv = bv;
>> +               prev = 1;
>> +               seg_size = bv.bv_len;
>> +       }
>> +
>> +       return NULL;
>> +split:
>> +       split = bio_clone_bioset(bio, GFP_NOIO, bs);
>> +
>> +       split->bi_iter.bi_size -= iter.bi_size;
>> +       bio->bi_iter = iter;
>> +
>> +       if (bio_integrity(bio)) {
>> +               bio_integrity_advance(bio, split->bi_iter.bi_size);
>> +               bio_integrity_trim(split, 0, bio_sectors(split));
>> +       }
>> +
>> +       return split;
>> +}
>> +
>> +void blk_queue_split(struct request_queue *q, struct bio **bio,
>> +                    struct bio_set *bs)
>> +{
>> +       struct bio *split;
>> +
>> +       if ((*bio)->bi_rw & REQ_DISCARD)
>> +               split = blk_bio_discard_split(q, *bio, bs);
>> +       else if ((*bio)->bi_rw & REQ_WRITE_SAME)
>> +               split = blk_bio_write_same_split(q, *bio, bs);
>> +       else
>> +               split = blk_bio_segment_split(q, *bio, q->bio_split);
>> +
>> +       if (split) {
>> +               bio_chain(split, *bio);
>> +               generic_make_request(*bio);
>> +               *bio = split;
>> +       }
>> +}
>> +EXPORT_SYMBOL(blk_queue_split);
>> +
>>  static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
>>                                              struct bio *bio)
>>  {
>>         struct bio_vec bv, bvprv = { NULL };
>> -       int cluster, high, highprv = 1;
>> +       int cluster, prev = 0;
>>         unsigned int seg_size, nr_phys_segs;
>>         struct bio *fbio, *bbio;
>>         struct bvec_iter iter;
>> @@ -37,13 +175,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
>>         nr_phys_segs = 0;
>>         for_each_bio(bio) {
>>                 bio_for_each_segment(bv, bio, iter) {
>> -                       /*
>> -                        * the trick here is making sure that a high page is
>> -                        * never considered part of another segment, since that
>> -                        * might change with the bounce page.
>> -                        */
>> -                       high = page_to_pfn(bv.bv_page) > queue_bounce_pfn(q);
>> -                       if (!high && !highprv && cluster) {
>> +                       if (prev && cluster) {
>>                                 if (seg_size + bv.bv_len
>>                                     > queue_max_segment_size(q))
>>                                         goto new_segment;
>> @@ -63,8 +195,8 @@ new_segment:
>>
>>                         nr_phys_segs++;
>>                         bvprv = bv;
>> +                       prev = 1;
>>                         seg_size = bv.bv_len;
>> -                       highprv = high;
>>                 }
>>                 bbio = bio;
>>         }
>> diff --git a/block/blk-mq.c b/block/blk-mq.c
>> index 6468a715a0..7893e254d8 100644
>> --- a/block/blk-mq.c
>> +++ b/block/blk-mq.c
>> @@ -915,6 +915,8 @@ static void blk_mq_make_request(struct request_queue *q, struct bio *bio)
>>                 return;
>>         }
>>
>> +       blk_queue_split(q, &bio, q->bio_split);
>> +
>>         if (use_plug && blk_attempt_plug_merge(q, bio, &request_count))
>>                 return;
>>
>> diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
>> index 104a040f24..941a69c50c 100644
>> --- a/drivers/block/drbd/drbd_req.c
>> +++ b/drivers/block/drbd/drbd_req.c
>> @@ -1275,6 +1275,8 @@ void drbd_make_request(struct request_queue *q, struct bio *bio)
>>         struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
>>         unsigned long start_time;
>>
>> +       blk_queue_split(q, &bio, q->bio_split);
>> +
>>         start_time = jiffies;
>>
>>         /*
>> diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
>> index 516026954b..df733ca685 100644
>> --- a/drivers/block/mtip32xx/mtip32xx.c
>> +++ b/drivers/block/mtip32xx/mtip32xx.c
>> @@ -4033,6 +4033,10 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
>>         int nents = 0;
>>         int tag = 0, unaligned = 0;
>>
>> +       blk_queue_bounce(queue, &bio);
>> +
>> +       blk_queue_split(queue, &bio, queue->bio_split);
>> +
>>         if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
>>                 if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
>>                                                         &dd->dd_flag))) {
>> @@ -4082,8 +4086,6 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
>>
>>         sg = mtip_hw_get_scatterlist(dd, &tag, unaligned);
>>         if (likely(sg != NULL)) {
>> -               blk_queue_bounce(queue, &bio);
>> -
>>                 if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) {
>>                         dev_warn(&dd->pdev->dev,
>>                                 "Maximum number of SGL entries exceeded\n");
>> diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
>> index 51824d1f23..e4376b9613 100644
>> --- a/drivers/block/nvme-core.c
>> +++ b/drivers/block/nvme-core.c
>> @@ -737,6 +737,8 @@ static void nvme_make_request(struct request_queue *q, struct bio *bio)
>>         struct nvme_queue *nvmeq = get_nvmeq(ns->dev);
>>         int result = -EBUSY;
>>
>> +       blk_queue_split(q, &bio, q->bio_split);
>> +
>>         if (!nvmeq) {
>>                 put_nvmeq(NULL);
>>                 bio_endio(bio, -EIO);
>> diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
>> index a2af73db18..a37acf722b 100644
>> --- a/drivers/block/pktcdvd.c
>> +++ b/drivers/block/pktcdvd.c
>> @@ -2444,6 +2444,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",
>> @@ -2474,8 +2478,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);
>> diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
>> index ef45cfb98f..a995972961 100644
>> --- a/drivers/block/ps3vram.c
>> +++ b/drivers/block/ps3vram.c
>> @@ -603,6 +603,8 @@ static void ps3vram_make_request(struct request_queue *q, struct bio *bio)
>>         struct ps3vram_priv *priv = ps3_system_bus_get_drvdata(dev);
>>         int busy;
>>
>> +       blk_queue_split(q, &bio, q->bio_split);
>> +
>>         dev_dbg(&dev->core, "%s\n", __func__);
>>
>>         spin_lock_irq(&priv->lock);
>> diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c
>> index 2839d37e5a..ff074a3cd4 100644
>> --- a/drivers/block/rsxx/dev.c
>> +++ b/drivers/block/rsxx/dev.c
>> @@ -169,6 +169,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)
>> diff --git a/drivers/block/umem.c b/drivers/block/umem.c
>> index 4cf81b5bf0..13d577cfbc 100644
>> --- a/drivers/block/umem.c
>> +++ b/drivers/block/umem.c
>> @@ -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;
>> diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
>> index 011e55d820..ecf9daa01c 100644
>> --- a/drivers/block/zram/zram_drv.c
>> +++ b/drivers/block/zram/zram_drv.c
>> @@ -733,6 +733,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(!zram->init_done))
>>                 goto error;
>> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
>> index 8c53b09b9a..97f70420f2 100644
>> --- a/drivers/md/dm.c
>> +++ b/drivers/md/dm.c
>> @@ -1500,6 +1500,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
>> diff --git a/drivers/md/md.c b/drivers/md/md.c
>> index 4ad5cc4e63..1421bc3f7b 100644
>> --- a/drivers/md/md.c
>> +++ b/drivers/md/md.c
>> @@ -256,6 +256,8 @@ static void md_make_request(struct request_queue *q, struct bio *bio)
>>         int cpu;
>>         unsigned int sectors;
>>
>> +       blk_queue_split(q, &bio, q->bio_split);
>> +
>>         if (mddev == NULL || mddev->pers == NULL
>>             || !mddev->ready) {
>>                 bio_io_error(bio);
>> diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
>> index ebf41e228e..db33cd3e4c 100644
>> --- a/drivers/s390/block/dcssblk.c
>> +++ b/drivers/s390/block/dcssblk.c
>> @@ -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)
>> diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
>> index 6969d39f1e..f03c103f13 100644
>> --- a/drivers/s390/block/xpram.c
>> +++ b/drivers/s390/block/xpram.c
>> @@ -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. */
>> diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c
>> index 0718905ade..a3f6dc930b 100644
>> --- a/drivers/staging/lustre/lustre/llite/lloop.c
>> +++ b/drivers/staging/lustre/lustre/llite/lloop.c
>> @@ -344,6 +344,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;
>>
>> diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
>> index 1e1fa3f93d..99e9955c4d 100644
>> --- a/include/linux/blkdev.h
>> +++ b/include/linux/blkdev.h
>> @@ -470,6 +470,7 @@ struct request_queue {
>>         wait_queue_head_t       mq_freeze_wq;
>>         struct percpu_counter   mq_usage_counter;
>>         struct list_head        all_q_node;
>> +       struct bio_set          *bio_split;
>>  };
>>
>>  #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
>> @@ -781,6 +782,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,
>> --
>> 1.9.0
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/



More information about the Linux-nvme mailing list