From 4d179eeb91a0ffd1e9c86484e2febf4dcca1137f Mon Sep 17 00:00:00 2001 From: Xuewen Wang Date: Thu, 24 Sep 2026 09:45:12 +0800 Subject: [PATCH] ntfs: fix rollback after MFT bitmap run coalescing After the direct allocation attempt drops lcnbmp_lock, a concurrent free can let ntfs_cluster_alloc() return the adjacent cluster. The merged runlist then extends the existing last run, but rollback assumes a new run was added. A later metadata failure removes the old mapping and frees its first cluster. Record whether the allocated cluster is adjacent before merging the runlists. On rollback, shorten a coalesced run by one cluster and free only that cluster; remove the new run for a non-adjacent allocation. Suggested-by: Baolin Liu Reviewed-by: Baolin Liu Signed-off-by: Xuewen Wang Reviewed-by: Baolin Liu Signed-off-by: Namjae Jeon --- fs/ntfs/mft.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 88bac85d22bc..12666668a80e 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1428,6 +1428,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol) "Failed to allocate a cluster for the mft bitmap."); return PTR_ERR(rl2); } + /* The adjacent cluster may have become available while unlocked. */ + status.added_cluster = rl2->lcn == lcn; rl = ntfs_runlists_merge(&mftbmp_ni->runlist, rl2, 0, &new_rl_count); if (IS_ERR(rl)) { up_write(&mftbmp_ni->runlist.lock); @@ -1442,8 +1444,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol) } mftbmp_ni->runlist.rl = rl; mftbmp_ni->runlist.count = new_rl_count; - status.added_run = 1; - ntfs_debug("Adding one run to mft bitmap."); + status.added_run = !status.added_cluster; + ntfs_debug("Allocated one cluster for mft bitmap."); /* Find the last run in the new runlist. */ for (; rl[1].length; rl++) ;