/* 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 */
        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)
 
        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,
 {
        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;