From: liubaolin <liubaolin12138@163.com>
To: Shengzhuo Wei <me@cherr.cc>, Namjae Jeon <linkinjeon@kernel.org>,
Hyunchul Lee <hyc.lee@gmail.com>
Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-fsdevel@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH] ntfs: wait for bitmap folio writeback before modifying it
Date: Thu, 29 Oct 2026 10:07:29 +0800 [thread overview]
Message-ID: <374bf856-f880-4fa2-abec-c4b2a063bf57@163.com> (raw)
In-Reply-To: <20261029-b4-ntfs-bitmap-writeback-wait-v1-1-e2ba711b2dbf@cherr.cc>
在 2026/10/29 04:09, Shengzhuo Wei 写道:
> The bitmap update paths lock their page cache folios before modifying
> them, but the folio lock does not wait for an earlier writeback to
> finish. Writeback can release the lock while its BIO still references
> the folio memory, allowing bitmap changes to race with that I/O and
> expose partially updated contents to it.
>
> Wait for existing writeback after locking each folio and before
> modifying it in ntfs_attr_set(), both bitmap setter loops, the cluster
> allocator, and the two MFT bitmap allocation paths. This follows the
> lock-then-wait sequence already used for attribute and raw MFT updates.
>
> Cc: stable@vger.kernel.org
> Signed-off-by: Shengzhuo Wei <me@cherr.cc>
> ---
> The change was checked against the existing attribute/MFT waits and
> the iomap completion path. Existing base and patched NTFS object
> builds with W=1 and CONFIG_WERROR=y complete without warnings. No
> runtime reproduction or filesystem stress test was performed.
> ---
> fs/ntfs/attrib.c | 2 ++
> fs/ntfs/bitmap.c | 4 ++++
> fs/ntfs/lcnalloc.c | 2 ++
> fs/ntfs/mft.c | 4 ++++
> 4 files changed, 12 insertions(+)
>
> diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
> index fce7144d7bef..b460d2223314 100644
> --- a/fs/ntfs/attrib.c
> +++ b/fs/ntfs/attrib.c
> @@ -2332,6 +2332,8 @@ int ntfs_attr_set(struct ntfs_inode *ni, s64 ofs, s64 cnt, const u8 val)
> attr_len = min_t(size_t, (size_t)cnt, folio_size(folio) - offset);
>
> folio_lock(folio);
> + if (folio_test_writeback(folio))
> + folio_wait_writeback(folio);
> addr = kmap_local_folio(folio, offset);
> memset(addr, val, attr_len);
> kunmap_local(addr);
> diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c
> index af86fb1c199b..057b315789ec 100644
> --- a/fs/ntfs/bitmap.c
> +++ b/fs/ntfs/bitmap.c
> @@ -213,6 +213,8 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
> }
>
> folio_lock(folio);
> + if (folio_test_writeback(folio))
> + folio_wait_writeback(folio);
> kaddr = kmap_local_folio(folio, 0);
>
> /* Set @pos to the position of the byte containing @start_bit. */
> @@ -277,6 +279,8 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, const s64 start_bit,
> }
>
> folio_lock(folio);
> + if (folio_test_writeback(folio))
> + folio_wait_writeback(folio);
> kaddr = kmap_local_folio(folio, 0);
> /*
> * Depending on @value, modify all remaining whole bytes in the
> diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c
> index 3ebcac4c2864..aac8627a9283 100644
> --- a/fs/ntfs/lcnalloc.c
> +++ b/fs/ntfs/lcnalloc.c
> @@ -348,6 +348,8 @@ struct runlist_element *ntfs_cluster_alloc(struct ntfs_volume *vol, const s64 st
> }
>
> folio_lock(folio);
> + if (folio_test_writeback(folio))
> + folio_wait_writeback(folio);
> buf = kmap_local_folio(folio, 0) + pg_off;
> ntfs_debug("Before inner while loop: buf_size %i, lcn 0x%llx, bmp_pos 0x%llx, need_writeback %i.",
> buf_size, lcn, bmp_pos, need_writeback);
> diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
> index 89288b794348..b8aa8b0891dc 100644
> --- a/fs/ntfs/mft.c
> +++ b/fs/ntfs/mft.c
> @@ -1206,6 +1206,8 @@ static s64 mft_bitmap_alloc_free_rec(struct ntfs_volume *vol,
> return PTR_ERR(folio);
> }
> folio_lock(folio);
> + if (folio_test_writeback(folio))
> + folio_wait_writeback(folio);
Hi Shengzhuo,
Could this deadlock during MFT bitmap
expansion?ntfs_mft_bitmap_extend_allocation_nolock() can recurse into MFT
record allocation while holding mftbmp_ni->runlist.lock.
With L being that lock, could we get the following interleaving?
A and B are $MFT::$BITMAP folios; B is outside the cached iomap.
Time flows downwards.
Writeback Bitmap expansion
--------- ----------------
lock A
set PG_writeback(A)
map A (take/release L)
add A to wpc->wb_ctx
unlock A
[BIO still unsubmitted]
take L
extend bitmap mapping pairs
need another extent record
ntfs_mft_record_alloc()
mft_bitmap_alloc_free_rec()
lock A
folio_wait_writeback(A)
[wait for A's I/O, holding L]
lock B
set PG_writeback(B)
ntfs_writeback_range(B)
__ntfs_write_iomap_begin()
down_write(L)
[blocked on L]
Cannot reach iomap_add_to_ioend()
to submit A's pending BIO. Cannot release L until
A's writeback completes.
ntfs_writeback_range() obtains the next mapping before
iomap_add_to_ioend() can submit the pending BIO.
Would we need to submit that BIO before taking the mapping locks?
Thanks,
Baolin.
> buf = (u8 *)kmap_local_folio(folio, 0) + folio_ofs;
> bit = data_pos & 7;
> data_pos &= ~7ull;
> @@ -1402,6 +1404,8 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol)
>
> down_write(&vol->lcnbmp_lock);
> folio_lock(folio);
> + if (folio_test_writeback(folio))
> + folio_wait_writeback(folio);
> b = (u8 *)kmap_local_folio(folio, 0) + (ll & ~PAGE_MASK);
> tb = 1 << (lcn & 7ull);
> /*
>
> ---
> base-commit: d135ab453a7400a34930bdda1ef4bdc8acfac80e
> change-id: 20261029-b4-ntfs-bitmap-writeback-wait-d4561fa54c97
>
> Best regards,
> --
> Shengzhuo Wei <me@cherr.cc>
next prev parent reply other threads:[~2026-10-29 2:07 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 20:09 Shengzhuo Wei
2026-10-29 2:07 ` liubaolin [this message]
2026-10-29 6:17 ` Shengzhuo Wei
2026-10-29 7:12 ` liubaolin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=374bf856-f880-4fa2-abec-c4b2a063bf57@163.com \
--to=liubaolin12138@163.com \
--cc=hyc.lee@gmail.com \
--cc=linkinjeon@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=me@cherr.cc \
--cc=ntfs@lists.linux.dev \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®