mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
ufs: do not let a rolled back inode write end a data-only sync
With soft updates, ffs_syncvnode() writes the inode between its passes while buffers are still dirty. That write can go out with new block pointers rolled back, for instance a new indirect block whose contents are only written in a later pass, yet ffs_update() clears IN_SIZEMOD and IN_IBLKDATA because the write was synchronous. A data-only sync then decides at the end that the inode need not be written, and fdatasync(2) or an O_DSYNC write that allocated the first indirect block returned with the on-disk inode not pointing to it. Note on entry whether a data-only sync has to write the inode, and base the final write, done once all dependencies are flushed, on that alone: nothing else can set IN_SIZEMOD or IN_IBLKDATA meanwhile, as the vnode is locked. A full sync always writes the inode last and was not affected. Sponsored by: Sippy Software, Inc. Reviewed by: kib Tested by: pho Differential Revision: https://reviews.freebsd.org/D60134 MFC after: 1 month
This commit is contained in:
1 parent
26d84bb8bf
commit
e8534ba3ad
1 file changed
+9
-2
@@ -271,11 +271,18 @@ ffs_syncvnode(struct vnode *vp, int waitfor, int flags)
|
||||
struct buf *bp, *nbp;
|
||||
ufs_lbn_t lbn;
|
||||
int error, passes, wflag;
|
||||
bool unlocked, wait;
|
||||
bool inoupdt, unlocked, wait;
|
||||
|
||||
ip = VTOI(vp);
|
||||
bo = &vp->v_bufobj;
|
||||
ump = VFSTOUFS(vp->v_mount);
|
||||
/*
|
||||
* With soft updates, the passes below may write the inode while
|
||||
* new block pointers in it are still rolled back. That clears
|
||||
* IN_SIZEMOD and IN_IBLKDATA all the same, so note up front
|
||||
* whether a data-only sync has to write the inode.
|
||||
*/
|
||||
inoupdt = (ip->i_flag & (IN_SIZEMOD | IN_IBLKDATA)) != 0;
|
||||
#ifdef WITNESS
|
||||
wflag = IS_SNAPSHOT(ip) ? LK_NOWITNESS : 0;
|
||||
#else
|
||||
@@ -442,7 +449,7 @@ next_locked:
|
||||
error = ffs_update(vp, 1);
|
||||
if (DOINGSUJ(vp))
|
||||
softdep_journal_fsync(VTOI(vp));
|
||||
} else if ((ip->i_flag & (IN_SIZEMOD | IN_IBLKDATA)) != 0) {
|
||||
} else if (inoupdt) {
|
||||
error = ffs_update(vp, 1);
|
||||
}
|
||||
if (error == 0 && unlocked)
|
||||
|
||||
Reference in new issue
Block a user