* [PATCH 1/4] block/blk-stat: drain per-cpu callback stats over possible CPUs
2026-07-20 9:37 [PATCH 0/4] block: drain per-cpu latency stats over possible CPUs Tao Cui
@ 2026-07-20 9:37 ` Tao Cui
2026-07-20 9:37 ` [PATCH 2/4] block/blk-iolatency: account per-cpu latency " Tao Cui
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-20 9:37 UTC (permalink / raw)
To: Jens Axboe
Cc: Tejun Heo, Josef Bacik, Omar Sandoval, Bart Van Assche, Yu Kuai,
Chaitanya Kulkarni, Hannes Reinecke, Ming Lei, Damien Le Moal,
Nilay Shroff, linux-block, cgroups, linux-kernel, cui.tao, cuitao
From: Tao Cui <cuitao@kylinos.cn>
blk_stat_timer_fn() sums and resets a callback's per-cpu buckets using
for_each_online_cpu(). A CPU that goes offline with pending samples is
skipped, so its samples are neither accumulated into the window nor
cleared; they sit in the bucket until the CPU comes back online, at
which point the stale values are flushed into whatever window is then
running.
This silently corrupts the latency picture that consumers (notably
writeback throttling via wbt, and blk-mq latency tracking) base
decisions on around CPU hotplug: under-counting while the CPU is
offline, then a burst of stale data on re-online.
Fixes: 34dbad5d26e2 ("blk-stat: convert to callback-based statistics reporting")
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
block/blk-stat.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/blk-stat.c b/block/blk-stat.c
index de126e1ea5ac..d57c2fc6bf06 100644
--- a/block/blk-stat.c
+++ b/block/blk-stat.c
@@ -83,7 +83,7 @@ static void blk_stat_timer_fn(struct timer_list *t)
for (bucket = 0; bucket < cb->buckets; bucket++)
blk_rq_stat_init(&cb->stat[bucket]);
- for_each_online_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct blk_rq_stat *cpu_stat;
cpu_stat = per_cpu_ptr(cb->cpu_stat, cpu);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/4] block/blk-iolatency: account per-cpu latency stats over possible CPUs
2026-07-20 9:37 [PATCH 0/4] block: drain per-cpu latency stats over possible CPUs Tao Cui
2026-07-20 9:37 ` [PATCH 1/4] block/blk-stat: drain per-cpu callback " Tao Cui
@ 2026-07-20 9:37 ` Tao Cui
2026-07-20 9:37 ` [PATCH 3/4] block/blk-iocost: collect " Tao Cui
2026-07-20 9:37 ` [PATCH 4/4] block/kyber-iosched: flush per-cpu latency buckets " Tao Cui
3 siblings, 0 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-20 9:37 UTC (permalink / raw)
To: Jens Axboe
Cc: Tejun Heo, Josef Bacik, Omar Sandoval, Bart Van Assche, Yu Kuai,
Chaitanya Kulkarni, Hannes Reinecke, Ming Lei, Damien Le Moal,
Nilay Shroff, linux-block, cgroups, linux-kernel, cui.tao, cuitao
From: Tao Cui <cuitao@kylinos.cn>
iolatency_check_latencies() and iolatency_ssd_stat() iterate a blkg's
per-cpu latency stats with for_each_online_cpu(). When a CPU that has
accumulated io.latency samples goes offline, its bucket is skipped: the
check loop (which also resets) neither sums nor clears it, and the show
path under-reports. On re-online the stranded samples are flushed into
a later check window, which can trigger a spurious throttle/scale
adjustment.
Fixes: d70675121546 ("block: introduce blk-iolatency io controller")
Fixes: 1fa2840e56f9 ("blk-iolatency: use a percentile approache for ssd's")
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
block/blk-iolatency.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c
index 1cc33aa0b669..d6c401d6174c 100644
--- a/block/blk-iolatency.c
+++ b/block/blk-iolatency.c
@@ -523,7 +523,7 @@ static void iolatency_check_latencies(struct iolatency_grp *iolat, u64 now)
latency_stat_init(iolat, &stat);
preempt_disable();
- for_each_online_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct latency_stat *s;
s = per_cpu_ptr(iolat->stats, cpu);
latency_stat_sum(iolat, &stat, s);
@@ -924,7 +924,7 @@ static void iolatency_ssd_stat(struct iolatency_grp *iolat, struct seq_file *s)
latency_stat_init(iolat, &stat);
preempt_disable();
- for_each_online_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct latency_stat *s;
s = per_cpu_ptr(iolat->stats, cpu);
latency_stat_sum(iolat, &stat, s);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/4] block/blk-iocost: collect per-cpu latency stats over possible CPUs
2026-07-20 9:37 [PATCH 0/4] block: drain per-cpu latency stats over possible CPUs Tao Cui
2026-07-20 9:37 ` [PATCH 1/4] block/blk-stat: drain per-cpu callback " Tao Cui
2026-07-20 9:37 ` [PATCH 2/4] block/blk-iolatency: account per-cpu latency " Tao Cui
@ 2026-07-20 9:37 ` Tao Cui
2026-07-20 9:37 ` [PATCH 4/4] block/kyber-iosched: flush per-cpu latency buckets " Tao Cui
3 siblings, 0 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-20 9:37 UTC (permalink / raw)
To: Jens Axboe
Cc: Tejun Heo, Josef Bacik, Omar Sandoval, Bart Van Assche, Yu Kuai,
Chaitanya Kulkarni, Hannes Reinecke, Ming Lei, Damien Le Moal,
Nilay Shroff, linux-block, cgroups, linux-kernel, cui.tao, cuitao
From: Tao Cui <cuitao@kylinos.cn>
ioc_lat_stat() walks ioc->pcpu_stat with for_each_online_cpu() to
compute missed-ppm and rq_wait deltas. An offlined CPU is skipped, so
its delta is dropped from the period and its last_* watermark is not
advanced; on re-online the next collection sees a delta spanning the
whole offline interval, corrupting the latency/vrate picture.
Fixes: 7caa47151ab2 ("blkcg: implement blk-iocost")
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
block/blk-iocost.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 8b2aeba2e1e3..b60625613e09 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -1592,7 +1592,7 @@ static void ioc_lat_stat(struct ioc *ioc, u32 *missed_ppm_ar, u32 *rq_wait_pct_p
u64 rq_wait_ns = 0;
int cpu, rw;
- for_each_online_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct ioc_pcpu_stat *stat = per_cpu_ptr(ioc->pcpu_stat, cpu);
u64 this_rq_wait_ns;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 4/4] block/kyber-iosched: flush per-cpu latency buckets over possible CPUs
2026-07-20 9:37 [PATCH 0/4] block: drain per-cpu latency stats over possible CPUs Tao Cui
` (2 preceding siblings ...)
2026-07-20 9:37 ` [PATCH 3/4] block/blk-iocost: collect " Tao Cui
@ 2026-07-20 9:37 ` Tao Cui
3 siblings, 0 replies; 5+ messages in thread
From: Tao Cui @ 2026-07-20 9:37 UTC (permalink / raw)
To: Jens Axboe
Cc: Tejun Heo, Josef Bacik, Omar Sandoval, Bart Van Assche, Yu Kuai,
Chaitanya Kulkarni, Hannes Reinecke, Ming Lei, Damien Le Moal,
Nilay Shroff, linux-block, cgroups, linux-kernel, cui.tao, cuitao
From: Tao Cui <cuitao@kylinos.cn>
kyber_timer_fn() sums the per-cpu latency histograms with
for_each_online_cpu(). A CPU that goes offline mid-interval leaves its
bucket un-flushed; the samples are lost from the current decision and
re-appear (stale) when the CPU is onlined again.
Fixes: 6e25cb01ea20 ("kyber: implement improved heuristics")
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
block/kyber-iosched.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/block/kyber-iosched.c b/block/kyber-iosched.c
index 971818bcdc9d..2ee552ab8135 100644
--- a/block/kyber-iosched.c
+++ b/block/kyber-iosched.c
@@ -275,7 +275,7 @@ static void kyber_timer_fn(struct timer_list *t)
bool bad = false;
/* Sum all of the per-cpu latency histograms. */
- for_each_online_cpu(cpu) {
+ for_each_possible_cpu(cpu) {
struct kyber_cpu_latency *cpu_latency;
cpu_latency = per_cpu_ptr(kqd->cpu_latency, cpu);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread