* [PATCH 0/2] blk-throttle: minor cleanups
@ 2026-07-14 10:30 Tao Cui
2026-07-14 10:30 ` [PATCH 1/2] blk-throttle: avoid ilog2(0) in calculate_bytes_allowed() Tao Cui
2026-07-14 10:30 ` [PATCH 2/2] blk-throttle: factor out limit field printing in tg_prfill_limit() Tao Cui
0 siblings, 2 replies; 4+ messages in thread
From: Tao Cui @ 2026-07-14 10:30 UTC (permalink / raw)
To: axboe, tj, josef; +Cc: cgroups, linux-block, linux-kernel, Tao Cui
From: Tao Cui <cuitao@kylinos.cn>
This short series collects two independent, behavior-preserving cleanups
to the blk-throttle policy.
Patch 1 reworks calculate_bytes_allowed() to short-circuit a zero
jiffy_elapsed explicitly, rather than relying on ilog2(0) == -1
(fls64(0) - 1) to skip the overflow guard. __tg_update_carryover()
reaches it with a zero elapsed time right after a slice starts.
Patch 2 factors the four identical rbps/wbps/riops/wiops print blocks
in tg_prfill_limit() into a small helper and drops two alias locals.
Neither changes behavior; the io.max seq_file output is unchanged. Built
and boot-tested in QEMU (cgroup v2 io.max read-back matches, throttled IO
completes without warning/oops).
Tao Cui (2):
blk-throttle: avoid ilog2(0) in calculate_bytes_allowed()
blk-throttle: factor out limit field printing in tg_prfill_limit()
block/blk-throttle.c | 52 ++++++++++++++++++++------------------------
1 file changed, 23 insertions(+), 29 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] blk-throttle: avoid ilog2(0) in calculate_bytes_allowed()
2026-07-14 10:30 [PATCH 0/2] blk-throttle: minor cleanups Tao Cui
@ 2026-07-14 10:30 ` Tao Cui
2026-07-14 11:32 ` David Laight
2026-07-14 10:30 ` [PATCH 2/2] blk-throttle: factor out limit field printing in tg_prfill_limit() Tao Cui
1 sibling, 1 reply; 4+ messages in thread
From: Tao Cui @ 2026-07-14 10:30 UTC (permalink / raw)
To: axboe, tj, josef; +Cc: cgroups, linux-block, linux-kernel, Tao Cui
From: Tao Cui <cuitao@kylinos.cn>
__tg_update_carryover() can call calculate_bytes_allowed() with a zero
jiffy_elapsed right after a slice starts. The overflow guard
if (ilog2(bps_limit) + ilog2(jiffy_elapsed) - ilog2(HZ) > 62)
relies on ilog2(0) == -1 (fls64(0) - 1) to stay below the threshold so
that the subsequent mul_u64_u64_div_u64(bps, 0, HZ) == 0 is reached.
That works, but the ilog2(0) dependency is non-obvious.
Add an explicit early return for jiffy_elapsed == 0, which is equivalent
(mul_u64_u64_div_u64(bps_limit, 0, HZ) == 0) and removes the reliance on
ilog2(0).
No behavior change.
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
block/blk-throttle.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index ffc3b70065d4..f37911abefdd 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -603,6 +603,10 @@ static unsigned int calculate_io_allowed(u32 iops_limit,
static u64 calculate_bytes_allowed(u64 bps_limit, unsigned long jiffy_elapsed)
{
+ /* 0 elapsed => 0 bytes allowed; also avoids ilog2(0) below. */
+ if (!jiffy_elapsed)
+ return 0;
+
/*
* Can result be wider than 64 bits?
* We check against 62, not 64, due to ilog2 truncation.
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] blk-throttle: factor out limit field printing in tg_prfill_limit()
2026-07-14 10:30 [PATCH 0/2] blk-throttle: minor cleanups Tao Cui
2026-07-14 10:30 ` [PATCH 1/2] blk-throttle: avoid ilog2(0) in calculate_bytes_allowed() Tao Cui
@ 2026-07-14 10:30 ` Tao Cui
1 sibling, 0 replies; 4+ messages in thread
From: Tao Cui @ 2026-07-14 10:30 UTC (permalink / raw)
To: axboe, tj, josef; +Cc: cgroups, linux-block, linux-kernel, Tao Cui
From: Tao Cui <cuitao@kylinos.cn>
The four rbps/wbps/riops/wiops blocks in tg_prfill_limit() are identical
apart from the key string and whether the limit is 64- or 32-bit. Factor
them into tg_prfill_limit_field() and drop the bps_dft / iops_dft alias
locals in favor of U64_MAX / UINT_MAX directly.
The io.max seq_file output is byte-for-byte unchanged.
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
block/blk-throttle.c | 48 ++++++++++++++++++--------------------------
1 file changed, 19 insertions(+), 29 deletions(-)
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index f37911abefdd..8f4563acbc16 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1489,47 +1489,37 @@ static struct cftype throtl_legacy_files[] = {
{ } /* terminate */
};
+static void tg_prfill_limit_field(struct seq_file *sf, const char *key,
+ u64 val, bool is_uint)
+{
+ u64 dflt = is_uint ? UINT_MAX : U64_MAX;
+
+ if (val == dflt)
+ seq_printf(sf, " %s=max", key);
+ else if (is_uint)
+ seq_printf(sf, " %s=%u", key, (unsigned int)val);
+ else
+ seq_printf(sf, " %s=%llu", key, val);
+}
+
static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd,
int off)
{
struct throtl_grp *tg = pd_to_tg(pd);
const char *dname = blkg_dev_name(pd->blkg);
- u64 bps_dft;
- unsigned int iops_dft;
if (!dname)
return 0;
- bps_dft = U64_MAX;
- iops_dft = UINT_MAX;
-
- if (tg->bps[READ] == bps_dft &&
- tg->bps[WRITE] == bps_dft &&
- tg->iops[READ] == iops_dft &&
- tg->iops[WRITE] == iops_dft)
+ if (tg->bps[READ] == U64_MAX && tg->bps[WRITE] == U64_MAX &&
+ tg->iops[READ] == UINT_MAX && tg->iops[WRITE] == UINT_MAX)
return 0;
seq_printf(sf, "%s", dname);
- if (tg->bps[READ] == U64_MAX)
- seq_printf(sf, " rbps=max");
- else
- seq_printf(sf, " rbps=%llu", tg->bps[READ]);
-
- if (tg->bps[WRITE] == U64_MAX)
- seq_printf(sf, " wbps=max");
- else
- seq_printf(sf, " wbps=%llu", tg->bps[WRITE]);
-
- if (tg->iops[READ] == UINT_MAX)
- seq_printf(sf, " riops=max");
- else
- seq_printf(sf, " riops=%u", tg->iops[READ]);
-
- if (tg->iops[WRITE] == UINT_MAX)
- seq_printf(sf, " wiops=max");
- else
- seq_printf(sf, " wiops=%u", tg->iops[WRITE]);
-
+ tg_prfill_limit_field(sf, "rbps", tg->bps[READ], false);
+ tg_prfill_limit_field(sf, "wbps", tg->bps[WRITE], false);
+ tg_prfill_limit_field(sf, "riops", tg->iops[READ], true);
+ tg_prfill_limit_field(sf, "wiops", tg->iops[WRITE], true);
seq_printf(sf, "\n");
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] blk-throttle: avoid ilog2(0) in calculate_bytes_allowed()
2026-07-14 10:30 ` [PATCH 1/2] blk-throttle: avoid ilog2(0) in calculate_bytes_allowed() Tao Cui
@ 2026-07-14 11:32 ` David Laight
0 siblings, 0 replies; 4+ messages in thread
From: David Laight @ 2026-07-14 11:32 UTC (permalink / raw)
To: Tao Cui; +Cc: axboe, tj, josef, cgroups, linux-block, linux-kernel, Tao Cui
On Tue, 14 Jul 2026 18:30:27 +0800
Tao Cui <cui.tao@linux.dev> wrote:
> From: Tao Cui <cuitao@kylinos.cn>
>
> __tg_update_carryover() can call calculate_bytes_allowed() with a zero
> jiffy_elapsed right after a slice starts. The overflow guard
>
> if (ilog2(bps_limit) + ilog2(jiffy_elapsed) - ilog2(HZ) > 62)
>
> relies on ilog2(0) == -1 (fls64(0) - 1) to stay below the threshold so
> that the subsequent mul_u64_u64_div_u64(bps, 0, HZ) == 0 is reached.
> That works, but the ilog2(0) dependency is non-obvious.
>
> Add an explicit early return for jiffy_elapsed == 0, which is equivalent
> (mul_u64_u64_div_u64(bps_limit, 0, HZ) == 0) and removes the reliance on
> ilog2(0).
>
> No behavior change.
There is a pending patch to make the x86-64 mul_u64_u64_div_u64()
return ~0ULL on overflow to match the generic code.
That would completely remove the requirement for the overflow guard.
I can't remember why it got lost (again).
There have been arguments about what should happen for divide by zero.
Personally I'd return ~0ULL and let the caller decide what that means,
but the generic mul_u64_u64_div_u64() goes to lengths to generate any
trap that a normal divide by zero would generate.
David
>
> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
> ---
> block/blk-throttle.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/block/blk-throttle.c b/block/blk-throttle.c
> index ffc3b70065d4..f37911abefdd 100644
> --- a/block/blk-throttle.c
> +++ b/block/blk-throttle.c
> @@ -603,6 +603,10 @@ static unsigned int calculate_io_allowed(u32 iops_limit,
>
> static u64 calculate_bytes_allowed(u64 bps_limit, unsigned long jiffy_elapsed)
> {
> + /* 0 elapsed => 0 bytes allowed; also avoids ilog2(0) below. */
> + if (!jiffy_elapsed)
> + return 0;
> +
> /*
> * Can result be wider than 64 bits?
> * We check against 62, not 64, due to ilog2 truncation.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-14 11:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 10:30 [PATCH 0/2] blk-throttle: minor cleanups Tao Cui
2026-07-14 10:30 ` [PATCH 1/2] blk-throttle: avoid ilog2(0) in calculate_bytes_allowed() Tao Cui
2026-07-14 11:32 ` David Laight
2026-07-14 10:30 ` [PATCH 2/2] blk-throttle: factor out limit field printing in tg_prfill_limit() Tao Cui
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.