]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - block/blk-iocost.c
Merge tag 'sound-fix-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
[linux.git] / block / blk-iocost.c
index cffed980dfac6bc1cced0f6634001b83b9f14dd6..3b39deb8b9f820620b86c0d964b30eb1dbb362b6 100644 (file)
  * https://github.com/osandov/drgn.  The ouput looks like the following.
  *
  *  sdb RUN   per=300ms cur_per=234.218:v203.695 busy= +1 vrate= 62.12%
- *                 active      weight      hweight% inflt% del_ms usages%
- *  test/a              *    50/   50  33.33/ 33.33  27.65  0*041 033:033:033
- *  test/b              *   100/  100  66.67/ 66.67  17.56  0*000 066:079:077
+ *                 active      weight      hweight% inflt% dbt  delay usages%
+ *  test/a              *    50/   50  33.33/ 33.33  27.65   2  0*041 033:033:033
+ *  test/b              *   100/  100  66.67/ 66.67  17.56   0  0*000 066:079:077
  *
  * - per       : Timer period
  * - cur_per   : Internal wall and device vtime clock
@@ -1784,28 +1784,39 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq,
                           struct bio *bio)
 {
        struct ioc_gq *iocg = blkg_to_iocg(bio->bi_blkg);
+       struct ioc *ioc = iocg->ioc;
        sector_t bio_end = bio_end_sector(bio);
+       struct ioc_now now;
        u32 hw_inuse;
        u64 abs_cost, cost;
 
-       /* add iff the existing request has cost assigned */
-       if (!rq->bio || !rq->bio->bi_iocost_cost)
+       /* bypass if disabled or for root cgroup */
+       if (!ioc->enabled || !iocg->level)
                return;
 
        abs_cost = calc_vtime_cost(bio, iocg, true);
        if (!abs_cost)
                return;
 
+       ioc_now(ioc, &now);
+       current_hweight(iocg, NULL, &hw_inuse);
+       cost = abs_cost_to_cost(abs_cost, hw_inuse);
+
        /* update cursor if backmerging into the request at the cursor */
        if (blk_rq_pos(rq) < bio_end &&
            blk_rq_pos(rq) + blk_rq_sectors(rq) == iocg->cursor)
                iocg->cursor = bio_end;
 
-       current_hweight(iocg, NULL, &hw_inuse);
-       cost = div64_u64(abs_cost * HWEIGHT_WHOLE, hw_inuse);
-       bio->bi_iocost_cost = cost;
-
-       atomic64_add(cost, &iocg->vtime);
+       /*
+        * Charge if there's enough vtime budget and the existing request
+        * has cost assigned.  Otherwise, account it as debt.  See debt
+        * handling in ioc_rqos_throttle() for details.
+        */
+       if (rq->bio && rq->bio->bi_iocost_cost &&
+           time_before_eq64(atomic64_read(&iocg->vtime) + cost, now.vnow))
+               iocg_commit_bio(iocg, bio, cost);
+       else
+               atomic64_add(abs_cost, &iocg->abs_vdebt);
 }
 
 static void ioc_rqos_done_bio(struct rq_qos *rqos, struct bio *bio)