diff --git a/block/blk-iocost.c b/block/blk-iocost.c index a3b1f1c87b0eaf635a39862d6354ff7674bc821e..92180abc43e15140c20f67d5657b91f8f985bc70 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1716,8 +1716,8 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio, iocg = blkg_to_iocg(blkg); - /* bypass IOs if disabled or for root cgroup */ - if (!ioc->enabled || !iocg->level) + /* bypass IOs if disabled, still initializing, or for root cgroup */ + if (!ioc->enabled || !iocg || !iocg->level) return; /* always activate so that even 0 cost IOs get protected to some level */ @@ -1857,8 +1857,8 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq, rcu_read_unlock(); iocg = blkg_to_iocg(blkg); - /* bypass if disabled or for root cgroup */ - if (!ioc->enabled || !iocg->level) + /* bypass if disabled, still initializing, or for root cgroup */ + if (!ioc->enabled || !iocg || !iocg->level) return; abs_cost = calc_vtime_cost(bio, iocg, true); @@ -1997,6 +1997,12 @@ static int blk_iocost_init(struct request_queue *q) ioc_refresh_params(ioc, true); spin_unlock_irq(&ioc->lock); + /* + * rqos must be added before activation to allow iocg_pd_init() to + * lookup the ioc from q. This means that the rqos methods may get + * called before policy activation completion, can't assume that the + * target bio has an iocg associated and need to test for NULL iocg. + */ rq_qos_add(q, rqos); ret = blkcg_activate_policy(q, &blkcg_policy_iocost); if (ret) {