Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Jun 2020 11:45:30 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r362050 - in stable/11/sys/ufs: ffs ufs
Message-ID:  <202006111145.05BBjUH0011385@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Thu Jun 11 11:45:30 2020
New Revision: 362050
URL: https://svnweb.freebsd.org/changeset/base/362050

Log:
  MFC r361785, r361801 (by mckusick), r361803 (by se), r361814 (by mckusick),
      r361875 (by mckusick):
  Fixes for UFS fdatasync(2).

Modified:
  stable/11/sys/ufs/ffs/ffs_alloc.c
  stable/11/sys/ufs/ffs/ffs_balloc.c
  stable/11/sys/ufs/ffs/ffs_inode.c
  stable/11/sys/ufs/ffs/ffs_snapshot.c
  stable/11/sys/ufs/ffs/ffs_softdep.c
  stable/11/sys/ufs/ffs/ffs_vnops.c
  stable/11/sys/ufs/ufs/inode.h
  stable/11/sys/ufs/ufs/ufs_lookup.c
  stable/11/sys/ufs/ufs/ufs_vnops.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/ufs/ffs/ffs_alloc.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_alloc.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ffs/ffs_alloc.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -2897,7 +2897,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/11/sys/ufs/ffs/ffs_balloc.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_balloc.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ffs/ffs_balloc.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -152,7 +152,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
@@ -222,7 +223,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);
 	}
@@ -279,7 +280,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.
@@ -632,7 +633,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
@@ -708,7 +709,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);
 	}
@@ -737,7 +738,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
@@ -809,7 +811,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);
 	}
@@ -867,7 +869,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/11/sys/ufs/ffs/ffs_inode.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_inode.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ffs/ffs_inode.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -92,6 +92,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);
@@ -263,7 +283,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, !DOINGASYNC(vp))))
 				return (error);
 			for (i = 0; i < NXADDR; i++) {
@@ -287,7 +307,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, !DOINGASYNC(vp)));
@@ -327,7 +347,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, !DOINGASYNC(vp)));
 	}
 	/*
@@ -413,6 +433,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;
@@ -447,6 +468,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
@@ -496,6 +518,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))
@@ -560,6 +583,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");
@@ -599,7 +623,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, 0);
 #endif

Modified: stable/11/sys/ufs/ffs/ffs_snapshot.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_snapshot.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ffs/ffs_snapshot.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -315,7 +315,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/11/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_softdep.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ffs/ffs_softdep.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -6617,6 +6617,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);
@@ -6627,6 +6628,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. */
@@ -6735,7 +6737,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);
@@ -6881,6 +6883,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) {
@@ -6888,6 +6891,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/11/sys/ufs/ffs/ffs_vnops.c
==============================================================================
--- stable/11/sys/ufs/ffs/ffs_vnops.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ffs/ffs_vnops.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -385,6 +385,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);
 }
@@ -758,6 +760,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;
@@ -1037,8 +1040,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/11/sys/ufs/ufs/inode.h
==============================================================================
--- stable/11/sys/ufs/ufs/inode.h	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ufs/inode.h	Thu Jun 11 11:45:30 2020	(r362050)
@@ -125,12 +125,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/11/sys/ufs/ufs/ufs_lookup.c
==============================================================================
--- stable/11/sys/ufs/ufs/ufs_lookup.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ufs/ufs_lookup.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -554,7 +554,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);
 
@@ -916,7 +916,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);
@@ -1002,6 +1002,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/11/sys/ufs/ufs/ufs_vnops.c
==============================================================================
--- stable/11/sys/ufs/ufs/ufs_vnops.c	Thu Jun 11 11:36:49 2020	(r362049)
+++ stable/11/sys/ufs/ufs/ufs_vnops.c	Thu Jun 11 11:45:30 2020	(r362050)
@@ -1925,7 +1925,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)) {
 		/*
@@ -2112,7 +2112,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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202006111145.05BBjUH0011385>