From nobody Thu Sep 24 12:09:31 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 11DF843F0A8 for ; Thu, 24 Sep 2026 09:01:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240501; cv=none; b=Fug9FSjvSSCTXzaZPLA4AEqJ+i8x/2jKNyzkJj070JxBo7wCWMmK3DzTimkEJsSFbT8VEyioiWSK+ysbRfZ5qmMMuyKmu7PUZAkUKg6SDlEuRmPa15V01ApWhuJHIGCW+Gk6UwUPEKx/TUUsdbKZczx3GJpEuGazgv7I8T0OqzA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240501; c=relaxed/simple; bh=UsaM0+IpzQRGVwhC5b7VpLDQLsiTaLSIbHXPKHHojnM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lvufYtChNNcYAseohHSPHmICO3o5Lp+7ItTmWAlpll57mSjwct+omjnPM2B68zgrMz8rQMQxBRBzi2KxfTwNuXHI2CjLI95I0o3xtEvxYQ/uQLvRaQdaVYH1hJFS4bxwM7QgVsbWkTpgY+m7+GZPx7+mvWFBDSguInO6Dczt22A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=j0hP4yPR; arc=none smtp.client-ip=117.135.210.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="j0hP4yPR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=FM Y/bov/Kiu7NY6r1RpOwu8u7WPqC8knEEbC+hnouzc=; b=j0hP4yPRRGy9IdVXAc E8mNai7SWcuhEXV6kf8XsRhZj/HpuoVUyHwFoEbtFX5dlggTJ7l+2UnTdTfGf9nM shD3ZscqtmHy+g+oBpWYfO7Z7b9Eh72TJUFZ9GNsH1jPMLIh3EV69FBtGkQ5mgAz UhavuuSo/HuOMLW5E7H53E+tI= Received: from liubaolin-ThinkPad-E15-Gen-2 (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3H73Q5rRqL6EhAg--.34883S3; Thu, 24 Sep 2026 17:01:09 +0800 (CST) From: Baolin Liu To: linkinjeon@kernel.org, hyc.lee@gmail.com Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org, Baolin Liu Subject: [PATCH v3 1/6] ntfs: report allocation metadata errors to fsnotify Date: Thu, 24 Sep 2026 17:00:57 +0800 Message-ID: <20260924090102.2865942-2-liubaolin12138@163.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260924090102.2865942-1-liubaolin12138@163.com> References: <20260924090102.2865942-1-liubaolin12138@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wD3H73Q5rRqL6EhAg--.34883S3 X-Coremail-Antispam: 1Uf129KBjvJXoWxCFWxJFyDGw15Xry5AF13Jwb_yoW5GF1UpF 97Awnakrs7t3WjqrsF93ySyw4S9a4kGw4UtryUXw1fXrn7Kr1DXF4kK3WF9FnY9FWUZr1U X3Wjg3y3urWDZr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07j7nYrUUUUU= X-CM-SenderInfo: xolxutxrol0iasrtmqqrwthudrp/xtbC6RW2gWq05tX2PAAA3s Content-Type: text/plain; charset="utf-8" From: Baolin Liu Cluster allocation and free rollbacks can leave volume metadata inconsistent without notifying filesystem health monitors. Add a volume-level helper that records the error and reports it through fsnotify after mount activation. Report each failed rollback where it is detected and leave event merging to fanotify. Signed-off-by: Baolin Liu --- fs/ntfs/lcnalloc.c | 4 ++-- fs/ntfs/super.c | 8 ++++++++ fs/ntfs/volume.h | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/ntfs/lcnalloc.c b/fs/ntfs/lcnalloc.c index 0d6cd08ee2e7..347f9e152588 100644 --- a/fs/ntfs/lcnalloc.c +++ b/fs/ntfs/lcnalloc.c @@ -763,7 +763,7 @@ switch_to_data1_zone: search_zone =3D 2; ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving inconsistent metadata! Unmount= and run chkdsk.", err2); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err2); } /* Free the runlist. */ kvfree(rl); @@ -1044,7 +1044,7 @@ s64 __ntfs_cluster_free(struct ntfs_inode *ni, const = s64 start_vcn, s64 count, ntfs_error(vol->sb, "Failed to rollback (error %i). Leaving inconsistent metadata! Unmoun= t and run chkdsk.", (int)delta); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, delta); } else { ntfs_dec_free_clusters(vol, delta); } diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 716ba775f1f3..827313df0e28 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -14,6 +14,7 @@ #include #include #include +#include =20 #include "sysctl.h" #include "logfile.h" @@ -394,6 +395,13 @@ const struct option_t on_errors_arr[] =3D { { 0, NULL } }; =20 +void ntfs_report_metadata_error(struct ntfs_volume *vol, int error) +{ + NVolSetErrors(vol); + if (vol->sb->s_flags & SB_ACTIVE) + fserror_report_metadata(vol->sb, error, GFP_ATOMIC); +} + void ntfs_handle_error(struct super_block *sb) { struct ntfs_volume *vol =3D NTFS_SB(sb); diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h index fdb57279de84..5bcd0dd2a19d 100644 --- a/fs/ntfs/volume.h +++ b/fs/ntfs/volume.h @@ -254,6 +254,8 @@ DEFINE_NVOL_BIT_OPS(DisableSparse) DEFINE_NVOL_BIT_OPS(NativeSymlinkRel) DEFINE_NVOL_BIT_OPS(SymlinkNative) =20 +void ntfs_report_metadata_error(struct ntfs_volume *vol, int error); + static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr) { if (!NVolFreeClusterKnown(vol)) --=20 2.51.0 From nobody Thu Sep 24 12:09:31 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 296FB3CFF55 for ; Thu, 24 Sep 2026 09:01:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240498; cv=none; b=kDFHSKLuB6zSr8H5sr/XKmj9496+gVXvve8uE70lRFZisZsLew+kkLDPPT133Ff+/imlnqdZ6lfp+yS22e6tVEXOdN+2wQsEkMomkReELwhlHaIHgE3t4nx+rkcuBBvAadKV6OHO6aBntP1repydVUNXiuAjU2inBBy3394xpvg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240498; c=relaxed/simple; bh=URnx+KRu+EBokNvm0JYAZE5u8FlO6vN1AwaGb3rIO60=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pzZMdVs0CLffNkk0T5+e/ZmtwJUHsdUq5aWfq3Ll4OfOqCmu9btNFkSwgTtcKO5bBjYWVqCqHd2dlA8v543V0iGqcuU/IVxOwgwyYU1Jz5qqFWTTxRbLrfTys8d2+HGXTgi67puHdNYzGEihQBcy0WMJH/NSgrm+1rw1b4agf5I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=mmtswZig; arc=none smtp.client-ip=117.135.210.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="mmtswZig" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=pd 6oZG92vv/3ivhx7v3ox5s2RlQW7KTGSNXZ1YwA9lQ=; b=mmtswZigk9gJnKqDai wljRQVyJ4rEB6mB8oBwhzUQxYDkUhOdCDLcYsmBsW5B9qFcm/hP80I0gH7tsH5m4 HoBBgkXUExW+txHAEGCZoy9gzNYf4ELM2GlNp5nCz/jJatzRQFuipnRpIOl+h9Ff AMSRB3QTfr2oiGGp0oW8fB5bo= Received: from liubaolin-ThinkPad-E15-Gen-2 (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3H73Q5rRqL6EhAg--.34883S4; Thu, 24 Sep 2026 17:01:11 +0800 (CST) From: Baolin Liu To: linkinjeon@kernel.org, hyc.lee@gmail.com Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org, Baolin Liu Subject: [PATCH v3 2/6] ntfs: report attribute errors to fsnotify Date: Thu, 24 Sep 2026 17:00:58 +0800 Message-ID: <20260924090102.2865942-3-liubaolin12138@163.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260924090102.2865942-1-liubaolin12138@163.com> References: <20260924090102.2865942-1-liubaolin12138@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wD3H73Q5rRqL6EhAg--.34883S4 X-Coremail-Antispam: 1Uf129KBjvAXoW3ZrWkJw1kur4rJFykur48WFg_yoW8JrWDWo ZIya1j9w4kKr1Yy3y09wn8tas8uan8GrZ8JFW5Jrnrur9Fqw4DGw1xG3W3Wayxu3yFgr1q grykt395AFs7try5n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxU3CzuDUUUU X-CM-SenderInfo: xolxutxrol0iasrtmqqrwthudrp/xtbC6Re2gWq05tf2kQAA3B Content-Type: text/plain; charset="utf-8" From: Baolin Liu Attribute corruption and failed allocation rollbacks can leave files unusable or their metadata inconsistent without notifying health monitors. Add a file-level reporting helper and notify fsnotify when attribute validation fails or a rollback cannot release clusters or restore mapping pairs. Keep the original operation's return value separate from the rollback error reported to userspace. Report rollback failures independently of earlier lookup or mapping errors. Leave event merging to fanotify instead of carrying reporting state through search contexts and mapping-pairs updates. Signed-off-by: Baolin Liu --- fs/ntfs/attrib.c | 84 ++++++++++++++++++++++++++++++++-------------- fs/ntfs/attrlist.c | 17 ++++++---- fs/ntfs/bitmap.c | 2 +- fs/ntfs/super.c | 12 +++++++ fs/ntfs/volume.h | 1 + 5 files changed, 84 insertions(+), 32 deletions(-) diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 333b3371acb4..10b7f9b7c051 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c @@ -838,6 +838,7 @@ static int ntfs_attr_find(const __le32 type, const __le= 16 *name, const u8 *val, const u32 val_len, struct ntfs_attr_search_ctx *ctx) { struct attr_record *a; + struct ntfs_inode *base_ni; struct ntfs_volume *vol =3D ctx->ntfs_ino->vol; __le16 *upcase =3D vol->upcase; u32 upcase_len =3D vol->upcase_len; @@ -964,7 +965,11 @@ static int ntfs_attr_find(const __le32 type, const __l= e16 *name, } ntfs_error(vol->sb, "mft %#llx, type %#x is corrupt. Run chkdsk.", (long long)ctx->ntfs_ino->mft_no, le32_to_cpu(type)); - NVolSetErrors(vol); + if (ctx->ntfs_ino->nr_extents >=3D 0) + base_ni =3D ctx->ntfs_ino; + else + base_ni =3D ctx->ntfs_ino->ext.base_ntfs_ino; + ntfs_report_file_metadata_error(VFS_I(base_ni), -EIO); return -EIO; } =20 @@ -1501,8 +1506,12 @@ static int ntfs_external_attr_find(const __le32 type, err =3D -EIO; } =20 - if (err !=3D -ENOMEM) - NVolSetErrors(vol); + if (err !=3D -ENOMEM) { + if (err !=3D -EINTR && err !=3D -ERESTARTSYS) + ntfs_report_file_metadata_error(VFS_I(base_ni), err); + else + NVolSetErrors(vol); + } return err; not_found: /* @@ -2233,10 +2242,11 @@ int ntfs_attr_make_non_resident(struct ntfs_inode *= ni, const u32 data_size) rl_err_out: up_write(&ni->runlist.lock); if (rl) { - if (ntfs_cluster_free_from_rl(vol, rl) < 0) { + err2 =3D ntfs_cluster_free_from_rl(vol, rl); + if (err2 < 0) { ntfs_error(vol->sb, "Failed to release allocated cluster(s) in error code path. Run chkds= k to recover the lost cluster(s)."); - NVolSetErrors(vol); + ntfs_report_file_metadata_error(vi, err2); } kvfree(rl); folio_err_out: @@ -3728,6 +3738,7 @@ static int __ntfs_attr_update_mapping_pairs(struct nt= fs_inode *ni, struct attr_record *a; s64 stop_vcn; int err =3D 0, mp_size, cur_max_mp_size, exp_max_mp_size; + int rollback_err; bool finished_build; bool first_updated =3D false; struct super_block *sb; @@ -4016,10 +4027,14 @@ static int __ntfs_attr_update_mapping_pairs(struct = ntfs_inode *ni, m =3D map_mft_record(ext_ni); if (IS_ERR(m)) { ntfs_error(sb, "Could not map new MFT record"); - if (ntfs_mft_record_free(ni->vol, ext_ni)) + rollback_err =3D ntfs_mft_record_free(ni->vol, ext_ni); + if (rollback_err) { ntfs_error(sb, "Could not free MFT record"); + ntfs_report_file_metadata_error(VFS_I(base_ni), + rollback_err); + } ntfs_inode_close(ext_ni); - err =3D -ENOMEM; + err =3D PTR_ERR(m); ext_ni =3D NULL; goto put_err_out; } @@ -4053,8 +4068,12 @@ static int __ntfs_attr_update_mapping_pairs(struct n= tfs_inode *ni, if (err < 0) { ntfs_error(sb, "Could not add attribute extent"); unmap_mft_record(ext_ni); - if (ntfs_mft_record_free(ni->vol, ext_ni)) + rollback_err =3D ntfs_mft_record_free(ni->vol, ext_ni); + if (rollback_err) { ntfs_error(sb, "Could not free MFT record"); + ntfs_report_file_metadata_error(VFS_I(base_ni), + rollback_err); + } ntfs_inode_close(ext_ni); goto put_err_out; } @@ -4067,8 +4086,12 @@ static int __ntfs_attr_update_mapping_pairs(struct n= tfs_inode *ni, if (err < 0 && err !=3D -ENOSPC) { ntfs_error(sb, "Failed to build MP"); unmap_mft_record(ext_ni); - if (ntfs_mft_record_free(ni->vol, ext_ni)) + rollback_err =3D ntfs_mft_record_free(ni->vol, ext_ni); + if (rollback_err) { ntfs_error(sb, "Couldn't free MFT record"); + ntfs_report_file_metadata_error(VFS_I(base_ni), + rollback_err); + } goto put_err_out; } a->data.non_resident.highest_vcn =3D cpu_to_le64(stop_vcn - 1); @@ -4449,6 +4472,7 @@ static int ntfs_non_resident_attr_expand(struct ntfs_= inode *ni, const s64 newsiz struct ntfs_attr_search_ctx *ctx =3D NULL; struct runlist_element *rl, *rln; s64 org_alloc_size, org_compressed_size; + s64 freed; int err, err2; struct ntfs_inode *base_ni; struct super_block *sb =3D ni->vol->sb; @@ -4678,10 +4702,12 @@ static int ntfs_non_resident_attr_expand(struct ntf= s_inode *ni, const s64 newsiz return 0; rollback: /* Free allocated clusters. */ - err2 =3D ntfs_cluster_free(ni, ntfs_bytes_to_cluster(vol, org_alloc_size), - -1, ctx); - if (err2) + freed =3D ntfs_cluster_free(ni, ntfs_bytes_to_cluster(vol, org_alloc_size= ), + -1, ctx); + if (freed < 0) { ntfs_debug("Leaking clusters"); + ntfs_report_file_metadata_error(VFS_I(base_ni), freed); + } =20 /* Now, truncate the runlist itself. */ if (ni !=3D locked_ni) @@ -4698,14 +4724,18 @@ static int ntfs_non_resident_attr_expand(struct ntf= s_inode *ni, const s64 newsiz kvfree(ni->runlist.rl); ni->runlist.rl =3D NULL; ntfs_error(sb, "Couldn't truncate runlist. Rollback failed"); + ntfs_report_file_metadata_error(VFS_I(base_ni), err2); } else { /* Prepare to mapping pairs update. */ ni->allocated_size =3D org_alloc_size; /* Restore mapping pairs. */ if (ni !=3D locked_ni) down_read(&ni->runlist.lock); - if (__ntfs_attr_update_mapping_pairs(ni, 0, locked_ni, true)) + err2 =3D __ntfs_attr_update_mapping_pairs(ni, 0, locked_ni, true); + if (err2) { ntfs_error(sb, "Failed to restore old mapping pairs"); + ntfs_report_file_metadata_error(VFS_I(base_ni), err2); + } if (ni !=3D locked_ni) up_read(&ni->runlist.lock); =20 @@ -5139,8 +5169,9 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 = vcn_start, s64 *lcn_start, struct runlist_element *rl, *rlc; struct runlist_element *old_rl =3D NULL; s64 vcn =3D vcn_start, lcn, clu_count; + s64 freed; s64 lcn_seek_from =3D -1; - int err =3D 0; + int err =3D 0, err2; size_t new_rl_count, old_rl_count; =20 err =3D ntfs_attr_map_whole_runlist(ni); @@ -5239,10 +5270,11 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s6= 4 vcn_start, s64 *lcn_start, old_rl_count * sizeof(*old_rl), GFP_NOFS); if (!old_rl) { err =3D -ENOMEM; - if (ntfs_cluster_free_from_rl(vol, rlc)) { + err2 =3D ntfs_cluster_free_from_rl(vol, rlc); + if (err2) { ntfs_error(vol->sb, "Failed to free cluster allocation after runlist backup failure."); - NVolSetErrors(vol); + ntfs_report_file_metadata_error(VFS_I(ni), err2); } kvfree(rlc); goto out; @@ -5252,8 +5284,11 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64= vcn_start, s64 *lcn_start, if (IS_ERR(rl)) { ntfs_error(vol->sb, "Failed to merge runlists"); err =3D PTR_ERR(rl); - if (ntfs_cluster_free_from_rl(vol, rlc)) + err2 =3D ntfs_cluster_free_from_rl(vol, rlc); + if (err2) { ntfs_error(vol->sb, "Failed to free hot clusters."); + ntfs_report_file_metadata_error(VFS_I(ni), err2); + } kvfree(rlc); goto out; } @@ -5272,13 +5307,12 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s6= 4 vcn_start, s64 *lcn_start, ntfs_attr_reinit_search_ctx(ctx); err =3D ntfs_attr_update_mapping_pairs_locked(ni, 0, ni); if (err) { - int err2; - - err2 =3D ntfs_cluster_free(ni, vcn, clu_count, ctx); - if (err2 < 0 || err2 !=3D clu_count) { + freed =3D ntfs_cluster_free(ni, vcn, clu_count, ctx); + if (freed < 0 || freed !=3D clu_count) { ntfs_error(vol->sb, "Failed to free cluster allocation. Leaving inconsistent metadata.= \n"); - NVolSetErrors(vol); + err2 =3D freed < 0 ? freed : -EIO; + ntfs_report_file_metadata_error(VFS_I(ni), err2); goto out; } =20 @@ -5290,11 +5324,11 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s6= 4 vcn_start, s64 *lcn_start, ni->runlist.rl =3D old_rl; ni->runlist.count =3D old_rl_count; old_rl =3D NULL; - if (ntfs_attr_update_mapping_pairs_locked( - ni, 0, ni)) { + err2 =3D ntfs_attr_update_mapping_pairs_locked(ni, 0, ni); + if (err2) { ntfs_error(vol->sb, "Failed to restore mapping pairs after allocation rollback.\n"); - NVolSetErrors(vol); + ntfs_report_file_metadata_error(VFS_I(ni), err2); } } } else { diff --git a/fs/ntfs/attrlist.c b/fs/ntfs/attrlist.c index 1bbd2bc62c58..3c36e849a8ab 100644 --- a/fs/ntfs/attrlist.c +++ b/fs/ntfs/attrlist.c @@ -76,7 +76,7 @@ static int ntfs_attrlist_repack(struct inode *attr_vi, s64 old_alloc_size; size_t old_rl_count, new_rl_count; unsigned long flags; - int err, restore_err; + int err, free_err, restore_err; if (attr_ni->mft_no !=3D FILE_MFT || !NInoNonResident(attr_ni) || min_alloc_size < 0) return -EINVAL; @@ -127,7 +127,9 @@ static int ntfs_attrlist_repack(struct inode *attr_vi, new_rl_count =3D 2; =20 if (new_rl_count !=3D 2) { - ntfs_cluster_free_from_rl(vol, new_rl); + free_err =3D ntfs_cluster_free_from_rl(vol, new_rl); + if (free_err) + ntfs_report_file_metadata_error(attr_vi, free_err); kvfree(new_rl); err =3D -ENOSPC; goto out_free_data; @@ -157,11 +159,12 @@ static int ntfs_attrlist_repack(struct inode *attr_vi, goto restore_old_runlist; =20 /* The new mapping is now authoritative; release the old data runs. */ - if (ntfs_cluster_free_from_rl(vol, old_rl)) { + free_err =3D ntfs_cluster_free_from_rl(vol, old_rl); + if (free_err) { ntfs_error(vol->sb, "Failed to free old ATTRIBUTE_LIST extent: inode %#llx", (long long)attr_ni->mft_no); - NVolSetErrors(vol); + ntfs_report_file_metadata_error(attr_vi, free_err); } kvfree(old_rl); kvfree(data); @@ -182,10 +185,12 @@ static int ntfs_attrlist_repack(struct inode *attr_vi, if (restore_err) { ntfs_error(vol->sb, "Failed to restore ATTRIBUTE_LIST mapping pairs (%d)= ", restore_err); - NVolSetErrors(vol); + ntfs_report_file_metadata_error(attr_vi, restore_err); } =20 - ntfs_cluster_free_from_rl(vol, new_rl); + free_err =3D ntfs_cluster_free_from_rl(vol, new_rl); + if (free_err) + ntfs_report_file_metadata_error(attr_vi, free_err); kvfree(new_rl); err =3D err ? err : restore_err; =20 diff --git a/fs/ntfs/bitmap.c b/fs/ntfs/bitmap.c index 912fdcca8e01..54efcb054d0a 100644 --- a/fs/ntfs/bitmap.c +++ b/fs/ntfs/bitmap.c @@ -287,7 +287,7 @@ int __ntfs_bitmap_set_bits_in_run(struct inode *vi, con= st s64 start_bit, ntfs_error(vi->i_sb, "Failed to map subsequent page (error %i) and rollback failed (error %i= ). Aborting and leaving inconsistent metadata. Unmount and run chkdsk.", err, pos); - NVolSetErrors(NTFS_SB(vi->i_sb)); + ntfs_report_file_metadata_error(vi, pos); } return err; } diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 827313df0e28..a7a7ecf9d074 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -402,6 +402,18 @@ void ntfs_report_metadata_error(struct ntfs_volume *vo= l, int error) fserror_report_metadata(vol->sb, error, GFP_ATOMIC); } =20 +void ntfs_report_file_metadata_error(struct inode *inode, int error) +{ + struct ntfs_inode *ni =3D NTFS_I(inode); + + /* Attribute inodes share the file handle of their base inode. */ + if (NInoAttr(ni)) + inode =3D VFS_I(ni->ext.base_ntfs_ino); + NVolSetErrors(NTFS_SB(inode->i_sb)); + if (inode->i_sb->s_flags & SB_ACTIVE) + fserror_report_file_metadata(inode, error, GFP_ATOMIC); +} + void ntfs_handle_error(struct super_block *sb) { struct ntfs_volume *vol =3D NTFS_SB(sb); diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h index 5bcd0dd2a19d..366e9f5d0443 100644 --- a/fs/ntfs/volume.h +++ b/fs/ntfs/volume.h @@ -255,6 +255,7 @@ DEFINE_NVOL_BIT_OPS(NativeSymlinkRel) DEFINE_NVOL_BIT_OPS(SymlinkNative) =20 void ntfs_report_metadata_error(struct ntfs_volume *vol, int error); +void ntfs_report_file_metadata_error(struct inode *inode, int error); =20 static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr) { --=20 2.51.0 From nobody Thu Sep 24 12:09:31 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C10A742EEB7 for ; Thu, 24 Sep 2026 09:01:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240516; cv=none; b=iewxg8T/Rv3pmbto2lal2+CB4EcXyeoLjyCobAPbf3ZyY2BLy772n+FG8iFNbWfiZnsEuTiPuHPXnxJzV6AZxd56cZ4ms6qP0Kok5+CBVFO7n6ndG9qDJ6aaymbD7gFaNyq4XfgULuVs8etGslhmgmMFX8Y71YQZMgBWpdI4x/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240516; c=relaxed/simple; bh=nlEcWPrX1SR8a4NjnBkTRcdgsv/PhhC7lVxaC6KPQsk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Xis3qa7BrmTbSVpfc2D6wS0abjlLBUB5pg9PFNG7qahwWLJN37Y8KGcNBOTd5SkBJMj+89JwHaXZN7y4qmieCVcoReWIQ2zyWrxLMAL55nTkxky0bB16X6YYt0pk9v8QyT7rX3LEn3dve5u5dOI1hiZIxf5b6cR1UXIkJehKLl4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=mMkr35rG; arc=none smtp.client-ip=220.197.31.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="mMkr35rG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=Rh XZkhWFBAftr/JZYjGl3TJHEvx++2EVZdgYgNiY64o=; b=mMkr35rGrpyQwPb3uS LSh02gkcXnNN9ofWSPdCIVT7c+mdO2zpHBhEmdJ8ZgsnAYBzIyR66SGs0pRSpAUl aG5XQrgsIXGd7zYE9KXEv7p8VORgyQYFc1Fh0/qno6MTBYVCp4cBdXMB4tu6ueXF AvRHcaGLXzufcSebAZGuOGEbU= Received: from liubaolin-ThinkPad-E15-Gen-2 (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3H73Q5rRqL6EhAg--.34883S5; Thu, 24 Sep 2026 17:01:13 +0800 (CST) From: Baolin Liu To: linkinjeon@kernel.org, hyc.lee@gmail.com Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org, Baolin Liu Subject: [PATCH v3 3/6] ntfs: report inode metadata errors to fsnotify Date: Thu, 24 Sep 2026 17:00:59 +0800 Message-ID: <20260924090102.2865942-4-liubaolin12138@163.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260924090102.2865942-1-liubaolin12138@163.com> References: <20260924090102.2865942-1-liubaolin12138@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wD3H73Q5rRqL6EhAg--.34883S5 X-Coremail-Antispam: 1Uf129KBjvJXoWxGFWrGF1DurW8JrykJFy3XFb_yoW5Ar1xpF 93G3s3t34DtFy2gwn2vrWYv34akF1xG3y7uryrG3W7X3Z8tr1vqF40yF1I9FyFkr95K3yY qw1jkrWUur4UArDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jWJPiUUUUU= X-CM-SenderInfo: xolxutxrol0iasrtmqqrwthudrp/xtbC6hm3gmq05tkM5wAA3M Content-Type: text/plain; charset="utf-8" From: Baolin Liu Inode initialization, writeback and LogFile failures currently mark the volume as having errors without notifying filesystem health monitors. Report these failures against the affected VFS inode, using the base inode for attribute and index inodes. Preserve the existing treatment of allocation failures, unsupported formats and interrupted operations. Do not propagate reporting state between inode and attribute operations; fanotify can merge queued error events. Signed-off-by: Baolin Liu --- fs/ntfs/inode.c | 12 ++++++++---- fs/ntfs/logfile.c | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 9583b2c6c7a2..591aab2850be 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -1257,7 +1257,7 @@ static int ntfs_read_locked_inode(struct inode *vi) 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; } @@ -1486,7 +1486,7 @@ static int ntfs_read_locked_attr_inode(struct inode *= base_vi, struct inode *vi) base_ni->mft_no); if (err !=3D -ENOENT && err !=3D -ENOMEM && err !=3D -EINTR && err !=3D -ERESTARTSYS) - NVolSetErrors(vol); + ntfs_report_file_metadata_error(base_vi, err); return err; } =20 @@ -1741,7 +1741,7 @@ static int ntfs_read_locked_index_inode(struct inode = *base_vi, struct inode *vi) err, ni->mft_no, ni->name_len); if (err !=3D -EOPNOTSUPP && err !=3D -ENOMEM && err !=3D -EINTR && err !=3D -ERESTARTSYS) - NVolSetErrors(vol); + ntfs_report_file_metadata_error(base_vi, err); return err; } =20 @@ -2898,7 +2898,10 @@ 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 (err !=3D -EINTR && err !=3D -ERESTARTSYS) + ntfs_report_file_metadata_error(vi, err); + else + NVolSetErrors(ni->vol); } if (need_iput) iput(vi); @@ -2967,6 +2970,7 @@ static struct ntfs_inode *ntfs_extent_inode_open(stru= ct ntfs_inode *base_ni, seq_no !=3D le16_to_cpu(ni_mrec->sequence_number)) { ntfs_error(sb, "Found stale extent mft reference mft=3D%llu", ni->mft_no); + ntfs_report_file_metadata_error(VFS_I(base_ni), -EIO); unmap_mft_record(ni); return ERR_PTR(-EIO); } diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 1404664dacc0..6897faf849c1 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 =3D -EIO; err: kvfree(empty_buf); --=20 2.51.0 From nobody Thu Sep 24 12:09:31 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E2B84302FC for ; Thu, 24 Sep 2026 09:02:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240527; cv=none; b=ql6AX8ya9NyFmF9iwSwDoXufjpvVNtYh6dIt60rF94sje3jlkp/IFe5t6PTJ+sPpPa2ryNCX2cXzWtKjmUPCg38McrtK9ZgZqSY2YAsAW7nhGw+XYavZd5mk/y+M1YCgE7h6LtaPEXrBXSGwJ+ZhZ8HaKyekY8yblzN8AyWs6YA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240527; c=relaxed/simple; bh=29P/UPzRRz+wSW8YsgUOLEMqtIhjGVN4Ze1tHsTCo3Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=phVRubvrBvM+tYzaMBHZYv1lNdE7p21GE+OLHtUPabL2tEuRlDqwvB8hsLjR6iKGQjvIUywVR0qPs/m8wI7UqzpDczFbZuKkuEPAgxKeE1FnMAvmTQAO4CUfPZI0KPEx5PfLPZ8KrVMr/DHGDoNx3tzd+88SzLDipQkKTYqc4YM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=TLr7tYf1; arc=none smtp.client-ip=117.135.210.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="TLr7tYf1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=xx qamFhghV3me5i+3ZPwhqveYKpTL8j99C20bPCfdDc=; b=TLr7tYf13enMKpjPvE dEn43Prxfl5sj2tHRRl3ln/Pgd1nrittCQWfXjAsUgibhgpAfsoDDemG8FRn7El+ bkn+bTlw7qlfGOetOLG4QQvE0CT68TtwAyv/HA4PsVJY95J7FmQk0tdWjBp/zEex /XlE9U7bUa14SU7RHQ26gBJdM= Received: from liubaolin-ThinkPad-E15-Gen-2 (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3H73Q5rRqL6EhAg--.34883S6; Thu, 24 Sep 2026 17:01:14 +0800 (CST) From: Baolin Liu To: linkinjeon@kernel.org, hyc.lee@gmail.com Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org, Baolin Liu Subject: [PATCH v3 4/6] ntfs: report MFT metadata and recovery errors to fsnotify Date: Thu, 24 Sep 2026 17:01:00 +0800 Message-ID: <20260924090102.2865942-5-liubaolin12138@163.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260924090102.2865942-1-liubaolin12138@163.com> References: <20260924090102.2865942-1-liubaolin12138@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wD3H73Q5rRqL6EhAg--.34883S6 X-Coremail-Antispam: 1Uf129KBjvAXoW3KF1UXFWUXryftw43ZF45trb_yoW8Xry5Co ZIvrn0yw4kWw1jy34jywn8Xas8Aan8C3ykJry5CrsruFZ2gw1jg3yxKw43uay7W3WrWr42 9rn7twn5AFnxJFy7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxUx_-PUUUUU X-CM-SenderInfo: xolxutxrol0iasrtmqqrwthudrp/xtbCwhq3gmq05trZ+wAA3t Content-Type: text/plain; charset="utf-8" From: Baolin Liu MFT record corruption, stale extent references and allocation bitmap inconsistencies can leave files or volume metadata unusable without notifying filesystem health monitors. Report these errors against the affected base inode or the volume, as appropriate. Also report failures to release clusters, restore mapping pairs and attribute records, or restore MFT bitmap state during recovery. Keep recovery errors separate from the original operation's return value. Report each failed recovery where it is detected and leave event merging to fanotify, without passing reporting state through the mapping APIs. Signed-off-by: Baolin Liu --- fs/ntfs/mft.c | 158 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 62 deletions(-) diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 8bb8b4085c8b..a1b1c080b256 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -112,6 +112,7 @@ int ntfs_mft_record_check(const struct ntfs_volume *vol= , struct mft_record *m, static inline struct mft_record *map_mft_record_folio(struct ntfs_inode *n= i) { loff_t i_size; + struct ntfs_inode *base_ni; struct ntfs_volume *vol =3D ni->vol; struct inode *mft_vi =3D vol->mft_ino; struct folio *folio; @@ -170,7 +171,11 @@ static inline struct mft_record *map_mft_record_folio(= struct ntfs_inode *ni) kfree(ni->mrec); ni->mrec =3D NULL; folio =3D ERR_PTR(-EIO); - NVolSetErrors(vol); + if (ni->nr_extents >=3D 0) + base_ni =3D ni; + else + base_ni =3D ni->ext.base_ntfs_ino; + ntfs_report_file_metadata_error(VFS_I(base_ni), -EIO); } err_out: ni->folio =3D NULL; @@ -313,6 +318,7 @@ struct mft_record *map_extent_mft_record(struct ntfs_in= ode *base_ni, u64 mref, unmap_mft_record(ni); ntfs_error(base_ni->vol->sb, "Found stale extent mft reference! Corrupt filesystem. Run chkdsk."); + ntfs_report_file_metadata_error(VFS_I(base_ni), -EIO); return ERR_PTR(-EIO); } map_err_out: @@ -344,6 +350,7 @@ struct mft_record *map_extent_mft_record(struct ntfs_in= ode *base_ni, u64 mref, if (seq_no && (le16_to_cpu(m->sequence_number) !=3D seq_no)) { ntfs_error(base_ni->vol->sb, "Found stale extent mft reference! Corrupt filesystem. Run chkdsk."); + ntfs_report_file_metadata_error(VFS_I(base_ni), -EIO); destroy_ni =3D true; m =3D ERR_PTR(-EIO); goto unm_nolock_err_out; @@ -1340,8 +1347,9 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(s= truct ntfs_volume *vol) struct ntfs_attr_search_ctx *ctx =3D NULL; struct mft_record *mrec; struct attr_record *a =3D NULL; - int ret, mp_size; + int err, ret, mp_size; u32 old_alen =3D 0; + u16 mp_ofs; u8 *b, tb; struct { u8 added_cluster:1; @@ -1426,10 +1434,11 @@ static int ntfs_mft_bitmap_extend_allocation_nolock= (struct ntfs_volume *vol) if (IS_ERR(rl)) { up_write(&mftbmp_ni->runlist.lock); ntfs_error(vol->sb, "Failed to merge runlists for mft bitmap."); - if (ntfs_cluster_free_from_rl(vol, rl2)) { + err =3D ntfs_cluster_free_from_rl(vol, rl2); + if (err) { ntfs_error(vol->sb, "Failed to deallocate allocated cluster.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); } kvfree(rl2); return PTR_ERR(rl); @@ -1549,9 +1558,10 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(= struct ntfs_volume *vol) =20 restore_undo_alloc: ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(mftbmp_ni->type, mftbmp_ni->name, - mftbmp_ni->name_len, CASE_SENSITIVE, rl[1].vcn, NULL, - 0, ctx)) { + err =3D ntfs_attr_lookup(mftbmp_ni->type, mftbmp_ni->name, + mftbmp_ni->name_len, CASE_SENSITIVE, rl[1].vcn, + NULL, 0, ctx); + if (err) { ntfs_error(vol->sb, "Failed to find last attribute extent of mft bitmap attribute.%s", es); write_lock_irqsave(&mftbmp_ni->size_lock, flags); @@ -1564,7 +1574,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(s= truct ntfs_volume *vol) * The only thing that is now wrong is ->allocated_size of the * base attribute extent which chkdsk should be able to fix. */ - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); return ret; } a =3D ctx->attr; @@ -1583,31 +1593,36 @@ static int ntfs_mft_bitmap_extend_allocation_nolock= (struct ntfs_volume *vol) } /* Deallocate the cluster. */ down_write(&vol->lcnbmp_lock); - if (ntfs_bitmap_clear_bit(vol->lcnbmp_ino, lcn)) { + err =3D ntfs_bitmap_clear_bit(vol->lcnbmp_ino, lcn); + if (err) { ntfs_error(vol->sb, "Failed to free allocated cluster.%s", es); - NVolSetErrors(vol); - } else + ntfs_report_metadata_error(vol, err); + } else { ntfs_inc_free_clusters(vol, 1); + } up_write(&vol->lcnbmp_lock); if (status.mp_rebuilt) { - if (ntfs_mapping_pairs_build(vol, (u8 *)a + le16_to_cpu( - a->data.non_resident.mapping_pairs_offset), - old_alen - le16_to_cpu( - a->data.non_resident.mapping_pairs_offset), - rl2, ll, -1, NULL, NULL, NULL)) { + mp_ofs =3D le16_to_cpu(a->data.non_resident.mapping_pairs_offset); + err =3D ntfs_mapping_pairs_build(vol, (u8 *)a + mp_ofs, + old_alen - mp_ofs, rl2, ll, -1, + NULL, NULL, NULL); + if (err) { ntfs_error(vol->sb, "Failed to restore mapping pairs array.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); } - if (ntfs_attr_record_resize(ctx->mrec, a, old_alen)) { + err =3D ntfs_attr_record_resize(ctx->mrec, a, old_alen); + if (err) { ntfs_error(vol->sb, "Failed to restore attribute record.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); } mark_mft_record_dirty(ctx->ntfs_ino); - } else if (status.mp_extended && - ntfs_attr_update_mapping_pairs_locked(mftbmp_ni, 0, - mftbmp_ni)) { - ntfs_error(vol->sb, "Failed to restore mapping pairs.%s", es); - NVolSetErrors(vol); + } else if (status.mp_extended) { + err =3D ntfs_attr_update_mapping_pairs_locked(mftbmp_ni, 0, + mftbmp_ni); + if (err) { + ntfs_error(vol->sb, "Failed to restore mapping pairs.%s", es); + ntfs_report_metadata_error(vol, err); + } } if (ctx) ntfs_attr_put_search_ctx(ctx); @@ -1640,7 +1655,7 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(= struct ntfs_volume *vol) struct ntfs_attr_search_ctx *ctx; struct mft_record *mrec; struct attr_record *a; - int ret; + int err, ret; =20 ntfs_debug("Extending mft bitmap initialized (and data) size."); mft_ni =3D NTFS_I(vol->mft_ino); @@ -1700,20 +1715,23 @@ static int ntfs_mft_bitmap_extend_initialized_noloc= k(struct ntfs_volume *vol) mrec =3D map_mft_record(mft_ni); if (IS_ERR(mrec)) { ntfs_error(vol->sb, "Failed to map mft record.%s", es); - NVolSetErrors(vol); + err =3D PTR_ERR(mrec); + ntfs_report_metadata_error(vol, err); return ret; } ctx =3D ntfs_attr_get_search_ctx(mft_ni, mrec); if (unlikely(!ctx)) { ntfs_error(vol->sb, "Failed to get search context.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, -ENOMEM); goto unm_err_out; } - if (ntfs_attr_lookup(mftbmp_ni->type, mftbmp_ni->name, - mftbmp_ni->name_len, CASE_SENSITIVE, 0, NULL, 0, ctx)) { + err =3D ntfs_attr_lookup(mftbmp_ni->type, mftbmp_ni->name, + mftbmp_ni->name_len, CASE_SENSITIVE, 0, NULL, 0, + ctx); + if (err) { ntfs_error(vol->sb, "Failed to find first attribute extent of mft bitmap attribute.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); put_err_out: ntfs_attr_put_search_ctx(ctx); unm_err_out: @@ -1767,6 +1785,7 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(= struct ntfs_volume *vol) static int ntfs_mft_data_extend_allocation_nolock(struct ntfs_volume *vol) { s64 lcn; + s64 freed; s64 old_last_vcn; s64 min_nr, nr, ll; unsigned long flags; @@ -1775,8 +1794,9 @@ static int ntfs_mft_data_extend_allocation_nolock(str= uct ntfs_volume *vol) struct ntfs_attr_search_ctx *ctx =3D NULL; struct mft_record *mrec; struct attr_record *a =3D NULL; - int ret, mp_size; + int err, ret, mp_size; u32 old_alen =3D 0; + u16 mp_ofs; bool mp_rebuilt =3D false, mp_extended =3D false; size_t new_rl_count; =20 @@ -1863,10 +1883,11 @@ static int ntfs_mft_data_extend_allocation_nolock(s= truct ntfs_volume *vol) if (IS_ERR(rl)) { up_write(&mft_ni->runlist.lock); ntfs_error(vol->sb, "Failed to merge runlists for mft data attribute."); - if (ntfs_cluster_free_from_rl(vol, rl2)) { + err =3D ntfs_cluster_free_from_rl(vol, rl2); + if (err) { ntfs_error(vol->sb, "Failed to deallocate clusters from the mft data attribute.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); } kvfree(rl2); return PTR_ERR(rl); @@ -1986,8 +2007,9 @@ static int ntfs_mft_data_extend_allocation_nolock(str= uct ntfs_volume *vol) return 0; restore_undo_alloc: ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(mft_ni->type, mft_ni->name, mft_ni->name_len, - CASE_SENSITIVE, rl[1].vcn, NULL, 0, ctx)) { + err =3D ntfs_attr_lookup(mft_ni->type, mft_ni->name, mft_ni->name_len, + CASE_SENSITIVE, rl[1].vcn, NULL, 0, ctx); + if (err) { ntfs_error(vol->sb, "Failed to find last attribute extent of mft data attribute.%s", es); write_lock_irqsave(&mft_ni->size_lock, flags); @@ -2000,45 +2022,51 @@ static int ntfs_mft_data_extend_allocation_nolock(s= truct ntfs_volume *vol) * The only thing that is now wrong is ->allocated_size of the * base attribute extent which chkdsk should be able to fix. */ - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); return ret; } ctx->attr->data.non_resident.highest_vcn =3D cpu_to_le64(old_last_vcn - 1); undo_alloc: - if (ntfs_cluster_free(mft_ni, old_last_vcn, -1, ctx) < 0) { + freed =3D ntfs_cluster_free(mft_ni, old_last_vcn, -1, ctx); + if (freed < 0) { ntfs_error(vol->sb, "Failed to free clusters from mft data attribute.%s"= , es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, freed); } =20 - if (ntfs_rl_truncate_nolock(vol, &mft_ni->runlist, old_last_vcn)) { + err =3D ntfs_rl_truncate_nolock(vol, &mft_ni->runlist, old_last_vcn); + if (err) { ntfs_error(vol->sb, "Failed to truncate mft data attribute runlist.%s", = es); - NVolSetErrors(vol); - } - if (mp_extended && ntfs_attr_update_mapping_pairs(mft_ni, 0)) { - ntfs_error(vol->sb, "Failed to restore mapping pairs.%s", - es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); + } + if (mp_extended) { + err =3D ntfs_attr_update_mapping_pairs(mft_ni, 0); + if (err) { + ntfs_error(vol->sb, "Failed to restore mapping pairs.%s", + es); + ntfs_report_metadata_error(vol, err); + } } if (ctx) { a =3D ctx->attr; if (mp_rebuilt && !IS_ERR(ctx->mrec)) { - if (ntfs_mapping_pairs_build(vol, (u8 *)a + le16_to_cpu( - a->data.non_resident.mapping_pairs_offset), - old_alen - le16_to_cpu( - a->data.non_resident.mapping_pairs_offset), - rl2, ll, -1, NULL, NULL, NULL)) { + mp_ofs =3D le16_to_cpu(a->data.non_resident.mapping_pairs_offset); + err =3D ntfs_mapping_pairs_build(vol, (u8 *)a + mp_ofs, + old_alen - mp_ofs, rl2, ll, + -1, NULL, NULL, NULL); + if (err) { ntfs_error(vol->sb, "Failed to restore mapping pairs array.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); } - if (ntfs_attr_record_resize(ctx->mrec, a, old_alen)) { + err =3D ntfs_attr_record_resize(ctx->mrec, a, old_alen); + if (err) { ntfs_error(vol->sb, "Failed to restore attribute record.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, err); } mark_mft_record_dirty(ctx->ntfs_ino); } else if (IS_ERR(ctx->mrec)) { ntfs_error(vol->sb, "Failed to restore attribute search context.%s", es= ); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, PTR_ERR(ctx->mrec)); } ntfs_attr_put_search_ctx(ctx); } @@ -2270,8 +2298,8 @@ static int ntfs_mft_record_format(const struct ntfs_v= olume *vol, const s64 mft_n * * On error, the volume will be left in a consistent state and no record w= ill * be allocated. If rolling back a partial operation fails, we may leave = some - * inconsistent metadata in which case we set NVolErrors() so the volume is - * left dirty when unmounted. + * inconsistent metadata in which case we report the error so the volume is + * left dirty when unmounted and userspace is notified. * * Note, this function cannot make use of most of the normal functions, li= ke * for example for attribute resizing, etc, because when the run list over= flows @@ -2302,7 +2330,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, co= nst int mode, struct attr_record *a; pgoff_t index; unsigned int ofs; - int err; + int err, rollback_err; __le16 seq_no, usn; bool record_formatted =3D false, from_reserve =3D false, tail_alloc =3D f= alse; bool reserve_created =3D false; @@ -2706,7 +2734,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, co= nst int mode, folio_unlock(folio); kunmap_local(m); folio_put(folio); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, -EFSCORRUPTED); goto search_free_rec; } /* @@ -2862,9 +2890,12 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, c= onst int mode, if (!base_ni || base_ni->mft_no !=3D FILE_MFT) down_write(&vol->mftbmp_lock); undo_mftbmp_alloc_nolock: - if (!forced_reserved_record && ntfs_bitmap_clear_bit(vol->mftbmp_ino, bit= )) { + rollback_err =3D 0; + if (!forced_reserved_record) + rollback_err =3D ntfs_bitmap_clear_bit(vol->mftbmp_ino, bit); + if (rollback_err) { ntfs_error(vol->sb, "Failed to clear bit in mft bitmap.%s", es); - NVolSetErrors(vol); + ntfs_report_metadata_error(vol, rollback_err); } if ((from_reserve || reserve_created) && vol->mft_record_reserve_pos =3D=3D bit + 1) @@ -2901,7 +2932,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, co= nst int mode, int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni) { u64 mft_no; - int err; + int err, rollback_err; u16 seq_no; __le16 old_seq_no; __le64 old_base_mft_record; @@ -2995,8 +3026,11 @@ int ntfs_mft_record_free(struct ntfs_volume *vol, st= ruct ntfs_inode *ni) memalloc_flags =3D memalloc_nofs_save(); if (base_ni->mft_no !=3D FILE_MFT) down_write(&vol->mftbmp_lock); - if (ntfs_bitmap_set_bit(vol->mftbmp_ino, mft_no)) + rollback_err =3D ntfs_bitmap_set_bit(vol->mftbmp_ino, mft_no); + if (rollback_err) { ntfs_error(vol->sb, "ntfs_bitmap_set_bit failed in bitmap_rollback\n"); + ntfs_report_metadata_error(vol, rollback_err); + } if (base_ni->mft_no !=3D FILE_MFT) up_write(&vol->mftbmp_lock); memalloc_nofs_restore(memalloc_flags); --=20 2.51.0 From nobody Thu Sep 24 12:09:31 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 50CD83F6C24 for ; Thu, 24 Sep 2026 09:01:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240498; cv=none; b=UU71z4m0OEqpo8DblT2nKzkpbyLEJJPEWz0Dhu+V8kCSq9Rgz785dG1vZlHQaf9SjReJ2LH2B9rzii6m2xiiqidAsZrPYA44QziJJ6iyZbzfN9LQmVH92m615NNMrCRZsjqX59kHb4FeXkP1I4ZkIYazC6RgLyvXYX2oQl1IVFI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240498; c=relaxed/simple; bh=L5ZqUyzrf4+2nFL11gRp7aQvV9wnEqTL5bER3fteVEQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LZyFICLX8uBokU8l4ugJ+US7029M86Y6K4AVlmHIio6MzMfOIRoo5rsb1TU40/XndOhZydfaGZRLjdCRfPkCnBCPI+bvuy91h460NZ8Fw7nfXqwbKIYkCXL5xMqfQL0gnO2MdEfL8TI4DPiqgCNO7v35wMjrA9Kn/Y19t9NoX70= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=P7Dc3lHh; arc=none smtp.client-ip=220.197.31.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="P7Dc3lHh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=qm i3FHcbWjT1HDcn/gcvvyRGjaouytMYXJtS2GuTjXA=; b=P7Dc3lHhehjERVQMWX dF3znFXcLEexbKPSOGwAKbxHQs00aXrJJyQ8Z+ZG7KU9/5Ha+prS9FwTFDr1bu6V QqjE6hfpba2lB1bRRWNnjy+Wftp/sFftUL57KzBriwUgH1+QHL3FiJNGWS9uirg2 BqNF/GccW++jmZ1kYMacEMq9Q= Received: from liubaolin-ThinkPad-E15-Gen-2 (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3H73Q5rRqL6EhAg--.34883S7; Thu, 24 Sep 2026 17:01:16 +0800 (CST) From: Baolin Liu To: linkinjeon@kernel.org, hyc.lee@gmail.com Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org, Baolin Liu Subject: [PATCH v3 5/6] ntfs: report MFT writeback errors to fsnotify Date: Thu, 24 Sep 2026 17:01:01 +0800 Message-ID: <20260924090102.2865942-6-liubaolin12138@163.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260924090102.2865942-1-liubaolin12138@163.com> References: <20260924090102.2865942-1-liubaolin12138@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wD3H73Q5rRqL6EhAg--.34883S7 X-Coremail-Antispam: 1Uf129KBjvJXoWxZw1kJF4kKrWrJrWfAF4UXFb_yoW5Kw45pF Z8G3s3KrWDtr47Kwn7trW2v3Wa934xKa17CrykG3WI9wn8Kr1jqa10grWSgFWFkr93J3y8 Ja1qkrZ8CF1UAr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jcrc-UUUUU= X-CM-SenderInfo: xolxutxrol0iasrtmqqrwthudrp/xtbC6Ry4g2q05tz3VwAA3K Content-Type: text/plain; charset="utf-8" From: Baolin Liu 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 --- 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 =3D blk_status_to_errno(bio->bi_status); else err =3D 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_volu= me *vol, u64 mirror_size; unsigned int mirror_ofs; u8 *src, *dst; - int err; + int err =3D -EIO; =20 if (unlikely(!vol->mftmirr_ino)) - return -EIO; + goto out_report; =20 mirror_size =3D (u64)vol->mftmirr_size * vol->mft_record_size; if (mirror_file_ofs >=3D 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; =20 mirror =3D 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 =3D PTR_ERR(mirror); + goto out_report; + } =20 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; } =20 @@ -815,8 +822,14 @@ int write_mft_record_nolock(struct ntfs_inode *ni, str= uct mft_record *m, int syn mark_mft_record_dirty(ni); if (!sync) err =3D 0; - } else - NVolSetErrors(vol); + } else { + struct ntfs_inode *base_ni =3D ni; + + if (ni->nr_extents < 0) + base_ni =3D ni->ext.base_ntfs_ino; + mapping_set_error(folio->mapping, err); + ntfs_report_file_metadata_error(VFS_I(base_ni), err); + } return err; } =20 @@ -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); } =20 @@ -3346,6 +3359,7 @@ static int ntfs_write_mft_block(struct folio *folio, = struct writeback_control *w ctx->error =3D -EIO; redirty =3D true; err =3D -EIO; + ntfs_mft_write_error(vol, mapping, err); break; } } --=20 2.51.0 From nobody Thu Sep 24 12:09:31 2026 Received: from m16.mail.163.com (m16.mail.163.com [220.197.31.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04DB3441027 for ; Thu, 24 Sep 2026 09:02:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.2 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240532; cv=none; b=ACLXrcVuaSjPuCrk3afWIT/PlTXhSHQrGBvrzXekqvZGH//CeKvJdA0PxG/NY6a5UwvQHFStkti5Ab15fWepiGYNf13WkT/9wD5outLhR8ZnPgF3R8KIBCw2NODUcQEJXSy4b5eanACOtZEEpoV+XpETcNMuAmyRMytUjCZmeEw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790240532; c=relaxed/simple; bh=9vNjSL90J4yX9kw1EA3qLyad04ZhUpY0Tkov9iZfDhE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qPVF9rL84cAvDdjoJmGeMCz9V8FYSmo6srpgZ95VCoAHqk8kNnYebD5V3tZNUZUCFKdAZcmAdOc/TQJddYprp5q9zYc0naWAtjdmuOPXlCxMfkobjC0rKbASbu0HoyRK+zdeFQtZJFG9xqLflTQo1EsCan8cFQaelY/7USh+zls= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=o1HW+vr2; arc=none smtp.client-ip=220.197.31.2 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="o1HW+vr2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:To:Subject:Date:Message-ID:MIME-Version; bh=ul cahvz8a6nzlF4ykRPpW3Il7se8hI2AGVvN4y2l3qE=; b=o1HW+vr2OsMyIUMO4W JJV2I/ccg0RTYSUATHgrQXDdaAKghCfgJ1nQAmw3uthXE5ugwKu7gocaJQXbbR7M RBbhJVTzJoLhYQYh9OIh42oPBbzFiG2AhrW0DbH8k5g1Vp4+v9SkMvD3zrhstJl+ 9lFp8aj5p2lTJgYyDgACQhgmA= Received: from liubaolin-ThinkPad-E15-Gen-2 (unknown []) by gzga-smtp-mtada-g1-2 (Coremail) with SMTP id _____wD3H73Q5rRqL6EhAg--.34883S8; Thu, 24 Sep 2026 17:01:17 +0800 (CST) From: Baolin Liu To: linkinjeon@kernel.org, hyc.lee@gmail.com Cc: ntfs@lists.linux.dev, linux-kernel@vger.kernel.org, Baolin Liu Subject: [PATCH v3 6/6] ntfs: report shutdown errors to fsnotify Date: Thu, 24 Sep 2026 17:01:02 +0800 Message-ID: <20260924090102.2865942-7-liubaolin12138@163.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260924090102.2865942-1-liubaolin12138@163.com> References: <20260924090102.2865942-1-liubaolin12138@163.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: _____wD3H73Q5rRqL6EhAg--.34883S8 X-Coremail-Antispam: 1Uf129KBjvJXoW7ZFyDXr4DZFyxJw4kJFW7CFg_yoW8uF17pF 97Ar9xtwn2qF129wsFyw43A3WSvFyku34UKw1UGw1Igw1kKr10qF4kKF1F9F1F9a4F9w48 Zw1UK398uFW7ZrUanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07jcrc-UUUUU= X-CM-SenderInfo: xolxutxrol0iasrtmqqrwthudrp/xtbC6R24g2q05t33iwAA3W Content-Type: text/plain; charset="utf-8" From: Baolin Liu Notify FAN_FS_ERROR listeners when NTFS enters forced shutdown after FS_IOC_SHUTDOWN or backing-device removal. Keep the shutdown state transition and notification together in a dedicated helper. Signed-off-by: Baolin Liu --- fs/ntfs/super.c | 12 +++++++++--- fs/ntfs/volume.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index a7a7ecf9d074..a0d3934ef6c8 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -414,6 +414,12 @@ void ntfs_report_file_metadata_error(struct inode *ino= de, int error) fserror_report_file_metadata(inode, error, GFP_ATOMIC); } =20 +void ntfs_report_shutdown(struct ntfs_volume *vol) +{ + NVolSetShutdown(vol); + fserror_report_shutdown(vol->sb, GFP_ATOMIC); +} + void ntfs_handle_error(struct super_block *sb) { struct ntfs_volume *vol =3D NTFS_SB(sb); @@ -430,7 +436,7 @@ void ntfs_handle_error(struct super_block *sb) sb->s_id); } else if (vol->on_errors =3D=3D ON_ERRORS_CONTINUE) { if (errseq_check(&sb->s_wb_err, vol->wb_err) =3D=3D -ENODEV) { - NVolSetShutdown(vol); + ntfs_report_shutdown(vol); vol->wb_err =3D sb->s_wb_err; } } @@ -2086,10 +2092,10 @@ int ntfs_force_shutdown(struct super_block *sb, u32= flags) if (ret) return ret; bdev_thaw(sb->s_bdev); - NVolSetShutdown(vol); + ntfs_report_shutdown(vol); break; case FS_SHUTDOWN_FLAGS_NOLOGFLUSH: - NVolSetShutdown(vol); + ntfs_report_shutdown(vol); break; default: return -EINVAL; diff --git a/fs/ntfs/volume.h b/fs/ntfs/volume.h index 366e9f5d0443..648fe8991304 100644 --- a/fs/ntfs/volume.h +++ b/fs/ntfs/volume.h @@ -256,6 +256,7 @@ DEFINE_NVOL_BIT_OPS(SymlinkNative) =20 void ntfs_report_metadata_error(struct ntfs_volume *vol, int error); void ntfs_report_file_metadata_error(struct inode *inode, int error); +void ntfs_report_shutdown(struct ntfs_volume *vol); =20 static inline void ntfs_inc_free_clusters(struct ntfs_volume *vol, s64 nr) { --=20 2.51.0