[PATCH v5 09/29] md/md-llbitmap: stop daemon timer rearm on destroy

From: Yu Kuai

Date: Sun Aug 02 2026 - 15:55:14 EST


From: Yu Kuai <yukuai@xxxxxxx>

llbitmap_destroy() deletes pending_timer before flushing
md_llbitmap_io_wq. However, daemon_work can still be queued or running
after the timer has been deleted, and the daemon path can arm
pending_timer again when it finds dirty chunks that are not ready to
flush yet.

If that happens during teardown, pending_timer can remain armed after
llbitmap is freed and later dereference freed memory.

Add a BITMAP_SHUTDOWN bit to llbitmap->flags, set it before deleting
the timer, and make the timer and daemon paths stop queueing or rearming
work once teardown starts. Cancel daemon_work before flushing the shared
workqueue so no already queued daemon instance can race with the free.

BITMAP_SHUTDOWN is a runtime-only state. Mask it out when reading and
updating the llbitmap superblock so the shutdown state is never loaded
from disk or persisted to disk.

Fixes: 5ab829f1971d ("md/md-llbitmap: introduce new lockless bitmap")
Signed-off-by: Yu Kuai <yukuai@xxxxxxx>
---
drivers/md/md-bitmap.h | 1 +
drivers/md/md-llbitmap.c | 15 ++++++++++++---
2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/md/md-bitmap.h b/drivers/md/md-bitmap.h
index 214f623c7e79..890276d9c66e 100644
--- a/drivers/md/md-bitmap.h
+++ b/drivers/md/md-bitmap.h
@@ -29,6 +29,7 @@ enum bitmap_state {
BITMAP_FIRST_USE = 3, /* llbitmap is just created */
BITMAP_CLEAN = 4, /* llbitmap is created with assume_clean */
BITMAP_DAEMON_BUSY = 5, /* llbitmap daemon is not finished after daemon_sleep */
+ BITMAP_SHUTDOWN = 6, /* llbitmap is being destroyed */
BITMAP_HOSTENDIAN =15,
};

diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index af80a630bd21..3ec5b5985d48 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
@@ -789,6 +789,7 @@ static enum llbitmap_state llbitmap_state_machine(struct llbitmap *llbitmap,
if (state == BitNeedSync || state == BitNeedSyncUnwritten)
need_resync = !mddev->degraded;
else if (state == BitDirty &&
+ !test_bit(BITMAP_SHUTDOWN, &llbitmap->flags) &&
!timer_pending(&llbitmap->pending_timer))
mod_timer(&llbitmap->pending_timer,
jiffies + mddev->bitmap_info.daemon_sleep * HZ);
@@ -981,7 +982,7 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap)
else
mddev->bitmap_info.space = mddev->bitmap_info.default_space;
}
- llbitmap->flags = le32_to_cpu(sb->state);
+ llbitmap->flags = le32_to_cpu(sb->state) & ~BIT(BITMAP_SHUTDOWN);
if (test_and_clear_bit(BITMAP_FIRST_USE, &llbitmap->flags)) {
ret = llbitmap_init(llbitmap);
goto out_put_page;
@@ -1037,6 +1038,9 @@ static void llbitmap_pending_timer_fn(struct timer_list *pending_timer)
struct llbitmap *llbitmap =
container_of(pending_timer, struct llbitmap, pending_timer);

+ if (test_bit(BITMAP_SHUTDOWN, &llbitmap->flags))
+ return;
+
if (work_busy(&llbitmap->daemon_work)) {
pr_warn("md/llbitmap: %s daemon_work not finished in %lu seconds\n",
mdname(llbitmap->mddev),
@@ -1057,6 +1061,9 @@ static void md_llbitmap_daemon_fn(struct work_struct *work)
bool restart;
int idx;

+ if (test_bit(BITMAP_SHUTDOWN, &llbitmap->flags))
+ return;
+
if (llbitmap->mddev->degraded)
return;
retry:
@@ -1096,7 +1103,7 @@ static void md_llbitmap_daemon_fn(struct work_struct *work)
goto retry;

/* If some page is dirty but not expired, setup timer again */
- if (restart)
+ if (restart && !test_bit(BITMAP_SHUTDOWN, &llbitmap->flags))
mod_timer(&llbitmap->pending_timer,
jiffies + llbitmap->mddev->bitmap_info.daemon_sleep * HZ);
}
@@ -1179,7 +1186,9 @@ static void llbitmap_destroy(struct mddev *mddev)

mutex_lock(&mddev->bitmap_info.mutex);

+ set_bit(BITMAP_SHUTDOWN, &llbitmap->flags);
timer_delete_sync(&llbitmap->pending_timer);
+ cancel_work_sync(&llbitmap->daemon_work);
flush_workqueue(md_llbitmap_io_wq);
flush_workqueue(md_llbitmap_unplug_wq);

@@ -1523,7 +1532,7 @@ static void llbitmap_update_sb(void *data)

sb = kmap_local_page(sb_page);
sb->events = cpu_to_le64(mddev->events);
- sb->state = cpu_to_le32(llbitmap->flags);
+ sb->state = cpu_to_le32(llbitmap->flags & ~BIT(BITMAP_SHUTDOWN));
sb->chunksize = cpu_to_le32(llbitmap->chunksize);
sb->sync_size = cpu_to_le64(mddev->resync_max_sectors);
sb->events_cleared = cpu_to_le64(llbitmap->events_cleared);
--
2.51.0