ntfs: fail remount on sync errors and keep the dirty bit on SB_FORCE

ntfs_reconfigure() currently ignores sync_filesystem() errors, allowing
a regular read-only remount to succeed even when dirty data was not
synced. Check the error and fail regular remounts, leaving the
superblock read-write so ntfs_put_super() can retry at unmount.

SB_FORCE does not wait for writers already in progress, so it must not
clear the on-disk dirty bit. Warn and continue on sync errors for
SB_FORCE. A forced remount updates the dirty state only when errors
have been recorded, and never clears the dirty bit. Skip the commit if
that state update fails, since the in-memory flags may be inconsistent.

Reported-by: Hyunchul Lee <hyc.lee@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
Reviewed-by: Hyunchul Lee <hyc.lee@gmail.com>
Reviewed-by: Baolin Liu <liubaolin@kylinos.cn>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Hongling Zeng 2026-09-15 16:32:52 +08:00 committed by Namjae Jeon
parent 1a3883b368
commit 17a1edda75

View File

@ -273,7 +273,13 @@ static int ntfs_reconfigure(struct fs_context *fc)
ntfs_debug("Entering with remount");
sync_filesystem(sb);
err = sync_filesystem(sb);
if (err) {
ntfs_warning(sb, "Failed to sync the filesystem.");
/* A forced remount must still turn the superblock read-only. */
if (!(fc->sb_flags & SB_FORCE))
return err;
}
/*
* For the read-write compiled driver, if we are remounting read-write,
@ -336,11 +342,20 @@ static int ntfs_reconfigure(struct fs_context *fc)
* or flush fails the remount, leaving the superblock
* read-write so ntfs_put_super() retries at unmount.
*/
err = ntfs_sync_volume_dirty_state(vol);
if (err) {
ntfs_warning(sb,
"Failed to update dirty bit in volume information flags. Run chkdsk.");
return err;
/*
* A forced remount does not drain writers in progress,
* so one may still be modifying metadata when the flags
* are committed: never clear the dirty bit then; if
* errors have been recorded, the update preserves or
* sets it; otherwise, skip the update entirely.
*/
if (!(fc->sb_flags & SB_FORCE) || NVolErrors(vol)) {
err = ntfs_sync_volume_dirty_state(vol);
if (err) {
ntfs_warning(sb,
"Failed to update dirty bit in volume information flags. Run chkdsk.");
return err;
}
}
if (NInoDirty(NTFS_I(vol->vol_ino))) {
/* ntfs_commit_inode() would discard the error. */