Re: [RFC PATCH v1 1/3] blk-cgroup: add helpers for bio cgroup state
Jan Kara <[email protected]> Tue, 4 Aug 2026 12:52:16 +0200
| Newsgroups | dev.linux.lists.dm-devel,dev.linux.lists.gfs2,dev.linux.lists.nvdimm,dev.linux.lists.virtualization,org.kernel.vger.cgroups,org.kernel.vger.linux-bcache,org.kernel.vger.linux-block,org.kernel.vger.linux-doc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel,org.kernel.vger.linux-raid |
|---|---|
| Message-ID | <prx5s4rwbgoeh7wtgyo7vwydh5iwqn6qc2utamowirsplspfmp@e3eteq5xwuyf> |
On Tue 04-08-26 14:53:11, Yu Kuai wrote: > From: Yu Kuai <[email protected]> > > blk-cgroup users open-code bio->bi_blkg throughout the policy and > accounting paths. Some users need the blkg itself, while others > immediately dereference it to get the associated blkcg. The bio release > paths also open-code the CONFIG_BLK_CGROUP guarded blkg reference drop > and field clear. > > Add bio_blkg(), bio_blkcg() and bio_clear_blkg() helpers. Convert the > read-side users to use the accessors, and use bio_clear_blkg() from > bio_uninit() and bio_endio() so the release path no longer needs to know > about CONFIG_BLK_CGROUP. Keep the direct bio->bi_blkg stores in the > association and initialization paths, as those paths still assign the > stored association. > > This keeps the current behavior unchanged while preparing for changing > what cgroup state a bio stores internally. > > Signed-off-by: Yu Kuai <[email protected]> Mostly looks good. Just I think bio_blkcg() should gracefully handle the case where bio->bi_blkg is NULL (and return NULL in that case). That way you can also get rid of somewhat odd pattern: if (!bio_blkg(bio)) return ...; do something with bio_blkcg(bio) You can then just check bio_blkcg(bio) directly which is much more obvious. Honza > --- > block/bfq-cgroup.c | 4 ++-- > block/bio.c | 14 ++------------ > block/blk-cgroup-fc-appid.c | 11 +++++++++-- > block/blk-cgroup.c | 19 ++++++++++--------- > block/blk-cgroup.h | 19 ++++++++++++++++++- > block/blk-iocost.c | 6 +++--- > block/blk-iolatency.c | 6 +++--- > block/blk-ioprio.c | 2 +- > block/blk-throttle.c | 2 +- > block/blk-throttle.h | 2 +- > include/linux/bio.h | 10 ++++++++++ > 11 files changed, 60 insertions(+), 35 deletions(-) > > diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c > index e82ff03bda02..7e65fe6844ee 100644 > --- a/block/bfq-cgroup.c > +++ b/block/bfq-cgroup.c > @@ -363,7 +363,7 @@ void bfqg_and_blkg_put(struct bfq_group *bfqg) > > void bfqg_stats_update_legacy_io(struct request_queue *q, struct request *rq) > { > - struct bfq_group *bfqg = blkg_to_bfqg(rq->bio->bi_blkg); > + struct bfq_group *bfqg = blkg_to_bfqg(bio_blkg(rq->bio)); > > if (!bfqg) > return; > @@ -606,7 +606,7 @@ static void bfq_link_bfqg(struct bfq_data *bfqd, struct bfq_group *bfqg) > > struct bfq_group *bfq_bio_bfqg(struct bfq_data *bfqd, struct bio *bio) > { > - struct blkcg_gq *blkg = bio->bi_blkg; > + struct blkcg_gq *blkg = bio_blkg(bio); > struct bfq_group *bfqg; > > while (blkg) { > diff --git a/block/bio.c b/block/bio.c > index 6a2f6fc3413e..c207b248edba 100644 > --- a/block/bio.c > +++ b/block/bio.c > @@ -179,12 +179,7 @@ static inline gfp_t try_alloc_gfp(gfp_t gfp) > > void bio_uninit(struct bio *bio) > { > -#ifdef CONFIG_BLK_CGROUP > - if (bio->bi_blkg) { > - blkg_put(bio->bi_blkg); > - bio->bi_blkg = NULL; > - } > -#endif > + bio_clear_blkg(bio); > if (bio_integrity(bio)) > bio_integrity_free(bio); > > @@ -1803,17 +1798,12 @@ void bio_endio(struct bio *bio) > goto again; > } > > -#ifdef CONFIG_BLK_CGROUP > /* > * Release cgroup info. We shouldn't have to do this here, but quite > * a few callers of bio_init fail to call bio_uninit, so we cover up > * for that here at least for now. > */ > - if (bio->bi_blkg) { > - blkg_put(bio->bi_blkg); > - bio->bi_blkg = NULL; > - } > -#endif > + bio_clear_blkg(bio); > > if (bio->bi_end_io) > bio->bi_end_io(bio); > diff --git a/block/blk-cgroup-fc-appid.c b/block/blk-cgroup-fc-appid.c > index 3ec21333f393..b2e16e9a7a6c 100644 > --- a/block/blk-cgroup-fc-appid.c > +++ b/block/blk-cgroup-fc-appid.c > @@ -50,8 +50,15 @@ EXPORT_SYMBOL_GPL(blkcg_set_fc_appid); > */ > char *blkcg_get_fc_appid(struct bio *bio) > { > - if (!bio->bi_blkg || bio->bi_blkg->blkcg->fc_app_id[0] == '\0') > + struct blkcg *blkcg; > + > + if (!bio_blkg(bio)) > return NULL; > - return bio->bi_blkg->blkcg->fc_app_id; > + > + blkcg = bio_blkcg(bio); > + if (blkcg->fc_app_id[0] == '\0') > + return NULL; > + > + return blkcg->fc_app_id; > } > EXPORT_SYMBOL_GPL(blkcg_get_fc_appid); > diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c > index 354637f3b158..753a3bdd0e8c 100644 > --- a/block/blk-cgroup.c > +++ b/block/blk-cgroup.c > @@ -239,7 +239,7 @@ static void blkg_async_bio_workfn(struct work_struct *work) > */ > void blkcg_punt_bio_submit(struct bio *bio) > { > - struct blkcg_gq *blkg = bio->bi_blkg; > + struct blkcg_gq *blkg = bio_blkg(bio); > > if (blkg->parent) { > spin_lock(&blkg->async_bio_lock); > @@ -275,9 +275,9 @@ subsys_initcall(blkcg_punt_bio_init); > */ > struct cgroup_subsys_state *bio_blkcg_css(struct bio *bio) > { > - if (!bio || !bio->bi_blkg) > + if (!bio || !bio_blkg(bio)) > return NULL; > - return &bio->bi_blkg->blkcg->css; > + return &bio_blkcg(bio)->css; > } > EXPORT_SYMBOL_GPL(bio_blkcg_css); > > @@ -2118,8 +2118,8 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio, > void bio_associate_blkg_from_css(struct bio *bio, > struct cgroup_subsys_state *css) > { > - if (bio->bi_blkg) > - blkg_put(bio->bi_blkg); > + if (bio_blkg(bio)) > + blkg_put(bio_blkg(bio)); > > if (css && css->parent) { > bio->bi_blkg = blkg_tryget_closest(bio, css); > @@ -2146,7 +2146,7 @@ void bio_associate_blkg(struct bio *bio) > if (blk_op_is_passthrough(bio->bi_opf)) > return; > > - if (bio->bi_blkg) { > + if (bio_blkg(bio)) { > css = bio_blkcg_css(bio); > bio_associate_blkg_from_css(bio, css); > } else { > @@ -2170,7 +2170,7 @@ EXPORT_SYMBOL_GPL(bio_associate_blkg); > */ > void bio_clone_blkg_association(struct bio *dst, struct bio *src) > { > - if (src->bi_blkg) > + if (bio_blkg(src)) > bio_associate_blkg_from_css(dst, bio_blkcg_css(src)); > } > EXPORT_SYMBOL_GPL(bio_clone_blkg_association); > @@ -2186,7 +2186,8 @@ static int blk_cgroup_io_type(struct bio *bio) > > void blk_cgroup_bio_start(struct bio *bio) > { > - struct blkcg *blkcg = bio->bi_blkg->blkcg; > + struct blkcg_gq *blkg = bio_blkg(bio); > + struct blkcg *blkcg = bio_blkcg(bio); > int rwd = blk_cgroup_io_type(bio), cpu; > struct blkg_iostat_set *bis; > unsigned long flags; > @@ -2199,7 +2200,7 @@ void blk_cgroup_bio_start(struct bio *bio) > return; > > cpu = get_cpu(); > - bis = per_cpu_ptr(bio->bi_blkg->iostat_cpu, cpu); > + bis = per_cpu_ptr(blkg->iostat_cpu, cpu); > flags = u64_stats_update_begin_irqsave(&bis->sync); > > /* > diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h > index 615390f751aa..1e80b0a73233 100644 > --- a/block/blk-cgroup.h > +++ b/block/blk-cgroup.h > @@ -124,6 +124,11 @@ static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) > return css ? container_of(css, struct blkcg, css) : NULL; > } > > +static inline struct blkcg *bio_blkcg(struct bio *bio) > +{ > + return bio_blkg(bio)->blkcg; > +} > + > /* > * A blkcg_gq (blkg) is association between a block cgroup (blkcg) and a > * request_queue (q). This is used by blkcg policies which need to track > @@ -343,6 +348,16 @@ static inline void blkg_put(struct blkcg_gq *blkg) > percpu_ref_put(&blkg->refcnt); > } > > +static inline void bio_clear_blkg(struct bio *bio) > +{ > + struct blkcg_gq *blkg = bio_blkg(bio); > + > + if (blkg) { > + blkg_put(blkg); > + bio->bi_blkg = NULL; > + } > +} > + > /** > * blkg_for_each_descendant_pre - pre-order walk of a blkg's descendants > * @d_blkg: loop cursor pointing to the current descendant > @@ -455,7 +470,7 @@ static inline void blkcg_clear_delay(struct blkcg_gq *blkg) > */ > static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) > { > - return rq->bio->bi_blkg == bio->bi_blkg && > + return bio_blkg(rq->bio) == bio_blkg(bio) && > bio_issue_as_root_blkg(rq->bio) == bio_issue_as_root_blkg(bio); > } > > @@ -481,6 +496,7 @@ struct blkcg_policy { > struct blkcg { > }; > > +static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; } > static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; } > static inline void blkg_init_queue(struct request_queue *q) { } > static inline int blkcg_init_disk(struct gendisk *disk) { return 0; } > @@ -497,6 +513,7 @@ static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg, > static inline struct blkcg_gq *pd_to_blkg(struct blkg_policy_data *pd) { return NULL; } > static inline void blkg_get(struct blkcg_gq *blkg) { } > static inline void blkg_put(struct blkcg_gq *blkg) { } > +static inline void bio_clear_blkg(struct bio *bio) { } > static inline void blk_cgroup_bio_start(struct bio *bio) { } > static inline bool blk_cgroup_mergeable(struct request *rq, struct bio *bio) { return true; } > > diff --git a/block/blk-iocost.c b/block/blk-iocost.c > index 8b2aeba2e1e3..d4470476bcd0 100644 > --- a/block/blk-iocost.c > +++ b/block/blk-iocost.c > @@ -2686,7 +2686,7 @@ iocg_handle_over_budget(struct rq_qos *rqos, struct ioc_gq *iocg, > > static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio) > { > - struct blkcg_gq *blkg = bio->bi_blkg; > + struct blkcg_gq *blkg = bio_blkg(bio); > struct ioc *ioc = rqos_to_ioc(rqos); > struct ioc_gq *iocg = blkg_to_iocg(blkg); > struct ioc_now now; > @@ -2775,7 +2775,7 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio) > 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_gq *iocg = blkg_to_iocg(bio_blkg(bio)); > struct ioc *ioc = rqos_to_ioc(rqos); > sector_t bio_end = bio_end_sector(bio); > struct ioc_now now; > @@ -2833,7 +2833,7 @@ static void ioc_rqos_merge(struct rq_qos *rqos, struct request *rq, > > static void ioc_rqos_done_bio(struct rq_qos *rqos, struct bio *bio) > { > - struct ioc_gq *iocg = blkg_to_iocg(bio->bi_blkg); > + struct ioc_gq *iocg = blkg_to_iocg(bio_blkg(bio)); > > if (iocg && bio->bi_iocost_cost) > atomic64_add(bio->bi_iocost_cost, &iocg->done_vtime); > diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c > index cef02b6c5fa9..c0d8d5f6bdba 100644 > --- a/block/blk-iolatency.c > +++ b/block/blk-iolatency.c > @@ -463,7 +463,7 @@ static void check_scale_change(struct iolatency_grp *iolat) > static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio) > { > struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos); > - struct blkcg_gq *blkg = bio->bi_blkg; > + struct blkcg_gq *blkg = bio_blkg(bio); > bool issue_as_root = bio_issue_as_root_blkg(bio); > > if (!blkiolat->enabled) > @@ -590,11 +590,11 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio) > bool issue_as_root = bio_issue_as_root_blkg(bio); > int inflight = 0; > > - blkg = bio->bi_blkg; > + blkg = bio_blkg(bio); > if (!blkg || !bio_flagged(bio, BIO_QOS_THROTTLED)) > return; > > - iolat = blkg_to_lat(bio->bi_blkg); > + iolat = blkg_to_lat(blkg); > if (!iolat) > return; > > diff --git a/block/blk-ioprio.c b/block/blk-ioprio.c > index 8fa8bca35062..5e3f8e49550d 100644 > --- a/block/blk-ioprio.c > +++ b/block/blk-ioprio.c > @@ -132,7 +132,7 @@ static struct blkcg_policy ioprio_policy = { > > void blkcg_set_ioprio(struct bio *bio) > { > - struct ioprio_blkcg *blkcg = blkcg_to_ioprio_blkcg(bio->bi_blkg->blkcg); > + struct ioprio_blkcg *blkcg = blkcg_to_ioprio_blkcg(bio_blkcg(bio)); > u16 prio; > > if (!blkcg || blkcg->prio_policy == POLICY_NO_CHANGE) > diff --git a/block/blk-throttle.c b/block/blk-throttle.c > index ffc3b70065d4..3828c3857900 100644 > --- a/block/blk-throttle.c > +++ b/block/blk-throttle.c > @@ -1792,7 +1792,7 @@ static bool tg_within_limit(struct throtl_grp *tg, struct bio *bio, bool rw) > bool __blk_throtl_bio(struct bio *bio) > { > struct request_queue *q = bdev_get_queue(bio->bi_bdev); > - struct blkcg_gq *blkg = bio->bi_blkg; > + struct blkcg_gq *blkg = bio_blkg(bio); > struct throtl_qnode *qn = NULL; > struct throtl_grp *tg = blkg_to_tg(blkg); > struct throtl_service_queue *sq; > diff --git a/block/blk-throttle.h b/block/blk-throttle.h > index 9d7a42c039a1..609a126c7ccb 100644 > --- a/block/blk-throttle.h > +++ b/block/blk-throttle.h > @@ -173,7 +173,7 @@ static inline bool blk_should_throtl(struct bio *bio) > if (!blk_throtl_activated(bio->bi_bdev->bd_queue)) > return false; > > - tg = blkg_to_tg(bio->bi_blkg); > + tg = blkg_to_tg(bio_blkg(bio)); > if (!cgroup_subsys_on_dfl(io_cgrp_subsys)) { > if (!bio_flagged(bio, BIO_CGROUP_ACCT)) { > bio_set_flag(bio, BIO_CGROUP_ACCT); > diff --git a/include/linux/bio.h b/include/linux/bio.h > index 8f33f717b14f..dc4baa3602b7 100644 > --- a/include/linux/bio.h > +++ b/include/linux/bio.h > @@ -503,12 +503,22 @@ static inline void bio_release_pages(struct bio *bio, bool mark_dirty) > disk_devt((bio)->bi_bdev->bd_disk) > > #ifdef CONFIG_BLK_CGROUP > +static inline struct blkcg_gq *bio_blkg(struct bio *bio) > +{ > + return bio->bi_blkg; > +} > + > void bio_associate_blkg(struct bio *bio); > void bio_associate_blkg_from_css(struct bio *bio, > struct cgroup_subsys_state *css); > void bio_clone_blkg_association(struct bio *dst, struct bio *src); > void blkcg_punt_bio_submit(struct bio *bio); > #else /* CONFIG_BLK_CGROUP */ > +static inline struct blkcg_gq *bio_blkg(struct bio *bio) > +{ > + return NULL; > +} > + > static inline void bio_associate_blkg(struct bio *bio) { } > static inline void bio_associate_blkg_from_css(struct bio *bio, > struct cgroup_subsys_state *css) > -- > 2.51.0 > -- Jan Kara <[email protected]> SUSE Labs, CR