diff options
| author | Yu Kuai <yukuai@fygo.io> | 2026-08-03 03:50:25 +0800 |
|---|---|---|
| committer | Yu Kuai <yukuai@fygo.io> | 2026-08-07 14:43:35 +0800 |
| commit | 3a92c67aef5aeb0ccf46cf291be87dac0485fd5f (patch) | |
| tree | 395c81a92a68c168260ee6a781a3465caeb48018 | |
| parent | 1cbc6ea5fa6527853803345cb6099917b77b0c61 (diff) | |
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>
| -rw-r--r-- | drivers/md/md-llbitmap.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c index c34accb9233a..421a9a4ebbae 100644 --- a/drivers/md/md-llbitmap.c +++ b/drivers/md/md-llbitmap.c @@ -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); |
