svn commit: r367669 - head/sys/ufs/ffs

Konstantin Belousov kib at FreeBSD.org
Sat Nov 14 05:17:05 UTC 2020


Author: kib
Date: Sat Nov 14 05:17:04 2020
New Revision: 367669
URL: https://svnweb.freebsd.org/changeset/base/367669

Log:
  Add a framework that tracks exclusive vnode lock generation count for UFS.
  
  This count is memoized together with the lookup metadata in directory
  inode, and we assert that accesses to lookup metadata are done under
  the same lock generation as they were stored.  Enabled under DIAGNOSTICS.
  
  UFS saves additional data for parent dirent when doing lookup
  (i_offset, i_count, i_endoff), and this data is used later by VOPs
  operating on dirents.  If parent vnode exclusive lock is dropped and
  re-acquired between lookup and the VOP call, we corrupt directories.
  
  Framework asserts that corruption cannot occur that way, by tracking
  vnode lock generation counter.  Updates to inode dirent members also
  save the counter, while users compare current and saved counters
  values.
  
  Also, fix a case in ufs_lookup_ino() where i_offset and i_count could
  be updated under shared lock.  It is not a bug on its own since dvp
  i_offset results from such lookup cannot be used, but it causes false
  positive in the checker.
  
  In collaboration with:	pho
  Reviewed by:	mckusick (previous version), markj
  Tested by:	markj (syzkaller), pho
  Sponsored by:	The FreeBSD Foundation
  Differential revision:	https://reviews.freebsd.org/D26136

Modified:
  head/sys/ufs/ffs/ffs_inode.c

Modified: head/sys/ufs/ffs/ffs_inode.c
==============================================================================
--- head/sys/ufs/ffs/ffs_inode.c	Sat Nov 14 05:10:39 2020	(r367668)
+++ head/sys/ufs/ffs/ffs_inode.c	Sat Nov 14 05:17:04 2020	(r367669)
@@ -67,6 +67,17 @@ __FBSDID("$FreeBSD$");
 static int ffs_indirtrunc(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
 	    ufs2_daddr_t, int, ufs2_daddr_t *);
 
+static void
+ffs_inode_bwrite(struct vnode *vp, struct buf *bp, int flags)
+{
+	if ((flags & IO_SYNC) != 0)
+		bwrite(bp);
+	else if (DOINGASYNC(vp))
+		bdwrite(bp);
+	else
+		bawrite(bp);
+}
+
 /*
  * Update the access, modified, and inode change times as specified by the
  * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively.  Write the inode
@@ -357,12 +368,7 @@ ffs_truncate(vp, length, flags, cred)
 		DIP_SET(ip, i_size, length);
 		if (bp->b_bufsize == fs->fs_bsize)
 			bp->b_flags |= B_CLUSTEROK;
-		if (flags & IO_SYNC)
-			bwrite(bp);
-		else if (DOINGASYNC(vp))
-			bdwrite(bp);
-		else
-			bawrite(bp);
+		ffs_inode_bwrite(vp, bp, flags);
 		UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
 		return (ffs_update(vp, waitforupdate));
 	}
@@ -478,12 +484,7 @@ ffs_truncate(vp, length, flags, cred)
 		allocbuf(bp, size);
 		if (bp->b_bufsize == fs->fs_bsize)
 			bp->b_flags |= B_CLUSTEROK;
-		if (flags & IO_SYNC)
-			bwrite(bp);
-		else if (DOINGASYNC(vp))
-			bdwrite(bp);
-		else
-			bawrite(bp);
+		ffs_inode_bwrite(vp, bp, flags);
 		UFS_INODE_SET_FLAG(ip, IN_SIZEMOD | IN_CHANGE | IN_UPDATE);
 	}
 	/*


More information about the svn-src-all mailing list