All of lore.kernel.org
 help / color / mirror / Atom feed
From: sagig@dev.mellanox.co.il (Sagi Grimberg)
Subject: [PATCH 3/3] block: Refuse adding appending a gapped integrity page to a bio
Date: Wed, 2 Sep 2015 20:30:51 +0300	[thread overview]
Message-ID: <55E7324B.3060601@dev.mellanox.co.il> (raw)
In-Reply-To: <20150902143756.GA11062@kernel.dk>

On 9/2/2015 5:37 PM, Jens Axboe wrote:
> On 09/02/2015 02:04 AM, Sagi Grimberg wrote:
>> On 8/19/2015 1:42 PM, Christoph Hellwig wrote:
>>> On Wed, Aug 19, 2015@01:30:56PM +0300, Sagi Grimberg wrote:
>>>> Actually I didn't. I started to, but then I noticed that
>>>> I was still seeing gaps when using cfq (e.g. non-mq code
>>>> path), I assume that this was never tested?
>>>
>>> It probably wasn't.  The only user so far is the NVMe driver which
>>> is blk-mq only.
>>
>> So I got back to have a look on this. I originally thought that
>> this issue was specific to io schedulers, but I don't think it is
>> anymore, its just easier to trigger with io schedulers.
>>
>> It seems we are only protecting against gapped back merges (i.e.
>> appending a gapped bio to a request biotail) but we are not protecting
>> against front merges (i.e. adding a gapped bio to request as the bio
>> head).
>>
>> Imagine we have two bio_vec elements and the queue boundary is 0xfff:
>> req_bvec: offset=0xe00 length=0x200
>> bio_bvec: offset=0x0 length=0x200
>>
>> bvec_gap_to_prev() will allow back merging {req_bvec, bio_bvec} as
>> bio_vec->offset=0x0 and req_bvec->offset + req_bvec->length is aligned
>> to the queue boundary, but the problem is we might do a front merge
>> {bio_bvec, req_bvec} which gives us a gap.
>>
>> I'm able to reproduce this with iser with 512B sequential reads
>> (encourage gapped merges) but I wonder how this issue was missed in
>> nvme (the code seem to allow front merges)?
>>
>> Anyway, the patch below seems to solved the issue for me:
>>
>> Comments?
>
> Weird, I guess front merging was overlooked when the initial patch was
> added. Looks correct to me, and as far as I can see, we have now got all
> bases covered.
>
> But there's room for some cleanup now, where we check is a bit of a
> mess. If we kill the check in blk_rq_merge_ok() and only do them in the
> front/back merge points (and the req-to-req case), then I think that
> would be an improvement.


Yea, we do get to checking back merges even for front merges in this
point...

> Does the below work for you?

It's not on top of Keith virt_boundary patch right?
First glance looks ok though.

