[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <877f31kwti.fsf@notabene.neil.brown.name>
Date: Tue, 04 Apr 2017 07:25:45 +1000
From: NeilBrown <neilb@...e.com>
To: Michael Wang <yun.wang@...fitbricks.com>,
"linux-kernel\@vger.kernel.org" <linux-kernel@...r.kernel.org>,
linux-block@...r.kernel.org, linux-raid@...r.kernel.org
Cc: Jens Axboe <axboe@...nel.dk>, Shaohua Li <shli@...nel.org>,
Jinpu Wang <jinpu.wang@...fitbricks.com>
Subject: Re: [RFC PATCH] blk: reset 'bi_next' when bio is done inside request
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@...fitbricks.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
Download attachment "signature.asc" of type "application/pgp-signature" (833 bytes)
Powered by blists - more mailing lists