git: 8ff663dde22f - main - ufs: make fdatasync(2) and O_DSYNC writes update the inode

From: Maxim Sobolev <sobomax_at_FreeBSD.org>
Date: Tue, 13 Oct 2026 04:29:52 UTC
The branch main has been updated by sobomax:

URL: https://cgit.FreeBSD.org/src/commit/?id=8ff663dde22fe9f50ba5d71d0237bec9b9b44683

commit 8ff663dde22fe9f50ba5d71d0237bec9b9b44683
Author:     Maxim Sobolev <sobomax@FreeBSD.org>
AuthorDate: 2026-10-13 02:39:05 +0000
Commit:     Maxim Sobolev <sobomax@FreeBSD.org>
CommitDate: 2026-10-13 04:28:32 +0000

    ufs: make fdatasync(2) and O_DSYNC writes update the inode
    
    ffs_syncvnode() in the DATA_ONLY case and ffs_write() for IO_DATASYNC
    decide whether the inode has to be written by testing IN_SIZEMOD and
    IN_IBLKDATA against ip->i_flags, the chflags(2) word, instead of the
    in-core state ip->i_flag.  IN_SIZEMOD and IN_IBLKDATA alias UF_READONLY
    and UF_ARCHIVE, so for ordinary files the test was always false: after
    an fdatasync() or an O_DSYNC write that extended a file or filled a
    hole, the data blocks were on disk but the inode size and block pointers
    were not, and a crash before the syncer got to the inode lost the
    "synced" data.  Files with uarchive or urdonly set got a synchronous
    inode write on every call instead.
    
    journal_mount() has the same mixup and sets IN_MODIFIED in i_flags,
    which leaves UF_OPAQUE set on the in-core .sujournal inode.  The
    synchronous ffs_update() that follows writes the inode regardless, so
    only the stray flag is fixed here.
    
    Fixes:  7428630b757 ("UFS: write inode block for fdatasync(2) if pointers in inode where allocated")
    Fixes:  52488b51489 ("Further evaluation of the POSIX spec for fdatasync()...")
    Fixes:  e7347be9e34 ("ffs: Support O_DSYNC.")
    Fixes:  113db2dddb7 ("Merge soft-updates journaling from projects/suj/head into head.")
    
    Sponsored by:   Sippy Software, Inc.
    Reviewed by:    kib
    Tested by:      pho
    Differential Revision:  https://reviews.freebsd.org/D60134
    MFC after:      1 month
---
 sys/ufs/ffs/ffs_softdep.c | 2 +-
 sys/ufs/ffs/ffs_vnops.c   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index a83f7ee9b91c..a7068f43a800 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -2976,7 +2976,7 @@ journal_mount(struct mount *mp,
 	 */
 	if (fs->fs_clean) {
 		DIP_SET(ip, i_modrev, fs->fs_mtime);
-		ip->i_flags |= IN_MODIFIED;
+		ip->i_flag |= IN_MODIFIED;
 		ffs_update(vp, 1);
 	}
 out:
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index ee495fe3888c..be708d07a2ca 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -458,7 +458,7 @@ next_locked:
 			error = ffs_update(vp, 1);
 		if (DOINGSUJ(vp))
 			softdep_journal_fsync(VTOI(vp));
-	} else if ((ip->i_flags & (IN_SIZEMOD | IN_IBLKDATA)) != 0) {
+	} else if ((ip->i_flag & (IN_SIZEMOD | IN_IBLKDATA)) != 0) {
 		error = ffs_update(vp, 1);
 	}
 	if (error == 0 && unlocked)
@@ -1044,7 +1044,7 @@ ffs_write(
 		}
 	} else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
 		if (!(ioflag & IO_DATASYNC) ||
-		    (ip->i_flags & (IN_SIZEMOD | IN_IBLKDATA)))
+		    (ip->i_flag & (IN_SIZEMOD | IN_IBLKDATA)))
 			error = ffs_update(vp, 1);
 		if (ffs_fsfail_cleanup(VFSTOUFS(vp->v_mount), error))
 			error = ENXIO;