>
>
> diff --git a/block/blk-merge.c b/block/blk-merge.c
> index 30a0d9f89017..d226bc5e3b8d 100644
> --- a/block/blk-merge.c
> +++ b/block/blk-merge.c
> @@ -309,9 +309,39 @@ no_merge:
>      return 0;
> }
>
> +static bool queue_gap_check(struct request_queue *q, struct bio *bio)
> +{
> +    if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS) && bio_has_data(bio))
> +        return true;
> +
> +    return false;
> +}
> +
> +static bool bio_gap_to_prev(struct bio *prev, struct bio *next)
> +{
> +    return bvec_gap_to_prev(&prev->bi_io_vec[prev->bi_vcnt - 1],
> +                    next->bi_io_vec[0].bv_offset);
> +}
> +
> +static bool req_gap_to_prev(struct request *req, struct bio *bio)
> +{
> +    return bio_gap_to_prev(req->biotail, bio);
> +}
> +
> +static bool req_gap_to_next(struct request *req, struct bio *bio)
> +{
> +    struct bio *next = req->bio;
> +
> +    return bvec_gap_to_prev(&bio->bi_io_vec[bio->bi_vcnt - 1],
> +                    next->bi_io_vec[0].bv_offset);
> +}
> +
> int ll_back_merge_fn(struct request_queue *q, struct request *req,
>               struct bio *bio)
> {
> +    if (queue_gap_check(q, bio) && req_gap_to_prev(req, bio))
> +        return 0;
> +
>      if (blk_rq_sectors(req) + bio_sectors(bio) >
>          blk_rq_get_max_sectors(req)) {
>          req->cmd_flags |= REQ_NOMERGE;
> @@ -330,6 +360,9 @@ int ll_back_merge_fn(struct request_queue *q, struct
> request *req,
> int ll_front_merge_fn(struct request_queue *q, struct request *req,
>                struct bio *bio)
> {
> +    if (queue_gap_check(q, bio) && req_gap_to_next(req, bio))
> +        return 0;
> +
>      if (blk_rq_sectors(req) + bio_sectors(bio) >
>          blk_rq_get_max_sectors(req)) {
>          req->cmd_flags |= REQ_NOMERGE;
> @@ -356,14 +389,6 @@ static bool req_no_special_merge(struct request *req)
>      return !q->mq_ops && req->special;
> }
>
> -static int req_gap_to_prev(struct request *req, struct request *next)
> -{
> -    struct bio *prev = req->biotail;
> -
> -    return bvec_gap_to_prev(&prev->bi_io_vec[prev->bi_vcnt - 1],
> -                next->bio->bi_io_vec[0].bv_offset);
> -}
> -
> static int ll_merge_requests_fn(struct request_queue *q, struct request
> *req,
>                  struct request *next)
> {
> @@ -379,7 +404,7 @@ static int ll_merge_requests_fn(struct request_queue
> *q, struct request *req,
>          return 0;
>
>      if (test_bit(QUEUE_FLAG_SG_GAPS, &q->queue_flags) &&
> -        req_gap_to_prev(req, next))
> +        req_gap_to_prev(req, next->bio))
>          return 0;
>
>      /*
> @@ -564,8 +589,6 @@ int blk_attempt_req_merge(struct request_queue *q,
> struct request *rq,
>
> bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
> {
> -    struct request_queue *q = rq->q;
> -
>      if (!rq_mergeable(rq) || !bio_mergeable(bio))
>          return false;
>
> @@ -589,15 +612,6 @@ bool blk_rq_merge_ok(struct request *rq, struct bio
> *bio)
>          !blk_write_same_mergeable(rq->bio, bio))
>          return false;
>
> -    /* Only check gaps if the bio carries data */
> -    if (q->queue_flags & (1 << QUEUE_FLAG_SG_GAPS) && bio_has_data(bio)) {
> -        struct bio_vec *bprev;
> -
> -        bprev = &rq->biotail->bi_io_vec[rq->biotail->bi_vcnt - 1];
> -        if (bvec_gap_to_prev(bprev, bio->bi_io_vec[0].bv_offset))
> -            return false;
> -    }
> -
>      return true;
> }
>
>

  reply	other threads:[~2015-09-02 17:30 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-15 13:19 [PATCH 0/3] Fixes for gapped scatters Sagi Grimberg
2015-07-15 13:19 ` [PATCH 1/3] block: copy multi iovec user mappings if QUEUE_FLAG_SG_GAPS is set Sagi Grimberg
2015-07-16 16:47   ` Keith Busch
2015-07-16 16:49     ` Jens Axboe
2015-07-16 19:47       ` Matthew Wilcox
2015-07-17 15:26         ` Jens Axboe
2015-07-17  7:44       ` Christoph Hellwig
2015-07-17  7:43     ` Christoph Hellwig
2015-07-15 13:19 ` [PATCH 2/3] block: Refuse request/bio merges with gaps in the integrity payload Sagi Grimberg
2015-07-15 13:19 ` [PATCH 3/3] block: Refuse adding appending a gapped integrity page to a bio Sagi Grimberg
2015-07-15 15:28   ` Jens Axboe
2015-07-16  9:26     ` Christoph Hellwig
2015-07-16 15:58       ` Jens Axboe
2015-07-19 15:18         ` Sagi Grimberg
2015-08-19  9:40           ` Christoph Hellwig
2015-08-19 10:30             ` Sagi Grimberg
2015-08-19 10:42               ` Christoph Hellwig
2015-09-02  8:04                 ` Sagi Grimberg
2015-09-02 14:37                   ` Jens Axboe
2015-09-02 17:30                     ` Sagi Grimberg [this message]
2015-09-02 18:03                       ` Jens Axboe
2015-09-02 19:18                       ` Jens Axboe
2015-09-03  9:07                         ` Sagi Grimberg
2015-09-03 14:53                           ` Jens Axboe
2015-09-03 15:04                           ` Jens Axboe
2015-09-03 15:41                             ` Sagi Grimberg
2015-09-03 15:52                               ` Jens Axboe
2015-07-17  1:50       ` Martin K. Petersen
2015-07-17  1:39 ` [PATCH 0/3] Fixes for gapped scatters Martin K. Petersen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55E7324B.3060601@dev.mellanox.co.il \
    --to=sagig@dev.mellanox.co.il \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.