From d55b04e63abe643324e6c4392931d3e4f4e3b885 Mon Sep 17 00:00:00 2001 From: PiliLily Date: Sun, 23 Aug 2026 15:05:49 +0800 Subject: [PATCH] blk-throttle: only use seq_printf() in tg_prfill_limit() Upstream commit: d3a3a086ad57b8c05340c0a4ac97b26ea55a1119 tg_prfill_limit() formats the idle and latency limits into two 26-byte on-stack buffers with snprintf() before printing them with seq_printf(). " idle=" plus a full 64-bit unsigned long needs up to 27 bytes including the trailing NUL, and " latency=%lu" needs up to 30, so a limit written with many digits is silently truncated when it is read back. A W=1 build with CONFIG_WERROR=y reports both calls as format-truncation errors. Upstream commit d3a3a086ad57 ("blk-throttle: Only use seq_printf() in tg_prfill_limit()") solved this by dropping the on-stack buffers and printing each limit directly with seq_printf(). Follow the same approach instead of enlarging the buffers. OpenCloudOS adds the combined rwbps/rwiops limits on top of the upstream rbps/wbps/riops/wiops set, so the conversion is adapted to keep printing rbps, wbps, rwbps, riops, wiops and rwiops in the existing order and spacing. The cgroup text ABI is unchanged, including the "max" rendering of U64_MAX/UINT_MAX limits and the idle/latency fields on io.low. Verified by booting pre-fix and fixed kernels in QEMU and reading io.max/io.low back: normal values, 20-digit values and unlimited limits all print with identical field names, order and spacing, and the large idle/latency values truncated by the old buffers are now printed in full. make W=1 block/blk-throttle.o with CONFIG_WERROR=y also passes after the change. Conflict: adapted for the downstream rwbps/rwiops fields Signed-off-by: John Garry Signed-off-by: PiliLily --- block/blk-throttle.c | 69 +++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 143f40fc80d2..40c4ab01249e 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c @@ -1688,11 +1688,8 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd, { struct throtl_grp *tg = pd_to_tg(pd); const char *dname = blkg_dev_name(pd->blkg); - char bufs[6][21] = { "max", "max", "max", "max", "max", "max" }; u64 bps_dft; unsigned int iops_dft; - char idle_time[26] = ""; - char latency_time[26] = ""; if (!dname) return 0; @@ -1716,41 +1713,53 @@ static u64 tg_prfill_limit(struct seq_file *sf, struct blkg_policy_data *pd, tg->latency_target_conf == DFL_LATENCY_TARGET))) return 0; - if (tg->bps_conf[READ][off] != U64_MAX) - snprintf(bufs[0], sizeof(bufs[0]), "%llu", - tg->bps_conf[READ][off]); - if (tg->bps_conf[WRITE][off] != U64_MAX) - snprintf(bufs[1], sizeof(bufs[1]), "%llu", - tg->bps_conf[WRITE][off]); - if (tg->bps_conf[READWRITE][off] != U64_MAX) - snprintf(bufs[2], sizeof(bufs[2]), "%llu", - tg->bps_conf[READWRITE][off]); - if (tg->iops_conf[READ][off] != UINT_MAX) - snprintf(bufs[3], sizeof(bufs[3]), "%u", - tg->iops_conf[READ][off]); - if (tg->iops_conf[WRITE][off] != UINT_MAX) - snprintf(bufs[4], sizeof(bufs[4]), "%u", - tg->iops_conf[WRITE][off]); - if (tg->iops_conf[READWRITE][off] != UINT_MAX) - snprintf(bufs[5], sizeof(bufs[5]), "%u", - tg->iops_conf[READWRITE][off]); + seq_printf(sf, "%s", dname); + + if (tg->bps_conf[READ][off] == U64_MAX) + seq_printf(sf, " rbps=max"); + else + seq_printf(sf, " rbps=%llu", tg->bps_conf[READ][off]); + + if (tg->bps_conf[WRITE][off] == U64_MAX) + seq_printf(sf, " wbps=max"); + else + seq_printf(sf, " wbps=%llu", tg->bps_conf[WRITE][off]); + + if (tg->bps_conf[READWRITE][off] == U64_MAX) + seq_printf(sf, " rwbps=max"); + else + seq_printf(sf, " rwbps=%llu", tg->bps_conf[READWRITE][off]); + + if (tg->iops_conf[READ][off] == UINT_MAX) + seq_printf(sf, " riops=max"); + else + seq_printf(sf, " riops=%u", tg->iops_conf[READ][off]); + + if (tg->iops_conf[WRITE][off] == UINT_MAX) + seq_printf(sf, " wiops=max"); + else + seq_printf(sf, " wiops=%u", tg->iops_conf[WRITE][off]); + + if (tg->iops_conf[READWRITE][off] == UINT_MAX) + seq_printf(sf, " rwiops=max"); + else + seq_printf(sf, " rwiops=%u", tg->iops_conf[READWRITE][off]); + if (off == LIMIT_LOW) { if (tg->idletime_threshold_conf == ULONG_MAX) - strcpy(idle_time, " idle=max"); + seq_printf(sf, " idle=max"); else - snprintf(idle_time, sizeof(idle_time), " idle=%lu", - tg->idletime_threshold_conf); + seq_printf(sf, " idle=%lu", + tg->idletime_threshold_conf); if (tg->latency_target_conf == ULONG_MAX) - strcpy(latency_time, " latency=max"); + seq_printf(sf, " latency=max"); else - snprintf(latency_time, sizeof(latency_time), - " latency=%lu", tg->latency_target_conf); + seq_printf(sf, " latency=%lu", + tg->latency_target_conf); } - seq_printf(sf, "%s rbps=%s wbps=%s rwbps=%s riops=%s wiops=%s rwiops=%s%s%s\n", - dname, bufs[0], bufs[1], bufs[2], bufs[3], bufs[4], bufs[5], - idle_time, latency_time); + seq_printf(sf, "\n"); return 0; } -- Gitee