mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Baolin Liu <liubaolin12138@163.com>
To: linkinjeon@kernel.org, hyc.lee@gmail.com
Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org,
	Baolin Liu <liubaolin@kylinos.cn>
Subject: [PATCH v2 3/5] ntfs: report inode metadata errors to fsnotify
Date: Wed, 16 Sep 2026 10:23:43 +0800	[thread overview]
Message-ID: <20260916022345.1151836-4-liubaolin12138@163.com> (raw)
In-Reply-To: <20260916022345.1151836-1-liubaolin12138@163.com>

From: Baolin Liu <liubaolin@kylinos.cn>

Report inode initialization, writeback, and LogFile failures against
the affected VFS inode while retaining existing allocation and signal
handling. Consume attribute reporting state so callers do not emit a
second FAN_FS_ERROR event for the same failure.

Signed-off-by: Baolin Liu <liubaolin@kylinos.cn>
---
 fs/ntfs/inode.c   | 52 ++++++++++++++++++++++++++++++++++-------------
 fs/ntfs/logfile.c |  2 +-
 2 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index d5e526d3612a..13f353905fb3 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -689,7 +689,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	unsigned int name_len = 4, flags = 0;
 	int extend_sys = 0;
 	dev_t dev = 0;
-	bool has_lxmod = false;
+	bool error_reported = false, has_lxmod = false;
 	bool vol_err = true;
 
 	ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no);
@@ -761,6 +761,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0, 0, 0, NULL, 0,
 			ctx);
 	if (unlikely(err)) {
+		error_reported = ctx->error_reported;
 		if (err == -ENOENT)
 			ntfs_error(vi->i_sb, "$STANDARD_INFORMATION attribute is missing.");
 		goto unm_err_out;
@@ -801,6 +802,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	err = ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 0, 0, NULL, 0, ctx);
 	if (err) {
 		if (unlikely(err != -ENOENT)) {
+			error_reported = ctx->error_reported;
 			ntfs_error(vi->i_sb, "Failed to lookup attribute list attribute.");
 			goto unm_err_out;
 		}
@@ -923,6 +925,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 		err = ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE,
 				0, NULL, 0, ctx);
 		if (unlikely(err)) {
+			error_reported = ctx->error_reported;
 			if (err == -ENOENT)
 				ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is missing.");
 			goto unm_err_out;
@@ -1056,6 +1059,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 			vi->i_size = ni->initialized_size =
 					ni->allocated_size = 0;
 			if (err != -ENOENT) {
+				error_reported = ctx->error_reported;
 				ntfs_error(vi->i_sb, "Failed to lookup $DATA attribute.");
 				goto unm_err_out;
 			}
@@ -1091,6 +1095,7 @@ static int ntfs_read_locked_inode(struct inode *vi)
 			}
 
 			err = extend_sys;
+			error_reported = ctx->error_reported;
 			ntfs_error(vi->i_sb, "$DATA attribute is missing, err : %d", err);
 			goto unm_err_out;
 		}
@@ -1247,12 +1252,12 @@ static int ntfs_read_locked_inode(struct inode *vi)
 	if (m)
 		unmap_mft_record(ni);
 err_out:
-	if (err != -EOPNOTSUPP && err != -ENOMEM &&
+	if (!error_reported && err != -EOPNOTSUPP && err != -ENOMEM &&
 	    err != -EINTR && err != -ERESTARTSYS && vol_err == true) {
 		ntfs_error(vol->sb,
 			"Failed with error code %i.  Marking corrupt inode 0x%llx as bad.  Run chkdsk.",
 			err, ni->mft_no);
-		NVolSetErrors(vol);
+		ntfs_report_file_metadata_error(vi, err);
 	}
 	return err;
 }
@@ -1286,6 +1291,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 	struct attr_record *a;
 	struct ntfs_attr_search_ctx *ctx;
 	int err = 0;
+	bool error_reported = false;
 
 	ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no);
 
@@ -1316,8 +1322,10 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 	/* Find the attribute. */
 	err = ntfs_attr_lookup(ni->type, ni->name, ni->name_len,
 			CASE_SENSITIVE, 0, NULL, 0, ctx);
