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