summaryrefslogtreecommitdiff
path: root/block/blk-flush.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-flush.c')
-rw-r--r--block/blk-flush.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 671fa9da7560..93d5fd8e51eb 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -211,9 +211,14 @@ static void flush_end_io(struct request *flush_rq, int error)
queued |= blk_flush_complete_seq(rq, seq, error);
}
- /* after populating an empty queue, kick it to avoid stall */
+ /*
+ * Moving a request silently to empty queue_head may stall the
+ * queue. Kick the queue in those cases. This function is called
+ * from request completion path and calling directly into
+ * request_fn may confuse the driver. Always use kblockd.
+ */
if (queued)
- __blk_run_queue(q);
+ __blk_run_queue(q, true);
}
/**
@@ -256,7 +261,7 @@ static bool blk_kick_flush(struct request_queue *q)
q->flush_rq.end_io = flush_end_io;
q->flush_pending_idx ^= 1;
- elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_FRONT);
+ elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_REQUEUE);
return true;
}
@@ -264,9 +269,12 @@ static void flush_data_end_io(struct request *rq, int error)
{
struct request_queue *q = rq->q;
- /* after populating an empty queue, kick it to avoid stall */
+ /*
+ * After populating an empty queue, kick it to avoid stall. Read
+ * the comment in flush_end_io().
+ */
if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error))
- __blk_run_queue(q);
+ __blk_run_queue(q, true);
}
/**