block: don't try to throttle split bio if iops limit isn't set
authorMing Lei <ming.lei@redhat.com>
Wed, 16 Feb 2022 04:45:13 +0000 (12:45 +0800)
committerJens Axboe <axboe@kernel.dk>
Thu, 17 Feb 2022 02:42:28 +0000 (19:42 -0700)
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>
block/blk-throttle.c
block/blk-throttle.h

index c7aa26d52e84583357921337f1702d87e3ed6a6c..ec72eced24d2cb35d4f9fe5e9093c71d5e3b6fd0 100644 (file)
 /* A workqueue to queue throttle related work */
 static struct workqueue_struct *kthrotld_workqueue;
 
-enum tg_state_flags {
-       THROTL_TG_PENDING       = 1 << 0,       /* on parent's pending tree */
-       THROTL_TG_WAS_EMPTY     = 1 << 1,       /* bio_lists[] became non-empty */
-};
-
 #define rb_entry_tg(node)      rb_entry((node), struct throtl_grp, rb_node)
 
 /* We measure latency for request size from <= 4k to >= 1M */
@@ -425,12 +420,24 @@ static void tg_update_has_rules(struct throtl_grp *tg)
        struct throtl_grp *parent_tg = sq_to_tg(tg->service_queue.parent_sq);
        struct throtl_data *td = tg->td;
        int rw;
+       int has_iops_limit = 0;
+
+       for (rw = READ; rw <= WRITE; rw++) {
+               unsigned int iops_limit = tg_iops_limit(tg, rw);
 
-       for (rw = READ; rw <= WRITE; rw++)
                tg->has_rules[rw] = (parent_tg && parent_tg->has_rules[rw]) ||
                        (td->limit_valid[td->limit_index] &&
                         (tg_bps_limit(tg, rw) != U64_MAX ||
-                         tg_iops_limit(tg, rw) != UINT_MAX));
+                         iops_limit != UINT_MAX));
+
+               if (iops_limit != UINT_MAX)
+                       has_iops_limit = 1;
+       }
+
+       if (has_iops_limit)
+               tg->flags |= THROTL_TG_HAS_IOPS_LIMIT;
+       else
+               tg->flags &= ~THROTL_TG_HAS_IOPS_LIMIT;
 }
 
 static void throtl_pd_online(struct blkg_policy_data *pd)
index cb43f4417d6ea0014778a45bb403b08f035e7c97..c996a15f290e8a145d1cc4f01de3b45349054f49 100644 (file)
@@ -52,6 +52,12 @@ struct throtl_service_queue {
        struct timer_list       pending_timer;  /* fires on first_pending_disptime */
 };
 
+enum tg_state_flags {
+       THROTL_TG_PENDING       = 1 << 0,       /* on parent's pending tree */
+       THROTL_TG_WAS_EMPTY     = 1 << 1,       /* bio_lists[] became non-empty */
+       THROTL_TG_HAS_IOPS_LIMIT = 1 << 2,      /* tg has iops limit */
+};
+
 enum {
        LIMIT_LOW,
        LIMIT_MAX,
@@ -170,6 +176,11 @@ static inline bool blk_throtl_bio(struct bio *bio)
 {
        struct throtl_grp *tg = blkg_to_tg(bio->bi_blkg);
 
+       /* no need to throttle bps any more if the bio has been throttled */
+       if (bio_flagged(bio, BIO_THROTTLED) &&
+           !(tg->flags & THROTL_TG_HAS_IOPS_LIMIT))
+               return false;
+
        if (!tg->has_rules[bio_data_dir(bio)])
                return false;