diff options
author | Tejun Heo <tj@kernel.org> | 2012-03-06 15:24:55 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-03-06 15:24:55 -0500 |
commit | b855b04a0b2213dbc1b59cf936056726e7ed97ad (patch) | |
tree | 26a432c7f8d014531059a3f0789199d3dde2e3da /block/blk-core.c | |
parent | ea5f4db8ece896c2ab9eafa0924148a2596c52e4 (diff) |
block: blk-throttle should be drained regardless of q->elevator
Currently, blk_cleanup_queue() doesn't call elv_drain_elevator() if
q->elevator doesn't exist; however, bio based drivers don't have
elevator initialized but can still use blk-throttle. This patch moves
q->elevator test inside blk_drain_queue() such that only
elv_drain_elevator() is skipped if !q->elevator.
-v2: loop can have registered queue which has NULL request_fn. Make
sure we don't call into __blk_run_queue() in such cases.
Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Vivek Goyal <vgoyal@redhat.com>
Fold in bug fix from Vivek.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-core.c')
-rw-r--r-- | block/blk-core.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 3a78b00edd71..fccb25021121 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -365,17 +365,24 @@ void blk_drain_queue(struct request_queue *q, bool drain_all) | |||
365 | 365 | ||
366 | spin_lock_irq(q->queue_lock); | 366 | spin_lock_irq(q->queue_lock); |
367 | 367 | ||
368 | elv_drain_elevator(q); | 368 | /* |
369 | * The caller might be trying to drain @q before its | ||
370 | * elevator is initialized. | ||
371 | */ | ||
372 | if (q->elevator) | ||
373 | elv_drain_elevator(q); | ||
374 | |||
369 | if (drain_all) | 375 | if (drain_all) |
370 | blk_throtl_drain(q); | 376 | blk_throtl_drain(q); |
371 | 377 | ||
372 | /* | 378 | /* |
373 | * This function might be called on a queue which failed | 379 | * This function might be called on a queue which failed |
374 | * driver init after queue creation. Some drivers | 380 | * driver init after queue creation or is not yet fully |
375 | * (e.g. fd) get unhappy in such cases. Kick queue iff | 381 | * active yet. Some drivers (e.g. fd and loop) get unhappy |
376 | * dispatch queue has something on it. | 382 | * in such cases. Kick queue iff dispatch queue has |
383 | * something on it and @q has request_fn set. | ||
377 | */ | 384 | */ |
378 | if (!list_empty(&q->queue_head)) | 385 | if (!list_empty(&q->queue_head) && q->request_fn) |
379 | __blk_run_queue(q); | 386 | __blk_run_queue(q); |
380 | 387 | ||
381 | drain |= q->rq.elvpriv; | 388 | drain |= q->rq.elvpriv; |
@@ -428,13 +435,8 @@ void blk_cleanup_queue(struct request_queue *q) | |||
428 | spin_unlock_irq(lock); | 435 | spin_unlock_irq(lock); |
429 | mutex_unlock(&q->sysfs_lock); | 436 | mutex_unlock(&q->sysfs_lock); |
430 | 437 | ||
431 | /* | 438 | /* drain all requests queued before DEAD marking */ |
432 | * Drain all requests queued before DEAD marking. The caller might | 439 | blk_drain_queue(q, true); |
433 | * be trying to tear down @q before its elevator is initialized, in | ||
434 | * which case we don't want to call into draining. | ||
435 | */ | ||
436 | if (q->elevator) | ||
437 | blk_drain_queue(q, true); | ||
438 | 440 | ||
439 | /* @q won't process any more request, flush async actions */ | 441 | /* @q won't process any more request, flush async actions */ |
440 | del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); | 442 | del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); |
@@ -504,6 +506,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) | |||
504 | setup_timer(&q->backing_dev_info.laptop_mode_wb_timer, | 506 | setup_timer(&q->backing_dev_info.laptop_mode_wb_timer, |
505 | laptop_mode_timer_fn, (unsigned long) q); | 507 | laptop_mode_timer_fn, (unsigned long) q); |
506 | setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); | 508 | setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); |
509 | INIT_LIST_HEAD(&q->queue_head); | ||
507 | INIT_LIST_HEAD(&q->timeout_list); | 510 | INIT_LIST_HEAD(&q->timeout_list); |
508 | INIT_LIST_HEAD(&q->icq_list); | 511 | INIT_LIST_HEAD(&q->icq_list); |
509 | INIT_LIST_HEAD(&q->flush_queue[0]); | 512 | INIT_LIST_HEAD(&q->flush_queue[0]); |