]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - block/blk-iocost.c
Merge tag 'selinux-pr-20200127' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / block / blk-iocost.c
index a7ed434eae0387b92d41009b0cc52f3522ed556c..27ca68621137ad5418e647c859b39b12a588f9c2 100644 (file)
@@ -1057,9 +1057,12 @@ static bool iocg_activate(struct ioc_gq *iocg, struct ioc_now *now)
        atomic64_set(&iocg->active_period, cur_period);
 
        /* already activated or breaking leaf-only constraint? */
-       for (i = iocg->level; i > 0; i--)
-               if (!list_empty(&iocg->active_list))
+       if (!list_empty(&iocg->active_list))
+               goto succeed_unlock;
+       for (i = iocg->level - 1; i > 0; i--)
+               if (!list_empty(&iocg->ancestors[i]->active_list))
                        goto fail_unlock;
+
        if (iocg->child_active_sum)
                goto fail_unlock;
 
@@ -1101,6 +1104,7 @@ static bool iocg_activate(struct ioc_gq *iocg, struct ioc_now *now)
                ioc_start_period(ioc, now);
        }
 
+succeed_unlock:
        spin_unlock_irq(&ioc->lock);
        return true;
 
@@ -1208,7 +1212,7 @@ static enum hrtimer_restart iocg_waitq_timer_fn(struct hrtimer *timer)
        return HRTIMER_NORESTART;
 }
 
-static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
+static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
 {
        struct ioc *ioc = iocg->ioc;
        struct blkcg_gq *blkg = iocg_to_blkg(iocg);
@@ -1225,11 +1229,11 @@ static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
        /* clear or maintain depending on the overage */
        if (time_before_eq64(vtime, now->vnow)) {
                blkcg_clear_delay(blkg);
-               return;
+               return false;
        }
        if (!atomic_read(&blkg->use_delay) &&
            time_before_eq64(vtime, now->vnow + vmargin))
-               return;
+               return false;
 
        /* use delay */
        if (cost) {
@@ -1246,10 +1250,11 @@ static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
        oexpires = ktime_to_ns(hrtimer_get_softexpires(&iocg->delay_timer));
        if (hrtimer_is_queued(&iocg->delay_timer) &&
            abs(oexpires - expires) <= margin_ns / 4)
-               return;
+               return true;
 
        hrtimer_start_range_ns(&iocg->delay_timer, ns_to_ktime(expires),
                               margin_ns / 4, HRTIMER_MODE_ABS);
+       return true;
 }
 
 static enum hrtimer_restart iocg_delay_timer_fn(struct hrtimer *timer)
@@ -1735,7 +1740,9 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio)
         */
        if (bio_issue_as_root_blkg(bio) || fatal_signal_pending(current)) {
                atomic64_add(abs_cost, &iocg->abs_vdebt);
-               iocg_kick_delay(iocg, &now, cost);
+               if (iocg_kick_delay(iocg, &now, cost))
+                       blkcg_schedule_throttle(rqos->q,
+                                       (bio->bi_opf & REQ_SWAP) == REQ_SWAP);
                return;
        }