summaryrefslogtreecommitdiff
path: root/block/blk-flush.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@fb.com>2017-02-17 14:08:19 -0700
committerJens Axboe <axboe@fb.com>2017-02-17 14:08:19 -0700
commit818551e2b2c662a1b26de6b4f7d6b8411a838d18 (patch)
treef38b4c951df4d33db81ae7b7765a56bce491c2a8 /block/blk-flush.c
parent6010720da8aab51f33beee63b73cf88016e9b250 (diff)
parent7520872c0cf4d3df6d74242c6edfb9e70a47df4d (diff)
Merge branch 'for-4.11/next' into for-4.11/linus-merge
Signed-off-by: Jens Axboe <axboe@fb.com>
Diffstat (limited to 'block/blk-flush.c')
-rw-r--r--block/blk-flush.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 4427896641ac..0d5a9c1da1fc 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -297,8 +297,14 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq)
if (fq->flush_pending_idx != fq->flush_running_idx || list_empty(pending))
return false;
- /* C2 and C3 */
+ /* C2 and C3
+ *
+ * For blk-mq + scheduling, we can risk having all driver tags
+ * assigned to empty flushes, and we deadlock if we are expecting
+ * other requests to make progress. Don't defer for that case.
+ */
if (!list_empty(&fq->flush_data_in_flight) &&
+ !(q->mq_ops && q->elevator) &&
time_before(jiffies,
fq->flush_pending_since + FLUSH_PENDING_TIMEOUT))
return false;
@@ -327,7 +333,6 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq)
blk_mq_tag_set_rq(hctx, first_rq->tag, flush_rq);
}
- flush_rq->cmd_type = REQ_TYPE_FS;
flush_rq->cmd_flags = REQ_OP_FLUSH | REQ_PREFLUSH;
flush_rq->rq_flags |= RQF_FLUSH_SEQ;
flush_rq->rq_disk = first_rq->rq_disk;
@@ -547,11 +552,10 @@ struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q,
if (!fq)
goto fail;
- if (q->mq_ops) {
+ if (q->mq_ops)
spin_lock_init(&fq->mq_flush_lock);
- rq_sz = round_up(rq_sz + cmd_size, cache_line_size());
- }
+ rq_sz = round_up(rq_sz + cmd_size, cache_line_size());
fq->flush_rq = kzalloc_node(rq_sz, GFP_KERNEL, node);
if (!fq->flush_rq)
goto fail_rq;