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

block: don't try to throttle split bio if iops limit isn't set

We need to throttle split bio in case of IOPS limit even though the
split bio has been marked as BIO_THROTTLED since block layer
accounts split bio actually.

If only throughput throttle is setup, no need to throttle any more
if BIO_THROTTLED is set since we have accounted & considered the
whole bio bytes already.

Add one flag of THROTL_TG_HAS_IOPS_LIMIT for serving this purpose.

Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Link: https://lore.kernel.org/r/20220216044514.2903784-8-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Ming Lei and committed by
Jens Axboe
5a93b602 9f5ede3c

+25 -7
+14 -7
block/blk-throttle.c
··· 41 41 /* A workqueue to queue throttle related work */ 42 42 static struct workqueue_struct *kthrotld_workqueue; 43 43 44 - enum tg_state_flags { 45 - THROTL_TG_PENDING = 1 << 0, /* on parent's pending tree */ 46 - THROTL_TG_WAS_EMPTY = 1 << 1, /* bio_lists[] became non-empty */ 47 - }; 48 - 49 44 #define rb_entry_tg(node) rb_entry((node), struct throtl_grp, rb_node) 50 45 51 46 /* We measure latency for request size from <= 4k to >= 1M */ ··· 420 425 struct throtl_grp *parent_tg = sq_to_tg(tg->service_queue.parent_sq); 421 426 struct throtl_data *td = tg->td; 422 427 int rw; 428 + int has_iops_limit = 0; 423 429 424 - for (rw = READ; rw <= WRITE; rw++) 430 + for (rw = READ; rw <= WRITE; rw++) { 431 + unsigned int iops_limit = tg_iops_limit(tg, rw); 432 + 425 433 tg->has_rules[rw] = (parent_tg && parent_tg->has_rules[rw]) || 426 434 (td->limit_valid[td->limit_index] && 427 435 (tg_bps_limit(tg, rw) != U64_MAX || 428 - tg_iops_limit(tg, rw) != UINT_MAX)); 436 + iops_limit != UINT_MAX)); 437 + 438 + if (iops_limit != UINT_MAX) 439 + has_iops_limit = 1; 440 + } 441 + 442 + if (has_iops_limit) 443 + tg->flags |= THROTL_TG_HAS_IOPS_LIMIT; 444 + else 445 + tg->flags &= ~THROTL_TG_HAS_IOPS_LIMIT; 429 446 } 430 447 431 448 static void throtl_pd_online(struct blkg_policy_data *pd)
+11
block/blk-throttle.h
··· 52 52 struct timer_list pending_timer; /* fires on first_pending_disptime */ 53 53 }; 54 54 55 + enum tg_state_flags { 56 + THROTL_TG_PENDING = 1 << 0, /* on parent's pending tree */ 57 + THROTL_TG_WAS_EMPTY = 1 << 1, /* bio_lists[] became non-empty */ 58 + THROTL_TG_HAS_IOPS_LIMIT = 1 << 2, /* tg has iops limit */ 59 + }; 60 + 55 61 enum { 56 62 LIMIT_LOW, 57 63 LIMIT_MAX, ··· 175 169 static inline bool blk_throtl_bio(struct bio *bio) 176 170 { 177 171 struct throtl_grp *tg = blkg_to_tg(bio->bi_blkg); 172 + 173 + /* no need to throttle bps any more if the bio has been throttled */ 174 + if (bio_flagged(bio, BIO_THROTTLED) && 175 + !(tg->flags & THROTL_TG_HAS_IOPS_LIMIT)) 176 + return false; 178 177 179 178 if (!tg->has_rules[bio_data_dir(bio)]) 180 179 return false;