Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1615568

Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request

From NeilBrown <neilb@suse.com>
Newsgroups linux.kernel
Subject Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request
Date 2017-04-03 23:30 +0200
Message-ID <tshHY-3Tw-23@gated-at.bofh.it> (permalink)
References <ts8Y3-6GK-45@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


[Multipart message — attachments visible in raw view] - view raw

On Mon, Apr 03 2017, Michael Wang wrote:

> blk_attempt_plug_merge() try to merge bio into request and chain them
> by 'bi_next', while after the bio is done inside request, we forgot to
> reset the 'bi_next'.
>
> This lead into BUG while removing all the underlying devices from md-raid1,
> the bio once go through:
>
>   md_do_sync()
>     sync_request()
>       generic_make_request()

This is a read request from the "first" device.

>         blk_queue_bio()
>           blk_attempt_plug_merge()
>             CHAINED HERE
>
> will keep chained and reused by:
>
>   raid1d()
>     sync_request_write()
>       generic_make_request()

This is a write request to some other device, isn't it?

If sync_request_write() is using a bio that has already been used, it
should call bio_reset() and fill in the details again.
However I don't see how that would happen.
Can you give specific details on the situation that triggers the bug?

Thanks,
NeilBrown


>         BUG_ON(bio->bi_next)
>
> After reset the 'bi_next' this can no longer happen.
>
> Signed-off-by: Michael Wang <yun.wang@profitbricks.com>
> ---
>  block/blk-core.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/block/blk-core.c b/block/blk-core.c
> index 43b7d06..91223b2 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -2619,8 +2619,10 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
>                 struct bio *bio = req->bio;
>                 unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes);
>
> -               if (bio_bytes == bio->bi_iter.bi_size)
> +               if (bio_bytes == bio->bi_iter.bi_size) {
>                         req->bio = bio->bi_next;
> +                       bio->bi_next = NULL;
> +               }
>
>                 req_bio_endio(req, bio, bio_bytes, error);
>
> -- 
> 2.5.0

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[RFC PATCH] blk: reset 'bi_next' when bio is done inside request Michael Wang <yun.wang@profitbricks.com> - 2017-04-03 14:10 +0200
  Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request NeilBrown <neilb@suse.com> - 2017-04-03 23:30 +0200
    Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request Michael Wang <yun.wang@profitbricks.com> - 2017-04-04 10:20 +0200
      Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request NeilBrown <neilb@suse.com> - 2017-04-04 11:40 +0200
        Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request Michael Wang <yun.wang@profitbricks.com> - 2017-04-04 12:30 +0200
          Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request Michael Wang <yun.wang@profitbricks.com> - 2017-04-04 14:30 +0200
            Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request Michael Wang <yun.wang@profitbricks.com> - 2017-04-04 14:50 +0200
          Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request NeilBrown <neilb@suse.com> - 2017-04-05 00:00 +0200

csiph-web