[PATCH 3/3] blkcg: account cgroup v1 I/O before checking throttle activation

From: Zhe Liu

Date: Tue Nov 10 2026 - 05:49:19 EST


Commit a3166c51702b ("blk-throttle: delay initialization until
configuration") made throttle policy activation conditional on
configuring a limit. However, blk_should_throtl() returns before
updating the v1 counters when the policy is inactive. A cgroup v1
workload that only monitors I/O therefore gets no accounting until a
limit is configured on the device.

Now that the counters belong to the blkg, move their updates out of
blk_should_throtl() and account immediately before blk_throtl_bio() in
both submit_bio_noacct() and bio_submit_split_bioset(). This records I/O
even when the throttle policy has never been activated.

Keep BIO_CGROUP_ACCT byte deduplication and count each split-remainder
submission as an I/O. Throttle worker dispatch continues to use the
nocheck submission path, avoiding a second accounting update. The
inline hierarchy check skips v1 accounting on cgroup v2.

Fixes: a3166c51702b ("blk-throttle: delay initialization until configuration")
Signed-off-by: Zhe Liu <liuzhe1@xxxxxxxxxx>
---
block/blk-core.c | 1 +
block/blk-merge.c | 9 ++++++---
block/blk-throttle.h | 1 -
3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 8836c7028568..013d806efb43 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -924,6 +924,7 @@ void submit_bio_noacct(struct bio *bio)
goto not_supported;
}

+ blkcg_account_v1_bio(bio);
if (blk_throtl_bio(bio))
return;
submit_bio_noacct_nocheck(bio, false);
diff --git a/block/blk-merge.c b/block/blk-merge.c
index 501ddc01c449..8bc996002646 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -131,10 +131,13 @@ struct bio *bio_submit_split_bioset(struct bio *bio, unsigned int split_sectors,
trace_block_split(split, bio->bi_iter.bi_sector);
WARN_ON_ONCE(bio_zone_write_plugging(bio));

- if (should_fail_bio(bio))
+ if (should_fail_bio(bio)) {
bio_io_error(bio);
- else if (!blk_throtl_bio(bio))
- submit_bio_noacct_nocheck(bio, true);
+ } else {
+ blkcg_account_v1_bio(bio);
+ if (!blk_throtl_bio(bio))
+ submit_bio_noacct_nocheck(bio, true);
+ }

return split;
}
diff --git a/block/blk-throttle.h b/block/blk-throttle.h
index 02c08daf3dc3..73f0d4bbdc71 100644
--- a/block/blk-throttle.h
+++ b/block/blk-throttle.h
@@ -170,7 +170,6 @@ static inline bool blk_should_throtl(struct bio *bio)
return false;

tg = blkg_to_tg(bio->bi_blkg);
- blkcg_account_v1_bio(bio);

/* iops limit is always counted */
if (tg->has_rules_iops[rw])
--
2.25.1