Author: mckusick
Date: Fri Jun  5 01:00:55 2020
New Revision: 361814
URL: https://svnweb.freebsd.org/changeset/base/361814

Log:
  Further evaluation of the POSIX spec for fdatasync() shows that it
  requires that new data on growing files be accessible. Thus, the
  the fsyncdata() system call must update the on-disk inode when the
  size of the file has changed.
  
  This commit adds another inode update flag, IN_SIZEMOD, that gets
  set any time that the file size changes. If either the IN_IBLKDATA
  or the IN_SIZEMOD flag is set when fdatasync() is called, the
  associated inode is synchronously written to disk. We could have
  overloaded the IN_IBLKDATA flag to also track size changes since
  the only (current) use case for these flags are for fsyncdata(),
  but it does seem useful for possible future uses to separately
  track the file size changes and the inode block pointer changes.
  
  Reviewed by: kib
  MFC with: -r361785
  Differential revision:  https://reviews.freebsd.org/D25072

Modified:
  head/sys/ufs/ffs/ffs_alloc.c
  head/sys/ufs/ffs/ffs_balloc.c
  head/sys/ufs/ffs/ffs_inode.c
  head/sys/ufs/ffs/ffs_snapshot.c
  head/sys/ufs/ffs/ffs_softdep.c
  head/sys/ufs/ffs/ffs_vnops.c
  head/sys/ufs/ufs/inode.h
  head/sys/ufs/ufs/ufs_lookup.c
  head/sys/ufs/ufs/ufs_vnops.c

Modified: head/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_alloc.c        Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ffs/ffs_alloc.c        Fri Jun  5 01:00:55 2020        
(r361814)
@@ -3306,7 +3306,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
                        break;
                ip = VTOI(vp);
                DIP_SET(ip, i_size, cmd.size);
-               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_MODIFIED);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_MODIFIED);
                error = ffs_update(vp, 1);
                vput(vp);
                break;

Modified: head/sys/ufs/ffs/ffs_balloc.c
==============================================================================
--- head/sys/ufs/ffs/ffs_balloc.c       Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ffs/ffs_balloc.c       Fri Jun  5 01:00:55 2020        
(r361814)
@@ -155,7 +155,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, i
                        dp->di_size = ip->i_size;
                        dp->di_db[nb] = dbtofsb(fs, bp->b_blkno);
                        UFS_INODE_SET_FLAG(ip,
-                           IN_CHANGE | IN_UPDATE | IN_IBLKDATA);
+                           IN_SIZEMOD | IN_CHANGE | IN_UPDATE | IN_IBLKDATA);
                        if (flags & IO_SYNC)
                                bwrite(bp);
                        else if (DOINGASYNC(vp))
@@ -648,7 +648,8 @@ 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;
-                               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_IBLKDATA);
+                               UFS_INODE_SET_FLAG(ip,
+                                   IN_SIZEMOD | IN_CHANGE | IN_IBLKDATA);
                                if (flags & IO_SYNC)
                                        bwrite(bp);
                                else
@@ -751,8 +752,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);
-                       UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE |
-                           IN_IBLKDATA);
+                       UFS_INODE_SET_FLAG(ip,
+                           IN_SIZEMOD |IN_CHANGE | IN_UPDATE | IN_IBLKDATA);
                        if (flags & IO_SYNC)
                                bwrite(bp);
                        else

Modified: head/sys/ufs/ffs/ffs_inode.c
==============================================================================
--- head/sys/ufs/ffs/ffs_inode.c        Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ffs/ffs_inode.c        Fri Jun  5 01:00:55 2020        
(r361814)
@@ -279,7 +279,7 @@ ffs_truncate(vp, length, flags, cred)
                                oldblks[i] = ip->i_din2->di_extb[i];
                                ip->i_din2->di_extb[i] = 0;
                        }
-                       UFS_INODE_SET_FLAG(ip, IN_CHANGE);
+                       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
                        if ((error = ffs_update(vp, waitforupdate)))
                                return (error);
                        for (i = 0; i < UFS_NXADDR; i++) {
@@ -303,7 +303,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);
-               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
                if (needextclean)
                        goto extclean;
                return (ffs_update(vp, waitforupdate));
