linux/drivers/md/persistent-data
Ming-Hung Tsai 3995b25d00 dm array: fix cursor index when skipping across block boundaries
[ Upstream commit 0bb1968da2 ]

dm_array_cursor_skip() seeks to the target position by loading array
blocks iteratively until the specified number of entries to skip is
reached. When seeking across block boundaries, it uses
dm_array_cursor_next() to step into the next block.
dm_array_cursor_skip() must first move the cursor index to the end
of the current block; otherwise, the cursor position could incorrectly
remain in the same block, causing the actual number of skipped entries
to be much smaller than expected.

This bug affects cache resizing in v2 metadata and could lead to data
loss if the fast device is shrunk during the first-time resume. For
example:

1. create a cache metadata consists of 32768 blocks, with a dirty block
   assigned to the second bitmap block. cache_restore v1.0 is required.

cat <<EOF >> cmeta.xml
<superblock uuid="" block_size="64" nr_cache_blocks="32768" \
policy="smq" hint_width="4">
  <mappings>
    <mapping cache_block="32767" origin_block="0" dirty="true"/>
  </mappings>
</superblock>
EOF
dmsetup create cmeta --table "0 8192 linear /dev/sdc 0"
cache_restore -i cmeta.xml -o /dev/mapper/cmeta --metadata-version=2

2. bring up the cache while attempt to discard all the blocks belonging
   to the second bitmap block (block# 32576 to 32767). The last command
   is expected to fail, but it actually succeeds.

dmsetup create cdata --table "0 2084864 linear /dev/sdc 8192"
dmsetup create corig --table "0 65536 linear /dev/sdc 2105344"
dmsetup create cache --table "0 65536 cache /dev/mapper/cmeta \
/dev/mapper/cdata /dev/mapper/corig 64 2 metadata2 writeback smq \
2 migration_threshold 0"

In addition to the reproducer described above, this fix can be
verified using the "array_cursor/skip" tests in dm-unit:
  dm-unit run /pdata/array_cursor/skip/ --kernel-dir <KERNEL_DIR>

Signed-off-by: Ming-Hung Tsai <mtsai@redhat.com>
Fixes: 9b696229aa ("dm persistent data: add cursor skip functions to the cursor APIs")
Reviewed-by: Joe Thornber <thornber@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
History 2025-01-23 17:15:48 +01:00
..
dm-array.c dm array: fix cursor index when skipping across block boundaries 2025-01-23 17:15:48 +01:00
dm-array.h dm persistent data: add cursor skip functions to the cursor APIs 2017-02-16 13:12:50 -05:00
dm-bitset.c dm persistent data: add cursor skip functions to the cursor APIs 2017-02-16 13:12:50 -05:00
dm-bitset.h dm persistent data: add cursor skip functions to the cursor APIs 2017-02-16 13:12:50 -05:00
dm-block-manager.c dm thin metadata: Fix use-after-free in dm_bm_set_read_only 2020-09-02 13:38:40 -04:00
dm-block-manager.h dm block manager: remove an unused argument from dm_block_manager_create() 2017-04-27 17:08:41 -04:00
dm-btree-internal.h dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
dm-btree-remove.c dm btree remove: fix use after free in rebalance_children() 2021-12-22 09:32:36 +01:00
dm-btree-spine.c dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
dm-btree.c dm btree: add a defensive bounds check to insert_at() 2022-01-27 11:04:52 +01:00
dm-btree.h dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
dm-persistent-data-internal.h dm: add persistent data library 2011-10-31 20:19:11 +00:00
dm-space-map-common.c dm space map common: add bounds check to sm_ll_lookup_bitmap() 2022-01-27 11:04:53 +01:00
dm-space-map-common.h dm space map disk: cache a small number of index entries 2021-06-04 12:07:23 -04:00
dm-space-map-disk.c dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
dm-space-map-disk.h dm: add persistent data library 2011-10-31 20:19:11 +00:00
dm-space-map-metadata.c dm persistent data: fix memory allocation failure 2024-09-04 13:23:16 +02:00
dm-space-map-metadata.h dm thin: allow metadata space larger than supported to go unused 2014-02-27 11:49:08 -05:00
dm-space-map.h dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
dm-transaction-manager.c dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
dm-transaction-manager.h dm space maps: improve performance with inc/dec on ranges of blocks 2021-06-04 12:07:22 -04:00
Kconfig treewide: replace '---help---' in Kconfig files with 'help' 2020-06-14 01:57:21 +09:00
Makefile License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00