Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Tejun Heo and committed by
Jens Axboe
b855b04a ea5f4db8

+15 -12
+15 -12
block/blk-core.c
··· 365 365 366 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 375 if (drain_all) 370 376 blk_throtl_drain(q); 371 377 372 378 /* 373 379 * This function might be called on a queue which failed 374 - * driver init after queue creation. Some drivers 375 - * (e.g. fd) get unhappy in such cases. Kick queue iff 376 - * dispatch queue has something on it. 380 + * driver init after queue creation or is not yet fully 381 + * active yet. Some drivers (e.g. fd and loop) get unhappy 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 386 __blk_run_queue(q); 380 387 381 388 drain |= q->rq.elvpriv; ··· 435 428 spin_unlock_irq(lock); 436 429 mutex_unlock(&q->sysfs_lock); 437 430 438 - /* 439 - * Drain all requests queued before DEAD marking. The caller might 440 - * be trying to tear down @q before its elevator is initialized, in 441 - * which case we don't want to call into draining. 442 - */ 443 - if (q->elevator) 444 - blk_drain_queue(q, true); 431 + /* drain all requests queued before DEAD marking */ 432 + blk_drain_queue(q, true); 445 433 446 434 /* @q won't process any more request, flush async actions */ 447 435 del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer); ··· 506 504 setup_timer(&q->backing_dev_info.laptop_mode_wb_timer, 507 505 laptop_mode_timer_fn, (unsigned long) q); 508 506 setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q); 507 + INIT_LIST_HEAD(&q->queue_head); 509 508 INIT_LIST_HEAD(&q->timeout_list); 510 509 INIT_LIST_HEAD(&q->icq_list); 511 510 INIT_LIST_HEAD(&q->flush_queue[0]);