@@ -343,7 +343,7 @@ ffs_truncate(vp, length, flags, cred)
                        bdwrite(bp);
                else
                        bawrite(bp);
-               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
                return (ffs_update(vp, waitforupdate));
        }
        /*
@@ -429,6 +429,7 @@ ffs_truncate(vp, length, flags, cred)
        if (blkno != 0 && offset == 0) {
                ip->i_size = length;
                DIP_SET(ip, i_size, length);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
        } else {
                lbn = lblkno(fs, length);
                flags |= BA_CLRBUF;
@@ -463,6 +464,7 @@ ffs_truncate(vp, length, flags, cred)
                        bdwrite(bp);
                else
                        bawrite(bp);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
        }
        /*
         * Calculate index into inode's block list of
@@ -512,6 +514,7 @@ ffs_truncate(vp, length, flags, cred)
        }
        ip->i_size = osize;
        DIP_SET(ip, i_size, osize);
+       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
 
        error = vtruncbuf(vp, length, fs->fs_bsize);
        if (error && (allerror == 0))
@@ -578,6 +581,7 @@ ffs_truncate(vp, length, flags, cred)
                oldspace = blksize(fs, ip, lastblock);
                ip->i_size = length;
                DIP_SET(ip, i_size, length);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
                newspace = blksize(fs, ip, lastblock);
                if (newspace == 0)
                        panic("ffs_truncate: newspace");
@@ -623,7 +627,7 @@ done:
                DIP_SET(ip, i_blocks, DIP(ip, i_blocks) - blocksreleased);
        else    /* sanity */
                DIP_SET(ip, i_blocks, 0);
-       UFS_INODE_SET_FLAG(ip, IN_CHANGE);
+       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
 #ifdef QUOTA
        (void) chkdq(ip, -blocksreleased, NOCRED, FORCE);
 #endif

Modified: head/sys/ufs/ffs/ffs_snapshot.c
==============================================================================
--- head/sys/ufs/ffs/ffs_snapshot.c     Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ffs/ffs_snapshot.c     Fri Jun  5 01:00:55 2020        
(r361814)
@@ -319,7 +319,7 @@ restart:
                goto out;
        ip->i_size = lblktosize(fs, (off_t)numblks);
        DIP_SET(ip, i_size, ip->i_size);
-       UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
+       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
        error = readblock(vp, bp, numblks - 1);
        bawrite(bp);
        if (error != 0)

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c      Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ffs/ffs_softdep.c      Fri Jun  5 01:00:55 2020        
(r361814)
@@ -6709,6 +6709,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
                }
                ip->i_size = length;
                DIP_SET(ip, i_size, ip->i_size);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
                datablocks = DIP(ip, i_blocks) - extblocks;
                if (length != 0)
                        datablocks = blkcount(fs, datablocks, length);
@@ -6719,6 +6720,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
                        setup_freeext(freeblks, ip, i, needj);
                ip->i_din2->di_extsize = 0;
                datablocks += extblocks;
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
        }
 #ifdef QUOTA
        /* Reference the quotas in case the block count is wrong in the end. */
@@ -6829,7 +6831,7 @@ softdep_journal_freeblocks(ip, cred, length, flags)
                }
                ip->i_size = length;
                DIP_SET(ip, i_size, length);
-               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
                allocbuf(bp, frags);
                ffs_update(vp, 0);
                bawrite(bp);
@@ -6976,6 +6978,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);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
                datablocks = DIP(ip, i_blocks) - extblocks;
        }
        if ((flags & IO_EXT) != 0) {
@@ -6983,6 +6986,7 @@ softdep_setup_freeblocks(ip, length, flags)
                        setup_freeext(freeblks, ip, i, 0);
                ip->i_din2->di_extsize = 0;
                datablocks += extblocks;
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
        }
 #ifdef QUOTA
        /* Reference the quotas in case the block count is wrong in the end. */

