From: Matthias Goergens <matthias.goergens@gmail.com>
To: Namjae Jeon <linkinjeon@kernel.org>, Hyunchul Lee <hyc.lee@gmail.com>
Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH v2 2/6] ntfs: do not turn an unmappable runlist fragment into delalloc on write
Date: Sun, 27 Sep 2026 13:08:21 +0800 [thread overview]
Message-ID: <20260927050831.2739166-2-matthias.goergens@gmail.com> (raw)
In-Reply-To: <cover.1790417653.git.matthias.goergens@gmail.com>
ntfs_write_simple_iomap_begin_non_resident() has the same unchecked
retry. LCN_RL_NOT_MAPPED passes its "lcn <= LCN_HOLE" test, so a
buffered write into a range whose extent record cannot be read is
merged into the runlist as LCN_DELALLOC over clusters that are already
allocated on disk, and write() succeeds. If the record stays
unreadable, writeback fails too and the data never reaches the disk;
the error only shows up at a later fsync() or a synchronous write.
On the volume from the previous patch, after a read of the file, an
8 KiB pwrite() at vcn 1000 returns 8192, fsync() returns -EIO, and
after remount the range is unchanged.
Fail the lookup here too, with -ENOMEM or -EIO. That pwrite() now
fails with -EIO. Writes whose range can be mapped are unaffected.
Fixes: b041ca562526 ("ntfs: update iomap and address space operations")
Cc: stable@vger.kernel.org
Signed-off-by: Matthias Goergens <matthias.goergens@gmail.com>
---
fs/ntfs/iomap.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/fs/ntfs/iomap.c b/fs/ntfs/iomap.c
index c812d7f19b360..b4475963e57a7 100644
--- a/fs/ntfs/iomap.c
+++ b/fs/ntfs/iomap.c
@@ -394,7 +394,7 @@ static int ntfs_write_simple_iomap_begin_non_resident(struct inode *inode, loff_
loff_t vcn_ofs, rl_length;
struct runlist_element *rl, *rlc;
bool is_retry = false;
- int err = 0;
+ int err = 0, map_err = 0;
s64 vcn, lcn;
s64 max_clu_count =
ntfs_bytes_to_cluster(vol, round_up(length, vol->cluster_size));
@@ -429,12 +429,24 @@ static int ntfs_write_simple_iomap_begin_non_resident(struct inode *inode, loff_
if (lcn <= LCN_RL_NOT_MAPPED && is_retry == false) {
is_retry = true;
- if (!ntfs_map_runlist_nolock(ni, vcn, NULL)) {
+ map_err = ntfs_map_runlist_nolock(ni, vcn, NULL);
+ if (!map_err) {
rl = ni->runlist.rl;
goto remap_rl;
}
}
+ /*
+ * As in ntfs_attr_vcn_to_rl(): a runlist fragment that could not be
+ * mapped is not a hole. Treating it as one would put a delalloc
+ * extent over clusters that are allocated on disk but unknown to us.
+ */
+ if (lcn == LCN_RL_NOT_MAPPED) {
+ up_write(&ni->runlist.lock);
+ mutex_unlock(&ni->mrec_lock);
+ return map_err == -ENOMEM ? -ENOMEM : -EIO;
+ }
+
max_clu_count = min(max_clu_count, rl->length - (vcn - rl->vcn));
if (max_clu_count == 0) {
ntfs_error(inode->i_sb,
--
2.55.0
next prev parent reply other threads:[~2026-09-27 5:08 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 15:39 [PATCH] ntfs: fail the mount when $MFT needs its own extent records Matthias Goergens
2026-09-23 1:16 ` Hyunchul Lee
2026-09-27 5:08 ` [PATCH v2 0/6] ntfs: fix the $MFT bootstrap hang and reads of unmapped runlist ranges Matthias Goergens
2026-09-27 5:08 ` [PATCH v2 1/6] ntfs: do not map an unmappable runlist fragment as a hole Matthias Goergens
2026-09-27 23:03 ` liubaolin
2026-09-27 5:08 ` Matthias Goergens [this message]
2026-09-28 0:21 ` [PATCH v2 2/6] ntfs: do not turn an unmappable runlist fragment into delalloc on write Hyunchul Lee
2026-09-28 1:46 ` Hyunchul Lee
2026-09-27 5:08 ` [PATCH v2 3/6] ntfs: fail the mount when $MFT needs its own extent records Matthias Goergens
2026-09-27 5:08 ` [PATCH v2 4/6] ntfs: do not map a vcn as a hole when its runlist lookup failed Matthias Goergens
2026-09-28 1:09 ` Hyunchul Lee
2026-09-27 5:08 ` [PATCH v2 5/6] ntfs: fail the mount when $MFT's data size exceeds its allocation Matthias Goergens
2026-09-27 5:08 ` [PATCH v2 6/6] ntfs: reject non-resident attributes whose sizes exceed their allocation Matthias Goergens
2026-09-28 1:42 ` Hyunchul Lee
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=20260927050831.2739166-2-matthias.goergens@gmail.com \
--to=matthias.goergens@gmail.com \
--cc=hyc.lee@gmail.com \
--cc=linkinjeon@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ntfs@lists.linux.dev \
/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®