From cef48ebea8928f9a0455a9b60ec8411a4c6a17d8 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 4 Jun 2020 12:23:15 +0000 Subject: [PATCH] UFS: write inode block for fdatasync(2) if pointers in inode where allocated The fdatasync() description in POSIX specifies that all I/O operations shall be completed as defined for synchronized I/O data integrity completion. and then the explanation of Synchronized I/O Data Integrity Completion says The write is complete only when the data specified in the write request is successfully transferred and all file system information required to retrieve the data is successfully transferred. For UFS this means that all pointers must be on disk. Indirect pointers already contribute to the list of dirty data blocks, so only direct blocks and root pointers to indirect blocks, both of which reside in the inode block, should be taken care of. In ffs_balloc(), mark the inode with the new flag IN_IBLKDATA that specifies that ffs_syncvnode(DATA_ONLY) needs a call to ffs_update() to flush the inode block. Reviewed by: mckusick Discussed with: tmunro Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D25072 --- sys/ufs/ffs/ffs_balloc.c | 13 +++++++------ sys/ufs/ffs/ffs_inode.c | 2 +- sys/ufs/ffs/ffs_vnops.c | 2 ++ sys/ufs/ufs/inode.h | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 8b8d51b98476..49cd37b076db 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -224,7 +224,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, nsize, 0, bp); } dp->di_db[lbn] = dbtofsb(fs, bp->b_blkno); - UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE); + UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | IN_IBLKDATA); *bpp = bp; return (0); } @@ -280,7 +280,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, } allocib = &dp->di_ib[indirs[0].in_off]; *allocib = nb; - UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE); + UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | IN_IBLKDATA); } /* * Fetch through the indirect blocks, allocating as necessary. @@ -721,7 +721,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, nsize, 0, bp); } dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno); - UFS_INODE_SET_FLAG(ip, IN_CHANGE); + UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_IBLKDATA); *bpp = bp; return (0); } @@ -750,7 +750,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, ip->i_size = smalllblktosize(fs, nb + 1); dp->di_size = ip->i_size; dp->di_db[nb] = dbtofsb(fs, bp->b_blkno); - UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE); + UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | + IN_IBLKDATA); if (flags & IO_SYNC) bwrite(bp); else @@ -820,7 +821,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, nsize, 0, bp); } dp->di_db[lbn] = dbtofsb(fs, bp->b_blkno); - UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE); + UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | IN_IBLKDATA); *bpp = bp; return (0); } @@ -877,7 +878,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, } allocib = &dp->di_ib[indirs[0].in_off]; *allocib = nb; - UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE); + UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE | IN_IBLKDATA); } /* * Fetch through the indirect blocks, allocating as necessary. diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index dfe2b9f12965..b8e637207e4c 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -94,7 +94,7 @@ ffs_update(vp, waitfor) ip = VTOI(vp); if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0) return (0); - ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED); + ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED | IN_IBLKDATA); fs = ITOFS(ip); if (fs->fs_ronly && ITOUMP(ip)->um_fsckpid == 0) return (0); diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 7c1df1f50e31..979497f707ef 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -416,6 +416,8 @@ next: error = ffs_update(vp, 1); if (DOINGSUJ(vp)) softdep_journal_fsync(VTOI(vp)); + } else if ((ip->i_flags & IN_IBLKDATA) != 0) { + error = ffs_update(vp, 1); } return (error); } diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 2bab55ab9967..d0be73c76d44 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -129,13 +129,13 @@ struct inode { suspension finished */ #define IN_EA_LOCKED 0x0080 #define IN_EA_LOCKWAIT 0x0100 - #define IN_TRUNCATED 0x0200 /* Journaled truncation pending. */ - #define IN_UFS2 0x0400 /* UFS2 vs UFS1 */ +#define IN_IBLKDATA 0x0800 /* datasync requires inode block + update */ #define PRINT_INODE_FLAGS "\20\20b16\17b15\16b14\15b13" \ - "\14b12\13is_ufs2\12truncated\11ea_lockwait\10ea_locked" \ + "\14iblkdata\13is_ufs2\12truncated\11ea_lockwait\10ea_locked" \ "\7lazyaccess\6lazymod\5needsync\4modified\3update\2change\1access" #define UFS_INODE_FLAG_LAZY_MASK \