Re: [PATCH] dm cache: fix demotion stats in passthrough mode
Benjamin Marzinski <[email protected]>
| Newsgroups | dev.linux.lists.dm-devel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Aug 18, 2026 at 06:05:47PM +0800, Ming-Hung Tsai wrote:
> The demotion counter is incremented per incoming write bio before the
> invalidation begins, causing the demotion count to exceed the actual
> number of cached blocks when multiple bios target the same cached
> block. Additionally, the counter is incremented unconditionally
> regardless of invalidation failure.
>
> Reproduce steps:
>
> 1. Create a cache device consisting of 512 cache entries
>
> modprobe brd rd_size=262144
> dmsetup create cmeta --table "0 8192 linear /dev/ram0 0"
> dmsetup create cdata --table "0 65536 linear /dev/ram0 8192"
> dmsetup create corig --table "0 65536 linear /dev/ram0 262144"
> dd if=/dev/zero of=/dev/mapper/cmeta bs=4k count=1 oflag=direct
> dmsetup create cache --table "0 65536 cache /dev/mapper/cmeta \
> /dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 writethrough smq 0"
>
> 2. Populate the cache, and record the number of cached blocks
>
> fio --name=populate --filename=/dev/mapper/cache --rw=randwrite --bs=4k \
> --direct=1 --ioengine=libaio --iodepth=32 --io_size=2048m
> nr_cached=$(dmsetup status cache | awk '{split($7, a, "/"); print a[1]}')
>
> 3. Reload the cache into passthrough mode
>
> dmsetup suspend cache
> dmsetup reload cache --table "0 65536 cache /dev/mapper/cmeta \
> /dev/mapper/cdata /dev/mapper/corig 128 2 metadata2 passthrough smq 0"
> dmsetup resume cache
>
> 4. Write to the passthrough cache with multiple jobs to trigger
> multiple bios hitting the same cached block.
>
> fio --filename=/dev/mapper/cache --name=test --rw=write --bs=4k \
> --direct=1 --ioengine=libaio --iodepth=32 --numjobs=4
>
> 5. Check if demoted matches cached block count. These numbers should
> match but may differ due to overcounting per bio.
>
> nr_demoted=$(dmsetup status cache | awk '{print $12}')
> echo "$nr_cached, $nr_demoted"
>
> Fix by moving the demotion counter increment into invalidate_complete(),
> gated on the success flag.
>
> Reported-by: Ben Marzinski <[email protected]>
> Fixes: b29d4986d0da ("dm cache: significant rework to leverage dm-bio-prison-v2")
> Signed-off-by: Ming-Hung Tsai <[email protected]>
Reviewed-by: Benjamin Marzinski <[email protected]>
> ---
> drivers/md/dm-cache-target.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
> index 097315a9bf0f..b79206816956 100644
> --- a/drivers/md/dm-cache-target.c
> +++ b/drivers/md/dm-cache-target.c
> @@ -1461,6 +1461,9 @@ static void invalidate_complete(struct dm_cache_migration *mg, bool success)
> struct bio_list bios;
> struct cache *cache = mg->cache;
>
> + if (success)
> + atomic_inc(&cache->stats.demotion);
> +
> bio_list_init(&bios);
> if (mg->cell) {
> if (dm_cell_unlock_v2(cache->prison, mg->cell, &bios))
> @@ -1732,7 +1735,6 @@ static int map_bio(struct cache *cache, struct bio *bio, dm_oblock_t block,
> if (passthrough_mode(cache)) {
> if (bio_data_dir(bio) == WRITE) {
> bio_drop_shared_lock(cache, bio);
> - atomic_inc(&cache->stats.demotion);
> invalidate_start(cache, cblock, block, bio);
> return DM_MAPIO_SUBMITTED;
> } else
> --
> 2.49.0