[PATCH v3 5/6] ntfs: report MFT writeback errors to fsnotify
From: Baolin Liu
Date: Thu Sep 24 2026 - 05:03:29 EST
From: Baolin Liu <liubaolin@xxxxxxxxxx>
MFT writeback failures need to reach filesystem health monitors as well
as the kernel log and mapping error state.
Report device errors from the existing parent BIO completion callback for
both synchronous and asynchronous writes, before ending folio writeback.
The generic fserror code queues notification work and takes its own inode
reference, so no additional NTFS completion work is needed.
Report mirror and preparation failures where they are detected, including
failures that occur before a BIO can be submitted. Keep these reports
together with completion reporting so errors retained in the write context
still mark the volume and notify userspace independently of device errors.
Preserve the retry handling for allocation failures in MFT write
preparation.
Signed-off-by: Baolin Liu <liubaolin@xxxxxxxxxx>
---
fs/ntfs/mft.c | 34 ++++++++++++++++++++++++----------
1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c
index a1b1c080b256..6a202ffc513a 100644
--- a/fs/ntfs/mft.c
+++ b/fs/ntfs/mft.c
@@ -481,9 +481,11 @@ static void ntfs_mft_end_io(struct bio *bio)
err = blk_status_to_errno(bio->bi_status);
else
err = ctx->error;
+ /* Report device errors from both synchronous and asynchronous writes. */
+ if (bio->bi_status)
+ ntfs_report_file_metadata_error(ctx->mapping->host, err);
if (err) {
mapping_set_error(ctx->mapping, err);
- NVolSetErrors(ctx->vol);
ntfs_error(ctx->vol->sb, "I/O error while writing MFT: %d",
err);
}
@@ -544,22 +546,24 @@ static int ntfs_sync_mft_mirror_unit(struct ntfs_volume *vol,
u64 mirror_size;
unsigned int mirror_ofs;
u8 *src, *dst;
- int err;
+ int err = -EIO;
if (unlikely(!vol->mftmirr_ino))
- return -EIO;
+ goto out_report;
mirror_size = (u64)vol->mftmirr_size * vol->mft_record_size;
if (mirror_file_ofs >= mirror_size ||
unit->len > mirror_size - mirror_file_ofs)
- return -EIO;
+ goto out_report;
if (unit->folio_ofs + unit->len > folio_size(source))
- return -EIO;
+ goto out_report;
mirror = read_mapping_folio(vol->mftmirr_ino->i_mapping,
mirror_file_ofs >> PAGE_SHIFT, NULL);
- if (IS_ERR(mirror))
- return PTR_ERR(mirror);
+ if (IS_ERR(mirror)) {
+ err = PTR_ERR(mirror);
+ goto out_report;
+ }
folio_lock(mirror);
if (folio_test_writeback(mirror))
@@ -598,6 +602,9 @@ static int ntfs_sync_mft_mirror_unit(struct ntfs_volume *vol,
out_unlock:
folio_unlock(mirror);
folio_put(mirror);
+out_report:
+ if (err)
+ ntfs_report_metadata_error(vol, err);
return err;
}
@@ -815,8 +822,14 @@ int write_mft_record_nolock(struct ntfs_inode *ni, struct mft_record *m, int syn
mark_mft_record_dirty(ni);
if (!sync)
err = 0;
- } else
- NVolSetErrors(vol);
+ } else {
+ struct ntfs_inode *base_ni = ni;
+
+ if (ni->nr_extents < 0)
+ base_ni = ni->ext.base_ntfs_ino;
+ mapping_set_error(folio->mapping, err);
+ ntfs_report_file_metadata_error(VFS_I(base_ni), err);
+ }
return err;
}
@@ -3188,7 +3201,7 @@ static void ntfs_mft_write_error(struct ntfs_volume *vol,
struct address_space *mapping, int err)
{
mapping_set_error(mapping, err);
- NVolSetErrors(vol);
+ ntfs_report_file_metadata_error(mapping->host, err);
ntfs_error(vol->sb, "Error while writing MFT folio: %d", err);
}
@@ -3346,6 +3359,7 @@ static int ntfs_write_mft_block(struct folio *folio, struct writeback_control *w
ctx->error = -EIO;
redirty = true;
err = -EIO;
+ ntfs_mft_write_error(vol, mapping, err);
break;
}
}
--
2.51.0