Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== --- sys/ufs/ffs/ffs_vfsops.c +++ sys/ufs/ffs/ffs_vfsops.c @@ -1446,6 +1446,23 @@ IN_UPDATE)) != 0); } +static int +ffs_sync_lazy_filter(struct vnode *vp, void *arg __unused) +{ + struct inode *ip; + + /* + * Flags are safe to access because ->v_data invalidation + * is held off by listmtx. + */ + if (vp->v_type == VNON) + return (false); + ip = VTOI(vp); + if (!sync_doupdate(ip) && (vp->v_iflag & VI_OWEINACT) == 0) + return (false); + return (true); +} + /* * For a lazy sync, we only care about access times, quotas and the * superblock. Other filesystem changes are already converted to @@ -1465,7 +1482,7 @@ td = curthread; if ((mp->mnt_flag & MNT_NOATIME) != 0) goto qupdate; - MNT_VNODE_FOREACH_ACTIVE(vp, mp, mvp) { + MNT_VNODE_FOREACH_LAZY(vp, mp, mvp, ffs_sync_lazy_filter, NULL) { if (vp->v_type == VNON) { VI_UNLOCK(vp); continue; Index: sys/ufs/ffs/ffs_vnops.c =================================================================== --- sys/ufs/ffs/ffs_vnops.c +++ sys/ufs/ffs/ffs_vnops.c @@ -113,6 +113,9 @@ static vop_getpages_t ffs_getpages; static vop_getpages_async_t ffs_getpages_async; static vop_lock1_t ffs_lock; +#ifdef INVARIANTS +static vop_unlock_t ffs_unlock_debug; +#endif static vop_read_t ffs_read; static vop_write_t ffs_write; static int ffs_extread(struct vnode *vp, struct uio *uio, int ioflag); @@ -135,6 +138,9 @@ .vop_getpages = ffs_getpages, .vop_getpages_async = ffs_getpages_async, .vop_lock1 = ffs_lock, +#ifdef INVARIANTS + .vop_unlock = ffs_unlock_debug, +#endif .vop_read = ffs_read, .vop_reallocblks = ffs_reallocblks, .vop_write = ffs_write, @@ -147,6 +153,9 @@ .vop_fsync = ffs_fsync, .vop_fdatasync = ffs_fdatasync, .vop_lock1 = ffs_lock, +#ifdef INVARIANTS + .vop_unlock = ffs_unlock_debug, +#endif .vop_vptofh = ffs_vptofh, }; VFS_VOP_VECTOR_REGISTER(ffs_fifoops1); @@ -159,6 +168,9 @@ .vop_getpages = ffs_getpages, .vop_getpages_async = ffs_getpages_async, .vop_lock1 = ffs_lock, +#ifdef INVARIANTS + .vop_unlock = ffs_unlock_debug, +#endif .vop_read = ffs_read, .vop_reallocblks = ffs_reallocblks, .vop_write = ffs_write, @@ -177,6 +189,9 @@ .vop_fsync = ffs_fsync, .vop_fdatasync = ffs_fdatasync, .vop_lock1 = ffs_lock, +#ifdef INVARIANTS + .vop_unlock = ffs_unlock_debug, +#endif .vop_reallocblks = ffs_reallocblks, .vop_strategy = ffsext_strategy, .vop_closeextattr = ffs_closeextattr, @@ -463,6 +478,26 @@ #endif } +#ifdef INVARIANTS +static int +ffs_unlock_debug(struct vop_unlock_args *ap) +{ + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + + if (ip->i_flag & UFS_INODE_FLAG_LAZY_MASK) { + if ((vp->v_mflag & VMP_LAZYLIST) == 0) { + VI_LOCK(vp); + VNASSERT((vp->v_mflag & VMP_LAZYLIST), vp, + ("%s: modified vnode (%x) not on lazy list", + __func__, ip->i_flag)); + VI_UNLOCK(vp); + } + } + return (VOP_UNLOCK_APV(&ufs_vnodeops, ap)); +} +#endif + static int ffs_read_hole(struct uio *uio, long xfersize, long *size) { @@ -665,12 +700,8 @@ vfs_bio_brelse(bp, ioflag); if ((error == 0 || uio->uio_resid != orig_resid) && - (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0 && - (ip->i_flag & IN_ACCESS) == 0) { - VI_LOCK(vp); - UFS_INODE_SET_FLAG(ip, IN_ACCESS); - VI_UNLOCK(vp); - } + (vp->v_mount->mnt_flag & (MNT_NOATIME | MNT_RDONLY)) == 0) + UFS_INODE_SET_FLAG_SHARED(ip, IN_ACCESS); return (error); } Index: sys/ufs/ufs/inode.h =================================================================== --- sys/ufs/ufs/inode.h +++ sys/ufs/ufs/inode.h @@ -138,11 +138,32 @@ "\14b12\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) + #define UFS_INODE_SET_FLAG(ip, flags) do { \ struct inode *_ip = (ip); \ + struct vnode *_vp = ITOV(_ip); \ int _flags = (flags); \ \ _ip->i_flag |= _flags; \ + if (_flags & UFS_INODE_FLAG_LAZY_MASK) \ + vlazy(_vp); \ +} while (0) + +#define UFS_INODE_SET_FLAG_SHARED(ip, flags) do { \ + struct inode *_ip = (ip); \ + struct vnode *_vp = ITOV(_ip); \ + int _flags = (flags); \ + \ + ASSERT_VI_UNLOCKED(_vp, __func__); \ + if ((_ip->i_flag & (_flags)) != _flags) { \ + VI_LOCK(_vp); \ + _ip->i_flag |= _flags; \ + if (_flags & UFS_INODE_FLAG_LAZY_MASK) \ + vlazy(_vp); \ + VI_UNLOCK(_vp); \ + } \ } while (0) #define i_dirhash i_un.dirhash Index: sys/ufs/ufs/ufs_vnops.c =================================================================== --- sys/ufs/ufs/ufs_vnops.c +++ sys/ufs/ufs/ufs_vnops.c @@ -686,12 +686,9 @@ struct vnode *a_vp; } */ *ap; { - struct vnode *vp = ap->a_vp; - struct inode *ip = VTOI(vp); + struct inode *ip = VTOI(ap->a_vp); - VI_LOCK(vp); - UFS_INODE_SET_FLAG(ip, IN_ACCESS); - VI_UNLOCK(vp); + UFS_INODE_SET_FLAG_SHARED(ip, IN_ACCESS); /* * XXXKIB No UFS_UPDATE(ap->a_vp, 0) there. */