Modified: head/sys/ufs/ffs/ffs_vnops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vnops.c        Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ffs/ffs_vnops.c        Fri Jun  5 01:00:55 2020        
(r361814)
@@ -416,7 +416,7 @@ next:
                        error = ffs_update(vp, 1);
                if (DOINGSUJ(vp))
                        softdep_journal_fsync(VTOI(vp));
-       } else if ((ip->i_flags & IN_IBLKDATA) != 0) {
+       } else if ((ip->i_flags & (IN_SIZEMOD | IN_IBLKDATA)) != 0) {
                error = ffs_update(vp, 1);
        }
        return (error);
@@ -825,6 +825,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);
+                       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
                }
 
                size = blksize(fs, ip, lbn) - bp->b_resid;
@@ -1108,8 +1109,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;
+                       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE);
+               }
 
                size = sblksize(fs, dp->di_extsize, lbn) - bp->b_resid;
                if (size < xfersize)

Modified: head/sys/ufs/ufs/inode.h
==============================================================================
--- head/sys/ufs/ufs/inode.h    Fri Jun  5 00:16:54 2020        (r361813)
+++ head/sys/ufs/ufs/inode.h    Fri Jun  5 01:00:55 2020        (r361814)
@@ -127,19 +127,21 @@ 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 PRINT_INODE_FLAGS "\20\20b16\17b15\16b14\15b13" \
+#define PRINT_INODE_FLAGS "\20\20b16\17b15\16b14\15sizemod" \
        "\14iblkdata\13is_ufs2\12truncated\11ea_lockwait\10ea_locked" \
        "\7lazyaccess\6lazymod\5needsync\4modified\3update\2change\1access"
 
 #define UFS_INODE_FLAG_LAZY_MASK       \
-       (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE | IN_LAZYMOD | 
IN_LAZYACCESS)
+       (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE | IN_LAZYMOD | \
+        IN_LAZYACCESS)
 /*
  * Some flags can persist a vnode transitioning to 0 hold count and being tkaen
  * off the list.

Modified: head/sys/ufs/ufs/ufs_lookup.c
==============================================================================
--- head/sys/ufs/ufs/ufs_lookup.c       Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ufs/ufs_lookup.c       Fri Jun  5 01:00:55 2020        
(r361814)
@@ -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);
-               UFS_INODE_SET_FLAG(dp, IN_CHANGE | IN_UPDATE);
+               UFS_INODE_SET_FLAG(dp, 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;
-               UFS_INODE_SET_FLAG(dp, IN_CHANGE | IN_UPDATE);
+               UFS_INODE_SET_FLAG(dp, 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);
+               UFS_INODE_SET_FLAG(dp, IN_SIZEMOD | IN_MODIFIED);
        }
        /*
         * Get the block containing the space for the new directory entry.

Modified: head/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- head/sys/ufs/ufs/ufs_vnops.c        Fri Jun  5 00:16:54 2020        
(r361813)
+++ head/sys/ufs/ufs/ufs_vnops.c        Fri Jun  5 01:00:55 2020        
(r361814)
@@ -1932,7 +1932,7 @@ ufs_mkdir(ap)
                goto bad;
        ip->i_size = DIRBLKSIZ;
        DIP_SET(ip, i_size, DIRBLKSIZ);
-       UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
+       UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
        bcopy((caddr_t)&dirtemplate, (caddr_t)bp->b_data, sizeof dirtemplate);
        if (DOINGSOFTDEP(tvp)) {
                /*
@@ -2119,7 +2119,7 @@ ufs_symlink(ap)
                bcopy(ap->a_target, SHORTLINK(ip), len);
                ip->i_size = len;
                DIP_SET(ip, i_size, len);
-               UFS_INODE_SET_FLAG(ip, IN_CHANGE | IN_UPDATE);
+               UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
                error = UFS_UPDATE(vp, 0);
        } else
                error = vn_rdwr(UIO_WRITE, vp, __DECONST(void *, ap->a_target),
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to