Reviewed-by: thornber@xxxxxxxxxx On Tue, Dec 3, 2024 at 5:50 PM Ming-Hung Tsai <mtsai@xxxxxxxxxx> wrote: > > 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" > > Signed-off-by: Ming-Hung Tsai <mtsai@xxxxxxxxxx> > Fixes: 9b696229aa7d ("dm persistent data: add cursor skip functions to the cursor APIs") > --- > drivers/md/persistent-data/dm-array.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c > index 1c3af717ee4f..b293da766fb1 100644 > --- a/drivers/md/persistent-data/dm-array.c > +++ b/drivers/md/persistent-data/dm-array.c > @@ -1004,6 +1004,7 @@ int dm_array_cursor_skip(struct dm_array_cursor *c, uint32_t count) > } > > count -= remaining; > + c->index += (remaining - 1); > r = dm_array_cursor_next(c); > > } while (!r); > -- > 2.47.0 >