-	if (unlikely(err))
+	if (unlikely(err)) {
+		error_reported = ctx->error_reported;
 		goto unm_err_out;
+	}
 	a = ctx->attr;
 	if (a->flags & (ATTR_COMPRESSION_MASK | ATTR_IS_SPARSE)) {
 		if (a->flags & ATTR_COMPRESSION_MASK) {
@@ -1479,9 +1487,9 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
 			"Failed with error code %i while reading attribute inode (mft_no 0x%llx, type 0x%x, name_len %i).  Marking corrupt inode and base inode 0x%llx as bad.  Run chkdsk.",
 			err, ni->mft_no, ni->type, ni->name_len,
 			base_ni->mft_no);
-	if (err != -ENOENT && err != -ENOMEM &&
+	if (!error_reported && err != -ENOENT && err != -ENOMEM &&
 	    err != -EINTR && err != -ERESTARTSYS)
-		NVolSetErrors(vol);
+		ntfs_report_file_metadata_error(base_vi, err);
 	return err;
 }
 
@@ -1528,6 +1536,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	struct ntfs_attr_search_ctx *ctx;
 	struct index_root *ir;
 	int err = 0;
+	bool error_reported = false;
 
 	ntfs_debug("Entering for i_ino 0x%llx.", ni->mft_no);
 	lockdep_assert_held(&base_ni->mrec_lock);
@@ -1558,6 +1567,7 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	err = ntfs_attr_lookup(AT_INDEX_ROOT, ni->name, ni->name_len,
 			CASE_SENSITIVE, 0, NULL, 0, ctx);
 	if (unlikely(err)) {
+		error_reported = ctx->error_reported;
 		if (err == -ENOENT)
 			ntfs_error(vi->i_sb, "$INDEX_ROOT attribute is missing.");
 		goto unm_err_out;
@@ -1630,8 +1640,10 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 			m = NULL;
 			ctx = NULL;
 			goto skip_large_index_stuff;
-		} else
+		} else {
+			error_reported = ctx->error_reported;
 			ntfs_error(vi->i_sb, "Failed to lookup $INDEX_ALLOCATION attribute.");
+		}
 		goto unm_err_out;
 	}
 	NInoSetIndexAllocPresent(ni);
