Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b855b04a authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe
Browse files

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: default avatarTejun Heo <tj@kernel.org>
Reported-by: default avatarVivek Goyal <vgoyal@redhat.com>

Fold in bug fix from Vivek.

Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent ea5f4db8
Loading
Loading
Loading
Loading
+15 −12
Original line number Diff line number Diff line
@@ -365,17 +365,24 @@ void blk_drain_queue(struct request_queue *q, bool drain_all)

		spin_lock_irq(q->queue_lock);

		/*
		 * The caller might be trying to drain @q before its
		 * elevator is initialized.
		 */
		if (q->elevator)
			elv_drain_elevator(q);

		if (drain_all)
			blk_throtl_drain(q);

		/*
		 * This function might be called on a queue which failed
		 * driver init after queue creation.  Some drivers
		 * (e.g. fd) get unhappy in such cases.  Kick queue iff
		 * dispatch queue has something on it.
		 * driver init after queue creation or is not yet fully
		 * active yet.  Some drivers (e.g. fd and loop) get unhappy
		 * in such cases.  Kick queue iff dispatch queue has
		 * something on it and @q has request_fn set.
		 */
		if (!list_empty(&q->queue_head))
		if (!list_empty(&q->queue_head) && q->request_fn)
			__blk_run_queue(q);

		drain |= q->rq.elvpriv;
@@ -428,12 +435,7 @@ void blk_cleanup_queue(struct request_queue *q)
	spin_unlock_irq(lock);
	mutex_unlock(&q->sysfs_lock);

	/*
	 * Drain all requests queued before DEAD marking.  The caller might
	 * be trying to tear down @q before its elevator is initialized, in
	 * which case we don't want to call into draining.
	 */
	if (q->elevator)
	/* drain all requests queued before DEAD marking */
	blk_drain_queue(q, true);

	/* @q won't process any more request, flush async actions */
@@ -504,6 +506,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
	setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
		    laptop_mode_timer_fn, (unsigned long) q);
	setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
	INIT_LIST_HEAD(&q->queue_head);
	INIT_LIST_HEAD(&q->timeout_list);
	INIT_LIST_HEAD(&q->icq_list);
	INIT_LIST_HEAD(&q->flush_queue[0]);