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 1/6] ntfs: do not map an unmappable runlist fragment as a hole
Date: Sun, 27 Sep 2026 13:08:20 +0800 [thread overview]
Message-ID: <20260927050831.2739166-1-matthias.goergens@gmail.com> (raw)
In-Reply-To: <cover.1790417653.git.matthias.goergens@gmail.com>
When the extent mft record holding part of a file's runlist cannot be
read, ntfs_attr_vcn_to_rl() ignores the failed ntfs_map_runlist_nolock()
retry and returns with *lcn == LCN_RL_NOT_MAPPED. The iomap read path
only rejects lcn < LCN_ENOENT, so it maps the range as a hole and read()
returns zeros with no error. The first read already does this:
ntfs_attr_map_whole_runlist() keeps the fragments it could read,
readahead drops its error, and the next lookup finds the unmapped tail.
On a file whose runlist is split between its base record (vcn 0-214) and
one extent record (vcn 215-1499), breaking only the extent record's FILE
magic makes the kernel log "Failed to map extent mft record", yet read()
returns 1285 clusters of zeros for vcn 215-1499. A damaged attribute
list entry, which makes the retry fail with -ENOENT, gives the same
zeros.
Return -ENOMEM if the retry ran out of memory and -EIO otherwise. Both
callers already handle an ERR_PTR; other negative lcns, including
LCN_ENOENT, are returned as before. Reads of vcn 215-1499 now fail with
-EIO. An intact volume exercised with buffered, mmap and O_DIRECT I/O,
fallocate, truncate, sparse and compressed files behaves as before.
Fixes: 495e90fa3348 ("ntfs: update attrib operations")
Cc: stable@vger.kernel.org
Signed-off-by: Matthias Goergens <matthias.goergens@gmail.com>
---
fs/ntfs/attrib.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 333b3371acb47..a337a3429b401 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -317,7 +317,7 @@ int ntfs_map_runlist(struct ntfs_inode *ni, s64 vcn)
struct runlist_element *ntfs_attr_vcn_to_rl(struct ntfs_inode *ni, s64 vcn, s64 *lcn)
{
struct runlist_element *rl = ni->runlist.rl;
- int err;
+ int err = 0;
bool is_retry = false;
if (!rl) {
@@ -335,12 +335,21 @@ struct runlist_element *ntfs_attr_vcn_to_rl(struct ntfs_inode *ni, s64 vcn, s64
if (*lcn <= LCN_RL_NOT_MAPPED && is_retry == false) {
is_retry = true;
- if (!ntfs_map_runlist_nolock(ni, vcn, NULL)) {
+ err = ntfs_map_runlist_nolock(ni, vcn, NULL);
+ if (!err) {
rl = ni->runlist.rl;
goto remap_rl;
}
}
+ /*
+ * The runlist fragment containing @vcn could not be mapped, e.g.
+ * because the extent mft record holding it is corrupt. Do not hand
+ * LCN_RL_NOT_MAPPED back to callers, which would treat it as a hole.
+ */
+ if (*lcn == LCN_RL_NOT_MAPPED)
+ return ERR_PTR(err == -ENOMEM ? -ENOMEM : -EIO);
+
return rl;
}
--
2.55.0
next prev parent reply other threads:[~2026-09-27 5:08 UTC|newest]
Thread overview: 15+ 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 ` Matthias Goergens [this message]
2026-09-27 23:03 ` [PATCH v2 1/6] ntfs: do not map an unmappable runlist fragment as a hole liubaolin
2026-09-27 5:08 ` [PATCH v2 2/6] ntfs: do not turn an unmappable runlist fragment into delalloc on write Matthias Goergens
2026-09-28 0:21 ` 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
2026-09-29 0:26 ` 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=20260927050831.2739166-1-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®