@@ -1685,6 +1697,9 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 	bvi = ntfs_attr_iget(base_vi, AT_BITMAP, ni->name, ni->name_len);
 	if (IS_ERR(bvi)) {
 		err = PTR_ERR(bvi);
+		error_reported = err != -ENOENT && err != -ENOMEM &&
+				 err != -EOPNOTSUPP && err != -EINTR &&
+				 err != -ERESTARTSYS;
 		if (err != -EINTR && err != -ERESTARTSYS)
 			ntfs_error(vi->i_sb, "Failed to get bitmap attribute.");
 		goto unm_err_out;
@@ -1734,9 +1749,9 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
 		ntfs_error(vi->i_sb,
 			"Failed with error code %i while reading index inode (mft_no 0x%llx, name_len %i.",
 			err, ni->mft_no, ni->name_len);
-	if (err != -EOPNOTSUPP && err != -ENOMEM &&
+	if (!error_reported && err != -EOPNOTSUPP && err != -ENOMEM &&
 	    err != -EINTR && err != -ERESTARTSYS)
-		NVolSetErrors(vol);
+		ntfs_report_file_metadata_error(base_vi, err);
 	return err;
 }
 
@@ -2479,7 +2494,9 @@ int ntfs_truncate_vfs(struct inode *vi, loff_t new_size, loff_t i_size)
  *
  * Return 0 on success or -errno on error.
  */
-static int ntfs_inode_sync_standard_information(struct inode *vi, struct mft_record *m)
+static int ntfs_inode_sync_standard_information(struct inode *vi,
+						struct mft_record *m,
+						bool *error_reported)
 {
 	struct ntfs_inode *ni = NTFS_I(vi);
 	struct ntfs_attr_search_ctx *ctx;
@@ -2495,6 +2512,8 @@ static int ntfs_inode_sync_standard_information(struct inode *vi, struct mft_rec
 	err = ntfs_attr_lookup(AT_STANDARD_INFORMATION, NULL, 0,
 			CASE_SENSITIVE, 0, NULL, 0, ctx);
 	if (unlikely(err)) {
+		if (ctx->error_reported)
+			*error_reported = true;
 		ntfs_attr_put_search_ctx(ctx);
 		return err;
 	}
@@ -2749,7 +2768,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
 	struct ntfs_inode *mft_ni = NTFS_I(ni->vol->mft_ino);
 	struct mft_record *m;
 	int err = 0;
-	bool need_iput = false;
+	bool error_reported = false, need_iput = false;
 
 	ntfs_debug("Entering for %sinode 0x%llx.", NInoAttr(ni) ? "attr " : "",
 			ni->mft_no);
@@ -2783,13 +2802,14 @@ int __ntfs_write_inode(struct inode *vi, int sync)
 
 	if (NInoNonResident(ni) && NInoRunlistDirty(ni)) {
 		down_write(&ni->runlist.lock);
-		err = ntfs_attr_update_mapping_pairs_locked(ni, 0, ni);
+		err = ntfs_attr_update_mapping_pairs_locked_reported(ni, 0, ni,
+								     &error_reported);
 		if (!err)
 			NInoClearRunlistDirty(ni);
 		up_write(&ni->runlist.lock);
 	}
 
-	err = ntfs_inode_sync_standard_information(vi, m);
+	err = ntfs_inode_sync_standard_information(vi, m, &error_reported);
 	if (err)
 		goto unm_err_out;
 
@@ -2889,7 +2909,11 @@ int __ntfs_write_inode(struct inode *vi, int sync)
 		mark_inode_dirty(vi);
 	else {
 		ntfs_error(vi->i_sb, "Failed (error %i):  Run chkdsk.", -err);
-		NVolSetErrors(ni->vol);
+		if (!error_reported && err != -EINTR &&
+		    err != -ERESTARTSYS)
+			ntfs_report_file_metadata_error(vi, err);
+		else
+			NVolSetErrors(ni->vol);
 	}
 	if (need_iput)
 		iput(vi);
diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c
index 024ddee42dc8..9be0506fd5c0 100644
--- a/fs/ntfs/logfile.c
+++ b/fs/ntfs/logfile.c
@@ -768,7 +768,7 @@ bool ntfs_empty_logfile(struct inode *log_vi)
 rl_err:
 	ntfs_error(sb, "Runlist is corrupt.  Unmount and run chkdsk.");
 dirty_err:
-	NVolSetErrors(vol);
+	ntfs_report_file_metadata_error(log_vi, -EIO);
 	err = -EIO;
 err:
 	kvfree(empty_buf);
-- 
2.51.0


  parent reply	other threads:[~2026-09-16  2:24 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16  2:23 [PATCH v2 0/5] ntfs: report filesystem errors through fsnotify Baolin Liu
2026-09-16  2:23 ` [PATCH v2 1/5] ntfs: report allocation metadata errors to fsnotify Baolin Liu
2026-09-16  2:23 ` [PATCH v2 2/5] ntfs: report attribute " Baolin Liu
2026-09-16  7:38   ` Hyunchul Lee
2026-09-17  4:21     ` liubaolin
2026-09-16  2:23 ` Baolin Liu [this message]
2026-09-16  2:23 ` [PATCH v2 4/5] ntfs: report MFT " Baolin Liu
2026-09-16  2:23 ` [PATCH v2 5/5] ntfs: report shutdown " Baolin Liu
2026-09-16  2:40 ` [PATCH v2 0/5] ntfs: report filesystem errors through fsnotify 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=20260916022345.1151836-4-liubaolin12138@163.com \
    --to=liubaolin12138@163.com \
    --cc=hyc.lee@gmail.com \
    --cc=linkinjeon@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liubaolin@kylinos.cn \
    --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®