From: Roman Pen <r.peniaev@gmail.com>
To: unlisted-recipients:; (no To-header on input)
Cc: Roman Pen <r.peniaev@gmail.com>, Jens Axboe <axboe@kernel.dk>,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: [PATCH 1/1] blk-core: fix queue stuck on attempt to submit request from unplug
Date: Sun, 27 Sep 2015 22:44:59 +0200 [thread overview]
Message-ID: <1443386699-5049-1-git-send-email-r.peniaev@gmail.com> (raw)
In case of several stacked block devices, which both were inited by
blk_init_queue call, you can catch the queue stuck, if first device
in stack makes bio submit being in a flush of a plug list.
Let's consider this regular scenario taking readahead into account
(readahead.c:read_pages):
1. Start plug
2. Read pages in loop
3. Finish plug
This example generates backtrace as follows:
1. blk_start_plug
2. generic_make_request
q->make_request_fn
[blk_queue_bio]
if (current->plug)
list_add_tail(&req->queuelist, &plug->list);
3. blk_finish_plug
blk_flush_plug_list
queue_unplugged
__blk_run_queue
XXX_request_fn [some request handler of block device]
generic_make_request
q->make_request_fn
[blk_queue_bio]
if (current->plug)
list_add_tail(&req->queuelist, &plug->list);
So the problem is, that on step 3. XXX_request_fn makes
another request, which again will be put to plug list,
because plug is till active, thus new request will be
stuck forever in the queue.
How to fix?
Do flush plug list till it becomes empty.
Signed-off-by: Roman Pen <r.peniaev@gmail.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org
---
block/blk-core.c | 10 ++++++++++
block/blk-mq.c | 13 +++++++++++++
2 files changed, 23 insertions(+)
diff --git a/block/blk-core.c b/block/blk-core.c
index 2eb722d..36b3bd2 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -3151,6 +3151,7 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
LIST_HEAD(list);
unsigned int depth;
+repeat:
flush_plug_callbacks(plug, from_schedule);
if (!list_empty(&plug->mq_list))
@@ -3212,6 +3213,15 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
queue_unplugged(q, depth, from_schedule);
local_irq_restore(flags);
+
+ /*
+ * We have to repeat the whole flush till list becomes
+ * empty, because underlying block device can submit
+ * another bio which again will be put to plug list.
+ * To avoid stuck of these subsequent bios in the queue
+ * we have to flush till the end.
+ */
+ goto repeat;
}
void blk_finish_plug(struct blk_plug *plug)
diff --git a/block/blk-mq.c b/block/blk-mq.c
index f2d67b4..ced83eb 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1091,6 +1091,10 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
LIST_HEAD(ctx_list);
unsigned int depth;
+repeat:
+ if (list_empty(&plug->mq_list))
+ return;
+
list_splice_init(&plug->mq_list, &list);
list_sort(NULL, &list, plug_ctx_cmp);
@@ -1127,6 +1131,15 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
blk_mq_insert_requests(this_q, this_ctx, &ctx_list, depth,
from_schedule);
}
+
+ /*
+ * We have to repeat the whole flush till list becomes
+ * empty, because underlying block device can submit
+ * another bio which again will be put to plug list.
+ * To avoid stuck of these subsequent bios in the queue
+ * we have to flush till the end.
+ */
+ goto repeat;
}
static void blk_mq_bio_to_request(struct request *rq, struct bio *bio)
--
2.5.1
next reply other threads:[~2015-09-27 20:45 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-27 20:44 Roman Pen [this message]
2015-09-28 17:27 ` Jens Axboe
2015-09-28 17:36 ` Roman Peniaev
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=1443386699-5049-1-git-send-email-r.peniaev@gmail.com \
--to=r.peniaev@gmail.com \
--cc=axboe@kernel.dk \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®