diff options
author | Tejun Heo <tj@kernel.org> | 2011-03-04 13:09:02 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2011-03-04 13:09:02 -0500 |
commit | e83a46bbb1d4c03defd733a64b727632a40059ad (patch) | |
tree | c4bc4822b2d3af1bf38095f531adc0a2aac054a5 /block/blk-flush.c | |
parent | da527770007fce8e4541947d47918248286da875 (diff) | |
parent | fd51469fb68b987032e46297e0a4fe9020063c20 (diff) |
Merge branch 'for-linus' of ../linux-2.6-block into block-for-2.6.39/core
This merge creates two set of conflicts. One is simple context
conflicts caused by removal of throtl_scheduled_delayed_work() in
for-linus and removal of throtl_shutdown_timer_wq() in
for-2.6.39/core.
The other is caused by commit 255bb490c8 (block: blk-flush shouldn't
call directly into q->request_fn() __blk_run_queue()) in for-linus
crashing with FLUSH reimplementation in for-2.6.39/core. The conflict
isn't trivial but the resolution is straight-forward.
* __blk_run_queue() calls in flush_end_io() and flush_data_end_io()
should be called with @force_kblockd set to %true.
* elv_insert() in blk_kick_flush() should use
%ELEVATOR_INSERT_REQUEUE.
Both changes are to avoid invoking ->request_fn() directly from
request completion path and closely match the changes in the commit
255bb490c8.
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'block/blk-flush.c')
-rw-r--r-- | block/blk-flush.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/block/blk-flush.c b/block/blk-flush.c index a867e3f524f3..0bd8c9c5d6e5 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c | |||
@@ -212,9 +212,14 @@ static void flush_end_io(struct request *flush_rq, int error) | |||
212 | queued |= blk_flush_complete_seq(rq, seq, error); | 212 | queued |= blk_flush_complete_seq(rq, seq, error); |
213 | } | 213 | } |
214 | 214 | ||
215 | /* after populating an empty queue, kick it to avoid stall */ | 215 | /* |
216 | * Moving a request silently to empty queue_head may stall the | ||
217 | * queue. Kick the queue in those cases. This function is called | ||
218 | * from request completion path and calling directly into | ||
219 | * request_fn may confuse the driver. Always use kblockd. | ||
220 | */ | ||
216 | if (queued && was_empty) | 221 | if (queued && was_empty) |
217 | __blk_run_queue(q); | 222 | __blk_run_queue(q, true); |
218 | } | 223 | } |
219 | 224 | ||
220 | /** | 225 | /** |
@@ -257,7 +262,7 @@ static bool blk_kick_flush(struct request_queue *q) | |||
257 | q->flush_rq.end_io = flush_end_io; | 262 | q->flush_rq.end_io = flush_end_io; |
258 | 263 | ||
259 | q->flush_pending_idx ^= 1; | 264 | q->flush_pending_idx ^= 1; |
260 | elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_FRONT); | 265 | elv_insert(q, &q->flush_rq, ELEVATOR_INSERT_REQUEUE); |
261 | return true; | 266 | return true; |
262 | } | 267 | } |
263 | 268 | ||
@@ -266,9 +271,12 @@ static void flush_data_end_io(struct request *rq, int error) | |||
266 | struct request_queue *q = rq->q; | 271 | struct request_queue *q = rq->q; |
267 | bool was_empty = elv_queue_empty(q); | 272 | bool was_empty = elv_queue_empty(q); |
268 | 273 | ||
269 | /* after populating an empty queue, kick it to avoid stall */ | 274 | /* |
275 | * After populating an empty queue, kick it to avoid stall. Read | ||
276 | * the comment in flush_end_io(). | ||
277 | */ | ||
270 | if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error) && was_empty) | 278 | if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error) && was_empty) |
271 | __blk_run_queue(q); | 279 | __blk_run_queue(q, true); |
272 | } | 280 | } |
273 | 281 | ||
274 | /** | 282 | /** |