Re: [PATCH 0/4] block: drain per-cpu latency stats over possible CPUs
From: yu kuai
Date: Mon Aug 03 2026 - 01:31:20 EST
在 2026/7/20 17:37, Tao Cui 写道:
> From: Tao Cui <cuitao@xxxxxxxxxx>
>
> Several block-layer latency statistics accumulate samples in per-cpu
> buckets and drain them periodically -- in timer callbacks, or at each
> check / reporting site -- using for_each_online_cpu(). When a CPU that
> holds pending samples is taken offline, that bucket is skipped during
> the drain: the samples are neither accumulated into the current window
> nor, where the drain also resets, cleared. They sit in the bucket until
> the CPU is brought back online, at which point they are flushed into
> whatever window happens to be running.
>
> The effect cuts both ways and is harmful in each direction:
>
> - while the CPU is offline, its samples are under-counted, so
> throttle / latency / scheduling decisions derived from these stats
> miss the work that actually happened ("should have throttled, but
> didn't");
>
> - on re-online, a burst of stale samples lands in a later window and
> can spuriously trip a throttle or skew a vrate / latency estimate
> ("shouldn't throttle, but did").
>
> Fix: drain over for_each_possible_cpu() instead. The per-cpu areas are
> allocated for the full possible set, and the init paths already iterate
> it; an offline CPU has no concurrent writer, so reading and resetting
> its bucket is safe.
>
> Cost is bounded: the extra work is over offline buckets that have no
> writer and -- because each drain sums and resets -- hold a zeroed stat
> after the first post-offline drain. It amounts to O(possible - online)
> trivial per-cpu reads on a timer / check / show path, alongside the
> per-CPU stat work already done for online CPUs; on systems where all
> possible CPUs are online it is exactly zero.
>
> This is the same one-line mistake in four sites; each patch switches its
> drain loop from for_each_online_cpu() to for_each_possible_cpu():
>
> - block/blk-stat.c blk_stat_timer_fn() -- shared infrastructure
> that also feeds wbt and blk-mq latency
> - block/blk-iolatency.c iolatency_check_latencies() (throttle) and
> iolatency_ssd_stat() (io.stat reporting)
> - block/blk-iocost.c ioc_lat_stat() -- missed-ppm / rq_wait delta
> - block/kyber-iosched.c kyber_timer_fn() -- latency histogram flush
>
> blk-mq.c's for_each_online_cpu() at the hctx-has-online-cpu check is
> correct and left untouched -- it is not a statistics drain.
>
> Tao Cui (4):
> block/blk-stat: drain per-cpu callback stats over possible CPUs
> block/blk-iolatency: account per-cpu latency stats over possible CPUs
> block/blk-iocost: collect per-cpu latency stats over possible CPUs
> block/kyber-iosched: flush per-cpu latency buckets over possible CPUs
>
> block/blk-iocost.c | 2 +-
> block/blk-iolatency.c | 4 ++--
> block/blk-stat.c | 2 +-
> block/kyber-iosched.c | 2 +-
> 4 files changed, 5 insertions(+), 5 deletions(-)
>
> --
> 2.43.0'
For this set:
Reviewed-by: Yu Kuai <yukuai@xxxxxxx>
>
--
Thanks,
Kuai