svn commit: r362049 - in stable/12/sys/ufs: ffs ufs
Konstantin Belousov
kib at FreeBSD.org
Thu Jun 11 11:36:52 UTC 2020
Author: kib
Date: Thu Jun 11 11:36:49 2020
New Revision: 362049
URL: https://svnweb.freebsd.org/changeset/base/362049
Log:
MFC r361785, r361801 (by mckusick), r361803 (by se), r361814 (by mckusick),
r361875 (by mckusick):
Fixes for UFS fdatasync(2).
Modified:
stable/12/sys/ufs/ffs/ffs_alloc.c
stable/12/sys/ufs/ffs/ffs_balloc.c
stable/12/sys/ufs/ffs/ffs_inode.c
stable/12/sys/ufs/ffs/ffs_snapshot.c
stable/12/sys/ufs/ffs/ffs_softdep.c
stable/12/sys/ufs/ffs/ffs_vnops.c
stable/12/sys/ufs/ufs/inode.h
stable/12/sys/ufs/ufs/ufs_lookup.c
stable/12/sys/ufs/ufs/ufs_vnops.c
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- stable/12/sys/ufs/ffs/ffs_alloc.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ffs/ffs_alloc.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -3248,7 +3248,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
break;
ip = VTOI(vp);
DIP_SET(ip, i_size, cmd.size);
- ip->i_flag |= IN_CHANGE | IN_MODIFIED;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_MODIFIED;
error = ffs_update(vp, 1);
vput(vp);
break;
Modified: stable/12/sys/ufs/ffs/ffs_balloc.c
==============================================================================
--- stable/12/sys/ufs/ffs/ffs_balloc.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ffs/ffs_balloc.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -154,7 +154,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, i
ip->i_size = smalllblktosize(fs, nb + 1);
dp->di_size = ip->i_size;
dp->di_db[nb] = dbtofsb(fs, bp->b_blkno);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE |
+ IN_IBLKDATA;
if (flags & IO_SYNC)
bwrite(bp);
else if (DOINGASYNC(vp))
@@ -226,7 +227,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, i
nsize, 0, bp);
}
dp->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE | IN_IBLKDATA;
*bpp = bp;
return (0);
}
@@ -282,7 +283,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, i
}
allocib = &dp->di_ib[indirs[0].in_off];
*allocib = nb;
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE | IN_IBLKDATA;
}
/*
* Fetch through the indirect blocks, allocating as necessary.
@@ -648,7 +649,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, i
dp->di_extsize = smalllblktosize(fs, nb + 1);
dp->di_extb[nb] = dbtofsb(fs, bp->b_blkno);
bp->b_xflags |= BX_ALTDATA;
- ip->i_flag |= IN_CHANGE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_IBLKDATA;
if (flags & IO_SYNC)
bwrite(bp);
else
@@ -724,7 +725,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, i
nsize, 0, bp);
}
dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno);
- ip->i_flag |= IN_CHANGE;
+ ip->i_flag |= IN_CHANGE | IN_IBLKDATA;
*bpp = bp;
return (0);
}
@@ -753,7 +754,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, i
ip->i_size = smalllblktosize(fs, nb + 1);
dp->di_size = ip->i_size;
dp->di_db[nb] = dbtofsb(fs, bp->b_blkno);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE |
+ IN_IBLKDATA;
if (flags & IO_SYNC)
bwrite(bp);
else
@@ -825,7 +827,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, i
nsize, 0, bp);
}
dp->di_db[lbn] = dbtofsb(fs, bp->b_blkno);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE | IN_IBLKDATA;
*bpp = bp;
return (0);
}
@@ -882,7 +884,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, i
}
allocib = &dp->di_ib[indirs[0].in_off];
*allocib = nb;
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_CHANGE | IN_UPDATE | IN_IBLKDATA;
}
/*
* Fetch through the indirect blocks, allocating as necessary.
Modified: stable/12/sys/ufs/ffs/ffs_inode.c
==============================================================================
--- stable/12/sys/ufs/ffs/ffs_inode.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ffs/ffs_inode.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -94,6 +94,26 @@ ffs_update(vp, waitfor)
if ((ip->i_flag & IN_MODIFIED) == 0 && waitfor == 0)
return (0);
ip->i_flag &= ~(IN_LAZYACCESS | IN_LAZYMOD | IN_MODIFIED);
+ /*
+ * The IN_SIZEMOD and IN_IBLKDATA flags indicate changes to the
+ * file size and block pointer fields in the inode. When these
+ * fields have been changed, the fsync() and fsyncdata() system
+ * calls must write the inode to ensure their semantics that the
+ * file is on stable store.
+ *
+ * The IN_SIZEMOD and IN_IBLKDATA flags cannot be cleared until
+ * a synchronous write of the inode is done. If they are cleared
+ * on an asynchronous write, then the inode may not yet have been
+ * written to the disk when an fsync() or fsyncdata() call is done.
+ * Absent these flags, these calls would not know that they needed
+ * to write the inode. Thus, these flags only can be cleared on
+ * synchronous writes of the inode. Since the inode will be locked
+ * for the duration of the I/O that writes it to disk, no fsync()
+ * or fsyncdata() will be able to run before the on-disk inode
+ * is complete.
+ */
+ if (waitfor)
+ ip->i_flag &= ~(IN_SIZEMOD | IN_IBLKDATA);
fs = ITOFS(ip);
if (fs->fs_ronly && ITOUMP(ip)->um_fsckpid == 0)
return (0);
@@ -268,7 +288,7 @@ ffs_truncate(vp, length, flags, cred)
oldblks[i] = ip->i_din2->di_extb[i];
ip->i_din2->di_extb[i] = 0;
}
- ip->i_flag |= IN_CHANGE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
if ((error = ffs_update(vp, waitforupdate)))
return (error);
for (i = 0; i < UFS_NXADDR; i++) {
@@ -292,7 +312,7 @@ ffs_truncate(vp, length, flags, cred)
bzero(SHORTLINK(ip), (u_int)ip->i_size);
ip->i_size = 0;
DIP_SET(ip, i_size, 0);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
if (needextclean)
goto extclean;
return (ffs_update(vp, waitforupdate));
@@ -332,7 +352,7 @@ ffs_truncate(vp, length, flags, cred)
bdwrite(bp);
else
bawrite(bp);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
return (ffs_update(vp, waitforupdate));
}
/*
@@ -418,6 +438,7 @@ ffs_truncate(vp, length, flags, cred)
if (blkno != 0 && offset == 0) {
ip->i_size = length;
DIP_SET(ip, i_size, length);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
} else {
lbn = lblkno(fs, length);
flags |= BA_CLRBUF;
@@ -452,6 +473,7 @@ ffs_truncate(vp, length, flags, cred)
bdwrite(bp);
else
bawrite(bp);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
}
/*
* Calculate index into inode's block list of
@@ -501,6 +523,7 @@ ffs_truncate(vp, length, flags, cred)
}
ip->i_size = osize;
DIP_SET(ip, i_size, osize);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
error = vtruncbuf(vp, length, fs->fs_bsize);
if (error && (allerror == 0))
@@ -567,6 +590,7 @@ ffs_truncate(vp, length, flags, cred)
oldspace = blksize(fs, ip, lastblock);
ip->i_size = length;
DIP_SET(ip, i_size, length);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
newspace = blksize(fs, ip, lastblock);
if (newspace == 0)
panic("ffs_truncate: newspace");
@@ -607,7 +631,7 @@ done:
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
else /* sanity */
DIP_SET(ip, i_blocks, 0);
- ip->i_flag |= IN_CHANGE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
#ifdef QUOTA
(void) chkdq(ip, -blocksreleased, NOCRED, FORCE);
#endif
Modified: stable/12/sys/ufs/ffs/ffs_snapshot.c
==============================================================================
--- stable/12/sys/ufs/ffs/ffs_snapshot.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ffs/ffs_snapshot.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -317,7 +317,7 @@ restart:
goto out;
ip->i_size = lblktosize(fs, (off_t)numblks);
DIP_SET(ip, i_size, ip->i_size);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
error = readblock(vp, bp, numblks - 1);
bawrite(bp);
if (error != 0)
Modified: stable/12/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- stable/12/sys/ufs/ffs/ffs_softdep.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ffs/ffs_softdep.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -6654,6 +6654,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
}
ip->i_size = length;
DIP_SET(ip, i_size, ip->i_size);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
datablocks = DIP(ip, i_blocks) - extblocks;
if (length != 0)
datablocks = blkcount(fs, datablocks, length);
@@ -6664,6 +6665,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
setup_freeext(freeblks, ip, i, needj);
ip->i_din2->di_extsize = 0;
datablocks += extblocks;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
}
#ifdef QUOTA
/* Reference the quotas in case the block count is wrong in the end. */
@@ -6772,7 +6774,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
}
ip->i_size = length;
DIP_SET(ip, i_size, length);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
allocbuf(bp, frags);
ffs_update(vp, 0);
bawrite(bp);
@@ -6919,6 +6921,7 @@ softdep_setup_freeblocks(ip, length, flags)
setup_freeindir(freeblks, ip, i, -lbn -i, 0);
ip->i_size = 0;
DIP_SET(ip, i_size, 0);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
datablocks = DIP(ip, i_blocks) - extblocks;
}
if ((flags & IO_EXT) != 0) {
@@ -6926,6 +6929,7 @@ softdep_setup_freeblocks(ip, length, flags)
setup_freeext(freeblks, ip, i, 0);
ip->i_din2->di_extsize = 0;
datablocks += extblocks;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
}
#ifdef QUOTA
/* Reference the quotas in case the block count is wrong in the end. */
Modified: stable/12/sys/ufs/ffs/ffs_vnops.c
==============================================================================
--- stable/12/sys/ufs/ffs/ffs_vnops.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ffs/ffs_vnops.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -387,6 +387,8 @@ next:
error = ffs_update(vp, 1);
if (DOINGSUJ(vp))
softdep_journal_fsync(VTOI(vp));
+ } else if ((ip->i_flags & (IN_SIZEMOD | IN_IBLKDATA)) != 0) {
+ error = ffs_update(vp, 1);
}
return (error);
}
@@ -782,6 +784,7 @@ ffs_write(ap)
if (uio->uio_offset + xfersize > ip->i_size) {
ip->i_size = uio->uio_offset + xfersize;
DIP_SET(ip, i_size, ip->i_size);
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
}
size = blksize(fs, ip, lbn) - bp->b_resid;
@@ -1062,8 +1065,10 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int io
if ((bp->b_flags & B_CACHE) == 0 && fs->fs_bsize <= xfersize)
vfs_bio_clrbuf(bp);
- if (uio->uio_offset + xfersize > dp->di_extsize)
+ if (uio->uio_offset + xfersize > dp->di_extsize) {
dp->di_extsize = uio->uio_offset + xfersize;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE;
+ }
size = sblksize(fs, dp->di_extsize, lbn) - bp->b_resid;
if (size < xfersize)
Modified: stable/12/sys/ufs/ufs/inode.h
==============================================================================
--- stable/12/sys/ufs/ufs/inode.h Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ufs/inode.h Thu Jun 11 11:36:49 2020 (r362049)
@@ -127,12 +127,13 @@ struct inode {
#define IN_LAZYMOD 0x0020 /* Modified, but don't write yet. */
#define IN_LAZYACCESS 0x0040 /* Process IN_ACCESS after the
suspension finished */
-#define IN_EA_LOCKED 0x0080
-#define IN_EA_LOCKWAIT 0x0100
-
+#define IN_EA_LOCKED 0x0080 /* Extended attributes locked */
+#define IN_EA_LOCKWAIT 0x0100 /* Want extended attributes lock */
#define IN_TRUNCATED 0x0200 /* Journaled truncation pending. */
-
#define IN_UFS2 0x0400 /* UFS2 vs UFS1 */
+#define IN_IBLKDATA 0x0800 /* datasync requires inode block
+ update */
+#define IN_SIZEMOD 0x1000 /* Inode size has been modified */
#define i_dirhash i_un.dirhash
#define i_snapblklist i_un.snapblklist
Modified: stable/12/sys/ufs/ufs/ufs_lookup.c
==============================================================================
--- stable/12/sys/ufs/ufs/ufs_lookup.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ufs/ufs_lookup.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -556,7 +556,7 @@ found:
ufs_dirbad(dp, i_offset, "i_size too small");
dp->i_size = i_offset + DIRSIZ(OFSFMT(vdp), ep);
DIP_SET(dp, i_size, dp->i_size);
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
+ dp->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
}
brelse(bp);
@@ -918,7 +918,7 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename)
dp->i_size = dp->i_offset + DIRBLKSIZ;
DIP_SET(dp, i_size, dp->i_size);
dp->i_endoff = dp->i_size;
- dp->i_flag |= IN_CHANGE | IN_UPDATE;
+ dp->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
dirp->d_reclen = DIRBLKSIZ;
blkoff = dp->i_offset &
(VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_iosize - 1);
@@ -1004,6 +1004,7 @@ ufs_direnter(dvp, tvp, dirp, cnp, newdirbp, isrename)
if (dp->i_offset + dp->i_count > dp->i_size) {
dp->i_size = dp->i_offset + dp->i_count;
DIP_SET(dp, i_size, dp->i_size);
+ dp->i_flag |= IN_SIZEMOD | IN_MODIFIED;
}
/*
* Get the block containing the space for the new directory entry.
Modified: stable/12/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- stable/12/sys/ufs/ufs/ufs_vnops.c Thu Jun 11 11:35:30 2020 (r362048)
+++ stable/12/sys/ufs/ufs/ufs_vnops.c Thu Jun 11 11:36:49 2020 (r362049)
@@ -1926,7 +1926,7 @@ ufs_mkdir(ap)
goto bad;
ip->i_size = DIRBLKSIZ;
DIP_SET(ip, i_size, DIRBLKSIZ);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
if (DOINGSOFTDEP(tvp)) {
/*
@@ -2113,7 +2113,7 @@ ufs_symlink(ap)
bcopy(ap->a_target, SHORTLINK(ip), len);
ip->i_size = len;
DIP_SET(ip, i_size, len);
- ip->i_flag |= IN_CHANGE | IN_UPDATE;
+ ip->i_flag |= IN_SIZEMOD | IN_CHANGE | IN_UPDATE;
error = UFS_UPDATE(vp, 0);
} else
error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0,
More information about the svn-src-stable
mailing list