[PATCH v10 5/6] ntfs: do not clear the volume dirty bit during sync
From: Hongling Zeng
Date: Sun Sep 13 2026 - 23:13:12 EST
ntfs_sync_fs() clears VOLUME_IS_DIRTY while the volume is still mounted
read-write, so a sync running concurrently with an in-flight metadata
modification can clear and persist a bit that was just set: the
modification then lands on a volume that is clean on disk, and a crash
does not run chkdsk. Closing this from the writer side would mean
holding the $Volume mrec_lock across the whole operation.
Drop the ntfs_sync_fs() persistence point and leave the clearing to the
remount-to-read-only path, which the VFS reaches only after
sb_prepare_remount_readonly() has drained in-flight writers, and to
ntfs_put_super(), which runs after evict_inodes() on a quiesced
filesystem. A mounted read-write volume now keeps the dirty bit until
it is dismounted cleanly, which matches the NTFS semantics; the cost is
a needless chkdsk if the machine crashes between a sync and the unmount.
Reported-by: Baolin Liu <liubaolin@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Hongling Zeng <zenghongling@xxxxxxxxxx>
---
fs/ntfs/super.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 3574c224fe28..f58b9cd86b27 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -1963,11 +1963,14 @@ static int ntfs_sync_fs(struct super_block *sb, int wait)
if (!wait)
return 0;
- /* If there are some dirty buffers in the bdev inode */
- if (ntfs_sync_volume_dirty_state(vol)) {
- ntfs_warning(sb, "Failed to sync dirty bit in volume information flags. Run chkdsk.");
- err = -EIO;
- }
+ /*
+ * The volume dirty bit is deliberately not cleared here: a sync
+ * running concurrently with an in-flight modification could clear
+ * and persist a bit that was just set, leaving the modification
+ * on a volume that is clean on disk. The bit is only updated at
+ * quiescent state transitions: remounting read-only and clean
+ * unmount.
+ */
sync_inodes_sb(sb);
sync_blockdev(sb->s_bdev);
blkdev_issue_flush(sb->s_bdev);
--
2.25.1