From: Jens Axboe axboe@kernel.dk
commit cd4a4ae4683dc2e09380118e205e057896dcda2b upstream
If we end up splitting a bio and the queue goes away between the initial submission and the later split submission, then we can block forever in blk_queue_enter() waiting for the reference to drop to zero. This will never happen, since we already hold a reference.
Mark a split bio as already having entered the queue, so we can just use the live non-blocking queue enter variant.
Thanks to Tetsuo Handa for the analysis.
We're running fio tests and the tasks get stuck in a D state forever when systemd-udevd tries to read the partition table. This patch solves it. Please apply to 4.17 stable.
Reported-by: syzbot+c4f9cebf9d651f6e54de@syzkaller.appspotmail.com Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Alexandru Moise 00moses.alexander00@gmail.com --- v2: Fixed "From:" v3: Added "From: Jens Axboe" above commit sha
block/blk-core.c | 4 +++- block/blk-merge.c | 10 ++++++++++ include/linux/blk_types.h | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/block/blk-core.c b/block/blk-core.c index b559b9d4f1a2..47ab2d9d02d9 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2392,7 +2392,9 @@ blk_qc_t generic_make_request(struct bio *bio)
if (bio->bi_opf & REQ_NOWAIT) flags = BLK_MQ_REQ_NOWAIT; - if (blk_queue_enter(q, flags) < 0) { + if (bio_flagged(bio, BIO_QUEUE_ENTERED)) + blk_queue_enter_live(q); + else if (blk_queue_enter(q, flags) < 0) { if (!blk_queue_dying(q) && (bio->bi_opf & REQ_NOWAIT)) bio_wouldblock_error(bio); else diff --git a/block/blk-merge.c b/block/blk-merge.c index 782940c65d8a..481dc02668f9 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -210,6 +210,16 @@ void blk_queue_split(struct request_queue *q, struct bio **bio) /* there isn't chance to merge the splitted bio */ split->bi_opf |= REQ_NOMERGE;
+ /* + * Since we're recursing into make_request here, ensure + * that we mark this bio as already having entered the queue. + * If not, and the queue is going away, we can get stuck + * forever on waiting for the queue reference to drop. But + * that will never happen, as we're already holding a + * reference to it. + */ + bio_set_flag(*bio, BIO_QUEUE_ENTERED); + bio_chain(split, *bio); trace_block_split(q, split, (*bio)->bi_iter.bi_sector); generic_make_request(*bio); diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 17b18b91ebac..1602bf4ab4cd 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -186,6 +186,8 @@ struct bio { * throttling rules. Don't do it again. */ #define BIO_TRACE_COMPLETION 10 /* bio_endio() should trace the final completion * of this bio. */ +#define BIO_QUEUE_ENTERED 11 /* can use blk_queue_enter_live() */ + /* See BVEC_POOL_OFFSET below before adding new flags */
/*
On 7/4/18 5:51 AM, Alexandru Moise wrote:
From: Jens Axboe axboe@kernel.dk
commit cd4a4ae4683dc2e09380118e205e057896dcda2b upstream
If we end up splitting a bio and the queue goes away between the initial submission and the later split submission, then we can block forever in blk_queue_enter() waiting for the reference to drop to zero. This will never happen, since we already hold a reference.
Mark a split bio as already having entered the queue, so we can just use the live non-blocking queue enter variant.
Thanks to Tetsuo Handa for the analysis.
We're running fio tests and the tasks get stuck in a D state forever when systemd-udevd tries to read the partition table. This patch solves it. Please apply to 4.17 stable.
Can you please stop spamming with this?! If you would like to see something in stable, ask the maintainer to get it included. It's not up to random end users.
linux-stable-mirror@lists.linaro.org