]> Git Repo - linux.git/blob - drivers/md/dm-vdo/message-stats.c
Merge tag 'kbuild-v6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux.git] / drivers / md / dm-vdo / message-stats.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright 2023 Red Hat
4  */
5
6 #include "dedupe.h"
7 #include "logger.h"
8 #include "memory-alloc.h"
9 #include "message-stats.h"
10 #include "statistics.h"
11 #include "thread-device.h"
12 #include "vdo.h"
13
14 static void write_u64(char *prefix, u64 value, char *suffix, char **buf,
15                       unsigned int *maxlen)
16 {
17         int count;
18
19         count = scnprintf(*buf, *maxlen, "%s%llu%s", prefix == NULL ? "" : prefix,
20                           value, suffix == NULL ? "" : suffix);
21         *buf += count;
22         *maxlen -= count;
23 }
24
25 static void write_u32(char *prefix, u32 value, char *suffix, char **buf,
26                       unsigned int *maxlen)
27 {
28         int count;
29
30         count = scnprintf(*buf, *maxlen, "%s%u%s", prefix == NULL ? "" : prefix,
31                           value, suffix == NULL ? "" : suffix);
32         *buf += count;
33         *maxlen -= count;
34 }
35
36 static void write_block_count_t(char *prefix, block_count_t value, char *suffix,
37                                 char **buf, unsigned int *maxlen)
38 {
39         int count;
40
41         count = scnprintf(*buf, *maxlen, "%s%llu%s", prefix == NULL ? "" : prefix,
42                           value, suffix == NULL ? "" : suffix);
43         *buf += count;
44         *maxlen -= count;
45 }
46
47 static void write_string(char *prefix, char *value, char *suffix, char **buf,
48                          unsigned int *maxlen)
49 {
50         int count;
51
52         count = scnprintf(*buf, *maxlen, "%s%s%s", prefix == NULL ? "" : prefix,
53                           value, suffix == NULL ? "" : suffix);
54         *buf += count;
55         *maxlen -= count;
56 }
57
58 static void write_bool(char *prefix, bool value, char *suffix, char **buf,
59                        unsigned int *maxlen)
60 {
61         int count;
62
63         count = scnprintf(*buf, *maxlen, "%s%d%s", prefix == NULL ? "" : prefix,
64                           value, suffix == NULL ? "" : suffix);
65         *buf += count;
66         *maxlen -= count;
67 }
68
69 static void write_u8(char *prefix, u8 value, char *suffix, char **buf,
70                      unsigned int *maxlen)
71 {
72         int count;
73
74         count = scnprintf(*buf, *maxlen, "%s%u%s", prefix == NULL ? "" : prefix,
75                           value, suffix == NULL ? "" : suffix);
76         *buf += count;
77         *maxlen -= count;
78 }
79
80 static void write_block_allocator_statistics(char *prefix,
81                                              struct block_allocator_statistics *stats,
82                                              char *suffix, char **buf,
83                                              unsigned int *maxlen)
84 {
85         write_string(prefix, "{ ", NULL, buf, maxlen);
86         /* The total number of slabs from which blocks may be allocated */
87         write_u64("slabCount : ", stats->slab_count, ", ", buf, maxlen);
88         /* The total number of slabs from which blocks have ever been allocated */
89         write_u64("slabsOpened : ", stats->slabs_opened, ", ", buf, maxlen);
90         /* The number of times since loading that a slab has been re-opened */
91         write_u64("slabsReopened : ", stats->slabs_reopened, ", ", buf, maxlen);
92         write_string(NULL, "}", suffix, buf, maxlen);
93 }
94
95 static void write_commit_statistics(char *prefix, struct commit_statistics *stats,
96                                     char *suffix, char **buf, unsigned int *maxlen)
97 {
98         write_string(prefix, "{ ", NULL, buf, maxlen);
99         /* The total number of items on which processing has started */
100         write_u64("started : ", stats->started, ", ", buf, maxlen);
101         /* The total number of items for which a write operation has been issued */
102         write_u64("written : ", stats->written, ", ", buf, maxlen);
103         /* The total number of items for which a write operation has completed */
104         write_u64("committed : ", stats->committed, ", ", buf, maxlen);
105         write_string(NULL, "}", suffix, buf, maxlen);
106 }
107
108 static void write_recovery_journal_statistics(char *prefix,
109                                               struct recovery_journal_statistics *stats,
110                                               char *suffix, char **buf,
111                                               unsigned int *maxlen)
112 {
113         write_string(prefix, "{ ", NULL, buf, maxlen);
114         /* Number of times the on-disk journal was full */
115         write_u64("diskFull : ", stats->disk_full, ", ", buf, maxlen);
116         /* Number of times the recovery journal requested slab journal commits. */
117         write_u64("slabJournalCommitsRequested : ",
118                   stats->slab_journal_commits_requested, ", ", buf, maxlen);
119         /* Write/Commit totals for individual journal entries */
120         write_commit_statistics("entries : ", &stats->entries, ", ", buf, maxlen);
121         /* Write/Commit totals for journal blocks */
122         write_commit_statistics("blocks : ", &stats->blocks, ", ", buf, maxlen);
123         write_string(NULL, "}", suffix, buf, maxlen);
124 }
125
126 static void write_packer_statistics(char *prefix, struct packer_statistics *stats,
127                                     char *suffix, char **buf, unsigned int *maxlen)
128 {
129         write_string(prefix, "{ ", NULL, buf, maxlen);
130         /* Number of compressed data items written since startup */
131         write_u64("compressedFragmentsWritten : ",
132                   stats->compressed_fragments_written, ", ", buf, maxlen);
133         /* Number of blocks containing compressed items written since startup */
134         write_u64("compressedBlocksWritten : ",
135                   stats->compressed_blocks_written, ", ", buf, maxlen);
136         /* Number of VIOs that are pending in the packer */
137         write_u64("compressedFragmentsInPacker : ",
138                   stats->compressed_fragments_in_packer, ", ", buf, maxlen);
139         write_string(NULL, "}", suffix, buf, maxlen);
140 }
141
142 static void write_slab_journal_statistics(char *prefix,
143                                           struct slab_journal_statistics *stats,
144                                           char *suffix, char **buf, unsigned int *maxlen)
145 {
146         write_string(prefix, "{ ", NULL, buf, maxlen);
147         /* Number of times the on-disk journal was full */
148         write_u64("diskFullCount : ", stats->disk_full_count, ", ", buf, maxlen);
149         /* Number of times an entry was added over the flush threshold */
150         write_u64("flushCount : ", stats->flush_count, ", ", buf, maxlen);
151         /* Number of times an entry was added over the block threshold */
152         write_u64("blockedCount : ", stats->blocked_count, ", ", buf, maxlen);
153         /* Number of times a tail block was written */
154         write_u64("blocksWritten : ", stats->blocks_written, ", ", buf, maxlen);
155         /* Number of times we had to wait for the tail to write */
156         write_u64("tailBusyCount : ", stats->tail_busy_count, ", ", buf, maxlen);
157         write_string(NULL, "}", suffix, buf, maxlen);
158 }
159
160 static void write_slab_summary_statistics(char *prefix,
161                                           struct slab_summary_statistics *stats,
162                                           char *suffix, char **buf, unsigned int *maxlen)
163 {
164         write_string(prefix, "{ ", NULL, buf, maxlen);
165         /* Number of blocks written */
166         write_u64("blocksWritten : ", stats->blocks_written, ", ", buf, maxlen);
167         write_string(NULL, "}", suffix, buf, maxlen);
168 }
169
170 static void write_ref_counts_statistics(char *prefix, struct ref_counts_statistics *stats,
171                                         char *suffix, char **buf, unsigned int *maxlen)
172 {
173         write_string(prefix, "{ ", NULL, buf, maxlen);
174         /* Number of reference blocks written */
175         write_u64("blocksWritten : ", stats->blocks_written, ", ", buf, maxlen);
176         write_string(NULL, "}", suffix, buf, maxlen);
177 }
178
179 static void write_block_map_statistics(char *prefix, struct block_map_statistics *stats,
180                                        char *suffix, char **buf, unsigned int *maxlen)
181 {
182         write_string(prefix, "{ ", NULL, buf, maxlen);
183         /* number of dirty (resident) pages */
184         write_u32("dirtyPages : ", stats->dirty_pages, ", ", buf, maxlen);
185         /* number of clean (resident) pages */
186         write_u32("cleanPages : ", stats->clean_pages, ", ", buf, maxlen);
187         /* number of free pages */
188         write_u32("freePages : ", stats->free_pages, ", ", buf, maxlen);
189         /* number of pages in failed state */
190         write_u32("failedPages : ", stats->failed_pages, ", ", buf, maxlen);
191         /* number of pages incoming */
192         write_u32("incomingPages : ", stats->incoming_pages, ", ", buf, maxlen);
193         /* number of pages outgoing */
194         write_u32("outgoingPages : ", stats->outgoing_pages, ", ", buf, maxlen);
195         /* how many times free page not avail */
196         write_u32("cachePressure : ", stats->cache_pressure, ", ", buf, maxlen);
197         /* number of get_vdo_page() calls for read */
198         write_u64("readCount : ", stats->read_count, ", ", buf, maxlen);
199         /* number of get_vdo_page() calls for write */
200         write_u64("writeCount : ", stats->write_count, ", ", buf, maxlen);
201         /* number of times pages failed to read */
202         write_u64("failedReads : ", stats->failed_reads, ", ", buf, maxlen);
203         /* number of times pages failed to write */
204         write_u64("failedWrites : ", stats->failed_writes, ", ", buf, maxlen);
205         /* number of gets that are reclaimed */
206         write_u64("reclaimed : ", stats->reclaimed, ", ", buf, maxlen);
207         /* number of gets for outgoing pages */
208         write_u64("readOutgoing : ", stats->read_outgoing, ", ", buf, maxlen);
209         /* number of gets that were already there */
210         write_u64("foundInCache : ", stats->found_in_cache, ", ", buf, maxlen);
211         /* number of gets requiring discard */
212         write_u64("discardRequired : ", stats->discard_required, ", ", buf, maxlen);
213         /* number of gets enqueued for their page */
214         write_u64("waitForPage : ", stats->wait_for_page, ", ", buf, maxlen);
215         /* number of gets that have to fetch */
216         write_u64("fetchRequired : ", stats->fetch_required, ", ", buf, maxlen);
217         /* number of page fetches */
218         write_u64("pagesLoaded : ", stats->pages_loaded, ", ", buf, maxlen);
219         /* number of page saves */
220         write_u64("pagesSaved : ", stats->pages_saved, ", ", buf, maxlen);
221         /* the number of flushes issued */
222         write_u64("flushCount : ", stats->flush_count, ", ", buf, maxlen);
223         write_string(NULL, "}", suffix, buf, maxlen);
224 }
225
226 static void write_hash_lock_statistics(char *prefix, struct hash_lock_statistics *stats,
227                                        char *suffix, char **buf, unsigned int *maxlen)
228 {
229         write_string(prefix, "{ ", NULL, buf, maxlen);
230         /* Number of times the UDS advice proved correct */
231         write_u64("dedupeAdviceValid : ", stats->dedupe_advice_valid, ", ", buf, maxlen);
232         /* Number of times the UDS advice proved incorrect */
233         write_u64("dedupeAdviceStale : ", stats->dedupe_advice_stale, ", ", buf, maxlen);
234         /* Number of writes with the same data as another in-flight write */
235         write_u64("concurrentDataMatches : ", stats->concurrent_data_matches,
236                   ", ", buf, maxlen);
237         /* Number of writes whose hash collided with an in-flight write */
238         write_u64("concurrentHashCollisions : ",
239                   stats->concurrent_hash_collisions, ", ", buf, maxlen);
240         /* Current number of dedupe queries that are in flight */
241         write_u32("currDedupeQueries : ", stats->curr_dedupe_queries, ", ", buf, maxlen);
242         write_string(NULL, "}", suffix, buf, maxlen);
243 }
244
245 static void write_error_statistics(char *prefix, struct error_statistics *stats,
246                                    char *suffix, char **buf, unsigned int *maxlen)
247 {
248         write_string(prefix, "{ ", NULL, buf, maxlen);
249         /* number of times VDO got an invalid dedupe advice PBN from UDS */
250         write_u64("invalidAdvicePBNCount : ", stats->invalid_advice_pbn_count,
251                   ", ", buf, maxlen);
252         /* number of times a VIO completed with a VDO_NO_SPACE error */
253         write_u64("noSpaceErrorCount : ", stats->no_space_error_count, ", ",
254                   buf, maxlen);
255         /* number of times a VIO completed with a VDO_READ_ONLY error */
256         write_u64("readOnlyErrorCount : ", stats->read_only_error_count, ", ",
257                   buf, maxlen);
258         write_string(NULL, "}", suffix, buf, maxlen);
259 }
260
261 static void write_bio_stats(char *prefix, struct bio_stats *stats, char *suffix,
262                             char **buf, unsigned int *maxlen)
263 {
264         write_string(prefix, "{ ", NULL, buf, maxlen);
265         /* Number of REQ_OP_READ bios */
266         write_u64("read : ", stats->read, ", ", buf, maxlen);
267         /* Number of REQ_OP_WRITE bios with data */
268         write_u64("write : ", stats->write, ", ", buf, maxlen);
269         /* Number of bios tagged with REQ_PREFLUSH and containing no data */
270         write_u64("emptyFlush : ", stats->empty_flush, ", ", buf, maxlen);
271         /* Number of REQ_OP_DISCARD bios */
272         write_u64("discard : ", stats->discard, ", ", buf, maxlen);
273         /* Number of bios tagged with REQ_PREFLUSH */
274         write_u64("flush : ", stats->flush, ", ", buf, maxlen);
275         /* Number of bios tagged with REQ_FUA */
276         write_u64("fua : ", stats->fua, ", ", buf, maxlen);
277         write_string(NULL, "}", suffix, buf, maxlen);
278 }
279
280 static void write_memory_usage(char *prefix, struct memory_usage *stats, char *suffix,
281                                char **buf, unsigned int *maxlen)
282 {
283         write_string(prefix, "{ ", NULL, buf, maxlen);
284         /* Tracked bytes currently allocated. */
285         write_u64("bytesUsed : ", stats->bytes_used, ", ", buf, maxlen);
286         /* Maximum tracked bytes allocated. */
287         write_u64("peakBytesUsed : ", stats->peak_bytes_used, ", ", buf, maxlen);
288         write_string(NULL, "}", suffix, buf, maxlen);
289 }
290
291 static void write_index_statistics(char *prefix, struct index_statistics *stats,
292                                    char *suffix, char **buf, unsigned int *maxlen)
293 {
294         write_string(prefix, "{ ", NULL, buf, maxlen);
295         /* Number of records stored in the index */
296         write_u64("entriesIndexed : ", stats->entries_indexed, ", ", buf, maxlen);
297         /* Number of post calls that found an existing entry */
298         write_u64("postsFound : ", stats->posts_found, ", ", buf, maxlen);
299         /* Number of post calls that added a new entry */
300         write_u64("postsNotFound : ", stats->posts_not_found, ", ", buf, maxlen);
301         /* Number of query calls that found an existing entry */
302         write_u64("queriesFound : ", stats->queries_found, ", ", buf, maxlen);
303         /* Number of query calls that added a new entry */
304         write_u64("queriesNotFound : ", stats->queries_not_found, ", ", buf, maxlen);
305         /* Number of update calls that found an existing entry */
306         write_u64("updatesFound : ", stats->updates_found, ", ", buf, maxlen);
307         /* Number of update calls that added a new entry */
308         write_u64("updatesNotFound : ", stats->updates_not_found, ", ", buf, maxlen);
309         /* Number of entries discarded */
310         write_u64("entriesDiscarded : ", stats->entries_discarded, ", ", buf, maxlen);
311         write_string(NULL, "}", suffix, buf, maxlen);
312 }
313
314 static void write_vdo_statistics(char *prefix, struct vdo_statistics *stats, char *suffix,
315                                  char **buf, unsigned int *maxlen)
316 {
317         write_string(prefix, "{ ", NULL, buf, maxlen);
318         write_u32("version : ", stats->version, ", ", buf, maxlen);
319         /* Number of blocks used for data */
320         write_u64("dataBlocksUsed : ", stats->data_blocks_used, ", ", buf, maxlen);
321         /* Number of blocks used for VDO metadata */
322         write_u64("overheadBlocksUsed : ", stats->overhead_blocks_used, ", ",
323                   buf, maxlen);
324         /* Number of logical blocks that are currently mapped to physical blocks */
325         write_u64("logicalBlocksUsed : ", stats->logical_blocks_used, ", ", buf, maxlen);
326         /* number of physical blocks */
327         write_block_count_t("physicalBlocks : ", stats->physical_blocks, ", ",
328                             buf, maxlen);
329         /* number of logical blocks */
330         write_block_count_t("logicalBlocks : ", stats->logical_blocks, ", ",
331                             buf, maxlen);
332         /* Size of the block map page cache, in bytes */
333         write_u64("blockMapCacheSize : ", stats->block_map_cache_size, ", ",
334                   buf, maxlen);
335         /* The physical block size */
336         write_u64("blockSize : ", stats->block_size, ", ", buf, maxlen);
337         /* Number of times the VDO has successfully recovered */
338         write_u64("completeRecoveries : ", stats->complete_recoveries, ", ",
339                   buf, maxlen);
340         /* Number of times the VDO has recovered from read-only mode */
341         write_u64("readOnlyRecoveries : ", stats->read_only_recoveries, ", ",
342                   buf, maxlen);
343         /* String describing the operating mode of the VDO */
344         write_string("mode : ", stats->mode, ", ", buf, maxlen);
345         /* Whether the VDO is in recovery mode */
346         write_bool("inRecoveryMode : ", stats->in_recovery_mode, ", ", buf, maxlen);
347         /* What percentage of recovery mode work has been completed */
348         write_u8("recoveryPercentage : ", stats->recovery_percentage, ", ", buf, maxlen);
349         /* The statistics for the compressed block packer */
350         write_packer_statistics("packer : ", &stats->packer, ", ", buf, maxlen);
351         /* Counters for events in the block allocator */
352         write_block_allocator_statistics("allocator : ", &stats->allocator,
353                                          ", ", buf, maxlen);
354         /* Counters for events in the recovery journal */
355         write_recovery_journal_statistics("journal : ", &stats->journal, ", ",
356                                           buf, maxlen);
357         /* The statistics for the slab journals */
358         write_slab_journal_statistics("slabJournal : ", &stats->slab_journal,
359                                       ", ", buf, maxlen);
360         /* The statistics for the slab summary */
361         write_slab_summary_statistics("slabSummary : ", &stats->slab_summary,
362                                       ", ", buf, maxlen);
363         /* The statistics for the reference counts */
364         write_ref_counts_statistics("refCounts : ", &stats->ref_counts, ", ",
365                                     buf, maxlen);
366         /* The statistics for the block map */
367         write_block_map_statistics("blockMap : ", &stats->block_map, ", ", buf, maxlen);
368         /* The dedupe statistics from hash locks */
369         write_hash_lock_statistics("hashLock : ", &stats->hash_lock, ", ", buf, maxlen);
370         /* Counts of error conditions */
371         write_error_statistics("errors : ", &stats->errors, ", ", buf, maxlen);
372         /* The VDO instance */
373         write_u32("instance : ", stats->instance, ", ", buf, maxlen);
374         /* Current number of active VIOs */
375         write_u32("currentVIOsInProgress : ", stats->current_vios_in_progress,
376                   ", ", buf, maxlen);
377         /* Maximum number of active VIOs */
378         write_u32("maxVIOs : ", stats->max_vios, ", ", buf, maxlen);
379         /* Number of times the UDS index was too slow in responding */
380         write_u64("dedupeAdviceTimeouts : ", stats->dedupe_advice_timeouts,
381                   ", ", buf, maxlen);
382         /* Number of flush requests submitted to the storage device */
383         write_u64("flushOut : ", stats->flush_out, ", ", buf, maxlen);
384         /* Logical block size */
385         write_u64("logicalBlockSize : ", stats->logical_block_size, ", ", buf, maxlen);
386         /* Bios submitted into VDO from above */
387         write_bio_stats("biosIn : ", &stats->bios_in, ", ", buf, maxlen);
388         write_bio_stats("biosInPartial : ", &stats->bios_in_partial, ", ", buf, maxlen);
389         /* Bios submitted onward for user data */
390         write_bio_stats("biosOut : ", &stats->bios_out, ", ", buf, maxlen);
391         /* Bios submitted onward for metadata */
392         write_bio_stats("biosMeta : ", &stats->bios_meta, ", ", buf, maxlen);
393         write_bio_stats("biosJournal : ", &stats->bios_journal, ", ", buf, maxlen);
394         write_bio_stats("biosPageCache : ", &stats->bios_page_cache, ", ", buf, maxlen);
395         write_bio_stats("biosOutCompleted : ", &stats->bios_out_completed, ", ",
396                         buf, maxlen);
397         write_bio_stats("biosMetaCompleted : ", &stats->bios_meta_completed,
398                         ", ", buf, maxlen);
399         write_bio_stats("biosJournalCompleted : ",
400                         &stats->bios_journal_completed, ", ", buf, maxlen);
401         write_bio_stats("biosPageCacheCompleted : ",
402                         &stats->bios_page_cache_completed, ", ", buf, maxlen);
403         write_bio_stats("biosAcknowledged : ", &stats->bios_acknowledged, ", ",
404                         buf, maxlen);
405         write_bio_stats("biosAcknowledgedPartial : ",
406                         &stats->bios_acknowledged_partial, ", ", buf, maxlen);
407         /* Current number of bios in progress */
408         write_bio_stats("biosInProgress : ", &stats->bios_in_progress, ", ",
409                         buf, maxlen);
410         /* Memory usage stats. */
411         write_memory_usage("memoryUsage : ", &stats->memory_usage, ", ", buf, maxlen);
412         /* The statistics for the UDS index */
413         write_index_statistics("index : ", &stats->index, ", ", buf, maxlen);
414         write_string(NULL, "}", suffix, buf, maxlen);
415 }
416
417 int vdo_write_stats(struct vdo *vdo, char *buf, unsigned int maxlen)
418 {
419         struct vdo_statistics *stats;
420         int result;
421
422         result = vdo_allocate(1, struct vdo_statistics, __func__, &stats);
423         if (result != VDO_SUCCESS) {
424                 vdo_log_error("Cannot allocate memory to write VDO statistics");
425                 return result;
426         }
427
428         vdo_fetch_statistics(vdo, stats);
429         write_vdo_statistics(NULL, stats, NULL, &buf, &maxlen);
430         vdo_free(stats);
431         return VDO_SUCCESS;
432 }
This page took 0.062382 seconds and 4 git commands to generate.