md/md-llbitmap: track target reshape geometry fields

Track llbitmap bookkeeping for the target reshape geometry while keeping
a single live bitmap instance.

Add the reshape geometry fields, refresh helper, and update the load and
resize paths to keep the target geometry in sync.

Tested-by: Mykola Marzhan <mykola@meshstor.io>
Link: https://patch.msgid.link/20260802195038.164272-17-yukuai@kernel.org
Signed-off-by: Yu Kuai <yukuai@fygo.io>
This commit is contained in:
Yu Kuai
2026-08-03 03:50:25 +08:00
parent 1cbc6ea5fa
commit 3a92c67aef

View File

@@ -289,6 +289,9 @@ struct llbitmap {
unsigned long chunks;
/* total number of sectors tracked by current bitmap geometry */
sector_t sync_size;
unsigned long reshape_chunksize;
unsigned long reshape_chunks;
sector_t reshape_sync_size;
unsigned long last_end_sync;
/*
* time in seconds that dirty bits will be cleared if the page is not
@@ -430,6 +433,39 @@ static void llbitmap_calculate_chunks(struct mddev *mddev, sector_t blocks,
}
}
static bool llbitmap_reshaping(struct llbitmap *llbitmap)
{
return llbitmap->mddev->reshape_position != MaxSector;
}
static sector_t llbitmap_personality_sync_size(struct llbitmap *llbitmap,
bool previous)
{
struct mddev *mddev = llbitmap->mddev;
if (!llbitmap_reshaping(llbitmap) || !mddev->private || !mddev->pers ||
!mddev->pers->bitmap_sync_size)
return llbitmap->sync_size;
return mddev->pers->bitmap_sync_size(mddev, previous);
}
static void llbitmap_refresh_reshape(struct llbitmap *llbitmap)
{
unsigned long old_chunks = DIV_ROUND_UP_SECTOR_T(llbitmap->sync_size,
llbitmap->chunksize);
sector_t blocks = llbitmap_personality_sync_size(llbitmap, false);
unsigned long chunksize = llbitmap->chunksize;
unsigned long chunks = DIV_ROUND_UP_SECTOR_T(blocks, chunksize);
llbitmap->reshape_sync_size = blocks;
llbitmap->reshape_chunksize = chunksize;
llbitmap->reshape_chunks = chunks;
llbitmap_calculate_chunks(llbitmap->mddev, blocks,
&llbitmap->reshape_chunksize,
&llbitmap->reshape_chunks);
llbitmap->chunks = max(old_chunks, llbitmap->reshape_chunks);
}
static enum llbitmap_state llbitmap_read(struct llbitmap *llbitmap, loff_t pos)
{
unsigned int idx;
@@ -1030,6 +1066,7 @@ static int llbitmap_init(struct llbitmap *llbitmap)
llbitmap->chunksize = chunksize;
llbitmap->chunks = chunks;
llbitmap->sync_size = blocks;
llbitmap_refresh_reshape(llbitmap);
mddev->bitmap_info.daemon_sleep = DEFAULT_DAEMON_SLEEP;
ret = llbitmap_alloc_pages(llbitmap);
@@ -1146,6 +1183,7 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap)
llbitmap->chunks = DIV_ROUND_UP_SECTOR_T(sync_size, chunksize);
llbitmap->chunkshift = ffz(~chunksize);
llbitmap->sync_size = sync_size;
llbitmap_refresh_reshape(llbitmap);
ret = llbitmap_alloc_pages(llbitmap);
out_put_page:
@@ -1302,6 +1340,9 @@ static int llbitmap_resize(struct mddev *mddev, sector_t blocks, int chunksize)
goto out;
if (reshape) {
llbitmap->reshape_sync_size = blocks;
llbitmap->reshape_chunksize = bitmap_chunksize;
llbitmap->reshape_chunks = chunks;
llbitmap->chunks = max(old_chunks, chunks);
} else {
if (blocks < old_blocks && chunks < old_chunks)
@@ -1310,6 +1351,7 @@ static int llbitmap_resize(struct mddev *mddev, sector_t blocks, int chunksize)
mddev->bitmap_info.chunksize = bitmap_chunksize;
llbitmap->chunks = chunks;
llbitmap->sync_size = blocks;
llbitmap_refresh_reshape(llbitmap);
llbitmap_update_sb(llbitmap);
}
__llbitmap_flush(mddev);