This patch adds 10 counters for various events and exports them in the status line. It also adds a message "clear_stats" that resets the counters. Signed-off-by: Mikulas Patocka <mpatocka@xxxxxxxxxx> --- Documentation/admin-guide/device-mapper/writecache.rst | 16 ++++ drivers/md/dm-writecache.c | 56 ++++++++++++++++- 2 files changed, 67 insertions(+), 5 deletions(-) Index: linux-2.6/drivers/md/dm-writecache.c =================================================================== --- linux-2.6.orig/drivers/md/dm-writecache.c 2021-07-26 18:46:19.000000000 +0200 +++ linux-2.6/drivers/md/dm-writecache.c 2021-07-27 15:29:19.000000000 +0200 @@ -206,6 +206,19 @@ struct dm_writecache { struct bio_set bio_set; mempool_t copy_pool; + + struct { + unsigned long long reads; + unsigned long long read_hits; + unsigned long long writes; + unsigned long long write_hits_uncommitted; + unsigned long long write_hits_committed; + unsigned long long writes_around; + unsigned long long writes_allocate; + unsigned long long writes_blocked_on_freelist; + unsigned long long flushes; + unsigned long long discards; + } stats; }; #define WB_LIST_INLINE 16 @@ -1157,6 +1170,18 @@ static int process_cleaner_mesg(unsigned return 0; } +static int process_clear_stats_mesg(unsigned argc, char **argv, struct dm_writecache *wc) +{ + if (argc != 1) + return -EINVAL; + + wc_lock(wc); + memset(&wc->stats, 0, sizeof wc->stats); + wc_unlock(wc); + + return 0; +} + static int writecache_message(struct dm_target *ti, unsigned argc, char **argv, char *result, unsigned maxlen) { @@ -1169,6 +1194,8 @@ static int writecache_message(struct dm_ r = process_flush_on_suspend_mesg(argc, argv, wc); else if (!strcasecmp(argv[0], "cleaner")) r = process_cleaner_mesg(argc, argv, wc); + else if (!strcasecmp(argv[0], "clear_stats")) + r = process_clear_stats_mesg(argc, argv, wc); else DMERR("unrecognised message received: %s", argv[0]); @@ -1321,8 +1348,10 @@ static enum wc_map_op writecache_map_rea struct wc_entry *e; read_next_block: + wc->stats.reads++; e = writecache_find_entry(wc, bio->bi_iter.bi_sector, WFE_RETURN_FOLLOWING); if (e && read_original_sector(wc, e) == bio->bi_iter.bi_sector) { + wc->stats.read_hits++; if (WC_MODE_PMEM(wc)) { bio_copy_block(wc, bio, memory_data(wc, e)); if (bio->bi_iter.bi_size) @@ -1401,14 +1430,17 @@ static enum wc_map_op writecache_map_wri do { bool found_entry = false; bool search_used = false; + wc->stats.writes++; if (writecache_has_error(wc)) return WC_MAP_ERROR; e = writecache_find_entry(wc, bio->bi_iter.bi_sector, 0); if (e) { if (!writecache_entry_is_committed(wc, e)) { + wc->stats.write_hits_uncommitted++; search_used = true; goto bio_copy; } + wc->stats.write_hits_committed++; if (!WC_MODE_PMEM(wc) && !e->write_in_progress) { wc->overwrote_committed = true; search_used = true; @@ -1424,15 +1456,18 @@ static enum wc_map_op writecache_map_wri if (unlikely(!e)) { if (!WC_MODE_PMEM(wc) && !found_entry) { direct_write: + wc->stats.writes_around++; e = writecache_find_entry(wc, bio->bi_iter.bi_sector, WFE_RETURN_FOLLOWING); return writecache_map_remap_origin(wc, bio, e); } + wc->stats.writes_blocked_on_freelist++; writecache_wait_on_freelist(wc); continue; } write_original_sector_seq_count(wc, e, bio->bi_iter.bi_sector, wc->seq_count); writecache_insert_entry(wc, e); wc->uncommitted_blocks++; + wc->stats.writes_allocate++; bio_copy: if (WC_MODE_PMEM(wc)) bio_copy_block(wc, bio, memory_data(wc, e)); @@ -1454,6 +1489,7 @@ static enum wc_map_op writecache_map_flu return WC_MAP_ERROR; if (WC_MODE_PMEM(wc)) { + wc->stats.flushes++; writecache_flush(wc); if (writecache_has_error(wc)) return WC_MAP_ERROR; @@ -1464,12 +1500,15 @@ static enum wc_map_op writecache_map_flu /* SSD: */ if (dm_bio_get_target_bio_nr(bio)) return WC_MAP_REMAP_ORIGIN; + wc->stats.flushes++; writecache_offload_bio(wc, bio); return WC_MAP_RETURN; } static enum wc_map_op writecache_map_discard(struct dm_writecache *wc, struct bio *bio) { + wc->stats.discards++; + if (writecache_has_error(wc)) return WC_MAP_ERROR; @@ -2616,9 +2655,20 @@ static void writecache_status(struct dm_ switch (type) { case STATUSTYPE_INFO: - DMEMIT("%ld %llu %llu %llu", writecache_has_error(wc), + DMEMIT("%ld %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", + writecache_has_error(wc), (unsigned long long)wc->n_blocks, (unsigned long long)wc->freelist_size, - (unsigned long long)wc->writeback_size); + (unsigned long long)wc->writeback_size, + wc->stats.reads, + wc->stats.read_hits, + wc->stats.writes, + wc->stats.write_hits_uncommitted, + wc->stats.write_hits_committed, + wc->stats.writes_around, + wc->stats.writes_allocate, + wc->stats.writes_blocked_on_freelist, + wc->stats.flushes, + wc->stats.discards); break; case STATUSTYPE_TABLE: DMEMIT("%c %s %s %u ", WC_MODE_PMEM(wc) ? 'p' : 's', @@ -2676,7 +2726,7 @@ static void writecache_status(struct dm_ static struct target_type writecache_target = { .name = "writecache", - .version = {1, 5, 0}, + .version = {1, 6, 0}, .module = THIS_MODULE, .ctr = writecache_ctr, .dtr = writecache_dtr, Index: linux-2.6/Documentation/admin-guide/device-mapper/writecache.rst =================================================================== --- linux-2.6.orig/Documentation/admin-guide/device-mapper/writecache.rst 2021-07-12 15:29:03.000000000 +0200 +++ linux-2.6/Documentation/admin-guide/device-mapper/writecache.rst 2021-07-27 12:11:05.000000000 +0200 @@ -78,13 +78,23 @@ Status: 2. the number of blocks 3. the number of free blocks 4. the number of blocks under writeback +5. the number of read requests +6. the number of read requests that hit the cache +7. the number of write requests +8. the number of write requests that hit uncommitted block +9. the number of write requests that hit committed block +10. the number of write requests that bypass the cache +11. the number of write requests that are allocated in the cache +12. the number of write requests that are blocked on the freelist +13. the number of flush requests +14. the number of discard requests Messages: flush - flush the cache device. The message returns successfully + Flush the cache device. The message returns successfully if the cache device was flushed without an error flush_on_suspend - flush the cache device on next suspend. Use this message + Flush the cache device on next suspend. Use this message when you are going to remove the cache device. The proper sequence for removing the cache device is: @@ -98,3 +108,5 @@ Messages: 6. the cache device is now inactive and it can be deleted cleaner See above "cleaner" constructor documentation. + clear_stats + Clear the statistics that are reported on the status line -- dm-devel mailing list dm-devel@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/dm-devel