diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 6b3ced8ae1a5fe754b20b05905dfe708e7f5dd8f..1e6d5631669b96142e2d2e9ad78281a9a0f7c0f5 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -2198,20 +2198,23 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, struct throtl_service_queue *sq; bool rw = bio_data_dir(bio); bool throttled = false; + bool locked = true; struct throtl_data *td = tg->td; WARN_ON_ONCE(!rcu_read_lock_held()); /* see throtl_charge_bio() */ - if (bio_flagged(bio, BIO_THROTTLED) || !tg->has_rules[rw]) + if (bio_flagged(bio, BIO_THROTTLED) || !tg->has_rules[rw]) { + locked = false; goto out; + } spin_lock_irq(q->queue_lock); throtl_update_latency_buckets(td); if (unlikely(blk_queue_bypass(q))) - goto out_unlock; + goto out; blk_throtl_assoc_bio(tg, bio); blk_throtl_update_idletime(tg); @@ -2263,7 +2266,7 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, sq = sq->parent_sq; tg = sq_to_tg(sq); if (!tg) - goto out_unlock; + goto out; } /* out-of-limit, queue to @tg */ @@ -2291,8 +2294,6 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, throtl_schedule_next_dispatch(tg->service_queue.parent_sq, true); } -out_unlock: - spin_unlock_irq(q->queue_lock); out: bio_set_flag(bio, BIO_THROTTLED); @@ -2300,6 +2301,8 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, if (throttled || !td->track_bio_latency) bio->bi_issue.value |= BIO_ISSUE_THROTL_SKIP_LATENCY; #endif + if (locked) + spin_unlock_irq(q->queue_lock); return throttled; }