[Devel] [PATCH VZ10 v2 09/11] drivers/md/dm-stats: prepare for accounting data-less flushes
Andrey Zhadchenko
andrey.zhadchenko at virtuozzo.com
Mon Jul 27 19:32:52 MSK 2026
Flushes have always been invisible to dm-stats: they carry zero
sectors, so dm_stats_account_io() dropped them early. To later
support a flush latency histogram, teach the accounting path to let
them through:
- introduce the flush I/O class, set for REQ_PREFLUSH bios and
REQ_OP_FLUSH requests;
- since a data-less flush covers no sector range, account it to the
first step-sized area of the region, and only when some histogram of
the region subscribes to the flush class;
- keep the classic counters (ios, sectors, merges, ticks, in_flight
and the merge detection state) untouched by data-less flushes, so
the existing output does not change;
- only account flush completions: in-flight tracking is left to the
read/write counters.
https://virtuozzo.atlassian.net/browse/VSTOR-103846
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko at virtuozzo.com>
---
drivers/md/dm-stats.c | 39 ++++++++++++++++++++++++++++++++-------
1 file changed, 32 insertions(+), 7 deletions(-)
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index 9c2f290843bae..1899549748cc3 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -46,6 +46,7 @@ struct dm_stat_shared {
enum {
DM_STAT_CLASS_READ,
DM_STAT_CLASS_WRITE,
+ DM_STAT_CLASS_FLUSH,
DM_STAT_NR_CLASSES,
};
@@ -639,6 +640,9 @@ static unsigned int dm_stat_io_classes(blk_opf_t bi_opf, unsigned int bi_sectors
if (bi_sectors)
classes |= 1 << (op_is_write(bi_opf) ? DM_STAT_CLASS_WRITE :
DM_STAT_CLASS_READ);
+ if ((bi_opf & REQ_PREFLUSH) ||
+ (bi_opf & REQ_OP_MASK) == REQ_OP_FLUSH)
+ classes |= 1 << DM_STAT_CLASS_FLUSH;
return classes;
}
@@ -674,6 +678,7 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry,
struct dm_stat_shared *shared = &s->stat_shared[entry];
struct dm_stat_percpu *p;
int idx = op_is_write(bi_opf);
+ bool data = classes & DM_STAT_CLASSES_DATA;
/*
* For strict correctness we should use local_irq_save/restore
@@ -701,21 +706,26 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry,
if (!end) {
dm_stat_round(s, shared, p);
- atomic_inc(&shared->in_flight[idx]);
+ if (likely(data))
+ atomic_inc(&shared->in_flight[idx]);
} else {
unsigned long long duration;
unsigned int hmask = s->hist_mask[classes];
dm_stat_round(s, shared, p);
- atomic_dec(&shared->in_flight[idx]);
- p->sectors[idx] += len;
- p->ios[idx] += 1;
- p->merges[idx] += stats_aux->merged;
+ if (likely(data)) {
+ atomic_dec(&shared->in_flight[idx]);
+ p->sectors[idx] += len;
+ p->ios[idx] += 1;
+ p->merges[idx] += stats_aux->merged;
+ }
if (!(s->stat_flags & STAT_PRECISE_TIMESTAMPS)) {
- p->ticks[idx] += duration_jiffies;
+ if (likely(data))
+ p->ticks[idx] += duration_jiffies;
duration = jiffies_to_msecs(duration_jiffies);
} else {
- p->ticks[idx] += stats_aux->duration_ns;
+ if (likely(data))
+ p->ticks[idx] += stats_aux->duration_ns;
if ((s->stat_flags & STAT_HIST_TOTAL_LATENCY) &&
stats_aux->histogram_duration_ns)
duration = stats_aux->histogram_duration_ns;
@@ -742,6 +752,19 @@ static void __dm_stat_bio(struct dm_stat *s, blk_opf_t bi_opf,
sector_t rel_sector, offset, todo, fragment_len;
size_t entry;
+ if (unlikely(!(classes & DM_STAT_CLASSES_DATA))) {
+ /*
+ * A data-less flush covers no sector range, so region
+ * boundaries do not apply to it. Account it to the first
+ * entry of the region, and only if some histogram is
+ * interested in flushes.
+ */
+ if (end && s->hist_mask[classes])
+ dm_stat_for_entry(s, 0, bi_opf, classes, 0,
+ stats_aux, end, duration_jiffies);
+ return;
+ }
+
if (end_sector <= s->start || bi_sector >= s->end)
return;
if (unlikely(bi_sector < s->start)) {
@@ -791,6 +814,8 @@ void dm_stats_account_io(struct dm_stats *stats, blk_opf_t bi_opf,
end_sector = bi_sector + bi_sectors;
if (!end) {
+ if (unlikely(!(classes & DM_STAT_CLASSES_DATA)))
+ return;
/*
* A race condition can at worst result in the merged flag being
* misrepresented, so we don't have to disable preemption here.
--
2.43.5
More information about the Devel
mailing list