Index: sys/fs/tmpfs/tmpfs_vfsops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vfsops.c +++ sys/fs/tmpfs/tmpfs_vfsops.c @@ -142,6 +142,31 @@ mtx_destroy(&node->tn_interlock); } +extern bool tmpfs_mtime_filter_enabled; + +static bool +tmpfs_mtime_filter(struct vnode *vp, void *arg) +{ + struct vm_object *obj; + bool lazy = *(bool *)arg; + + if (!tmpfs_mtime_filter_enabled) + return (true); + + if (vp->v_type != VREG) + return (false); + obj = *(struct vm_object * const volatile *)&(vp->v_object); + /* + * We may race against VOP_RECLAIM which will NULLify the object. + * It is safe to access regardless thanks to being type-stable. + */ + if (obj == NULL) + return (false); + if (!lazy || (obj->flags & OBJ_TMPFS_DIRTY) != 0) + return (true); + return (false); +} + /* * Handle updates of time from writes to mmaped regions. Use * MNT_VNODE_FOREACH_ALL instead of MNT_VNODE_FOREACH_ACTIVE, since @@ -156,7 +181,7 @@ struct vnode *vp, *mvp; struct vm_object *obj; - MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { + MNT_VNODE_FOREACH_ALL_FILTER(vp, mp, mvp, tmpfs_mtime_filter, &lazy) { if (vp->v_type != VREG) { VI_UNLOCK(vp); continue; Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.c +++ sys/fs/tmpfs/tmpfs_vnops.c @@ -72,6 +72,10 @@ __DEVOLATILE(int *, &tmpfs_rename_restarts), 0, "Times rename had to restart due to lock contention"); +__read_mostly bool tmpfs_mtime_filter_enabled; +SYSCTL_BOOL(_vfs_tmpfs, OID_AUTO, mtime_filter_enabled, CTLFLAG_RW, + &tmpfs_mtime_filter_enabled, 0, ""); + static int tmpfs_vn_get_ino_alloc(struct mount *mp, void *arg, int lkflags, struct vnode **rvp) Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -5297,7 +5297,8 @@ MALLOC_DEFINE(M_VNODE_MARKER, "vnodemarker", "vnode marker"); struct vnode * -__mnt_vnode_next_all(struct vnode **mvp, struct mount *mp) +__mnt_vnode_next_all(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg) { struct vnode *vp; @@ -5310,6 +5311,8 @@ /* Allow a racy peek at VI_DOOMED to save a lock acquisition. */ if (vp->v_type == VMARKER || (vp->v_iflag & VI_DOOMED) != 0) continue; + if (cb != NULL && !cb(vp, cbarg)) + continue; VI_LOCK(vp); if ((vp->v_iflag & VI_DOOMED) != 0) { VI_UNLOCK(vp); @@ -5330,7 +5333,8 @@ } struct vnode * -__mnt_vnode_first_all(struct vnode **mvp, struct mount *mp) +__mnt_vnode_first_all(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *cbarg) { struct vnode *vp; @@ -5344,6 +5348,8 @@ /* Allow a racy peek at VI_DOOMED to save a lock acquisition. */ if (vp->v_type == VMARKER || (vp->v_iflag & VI_DOOMED) != 0) continue; + if (cb != NULL && !cb(vp, cbarg)) + continue; VI_LOCK(vp); if ((vp->v_iflag & VI_DOOMED) != 0) { VI_UNLOCK(vp); Index: sys/sys/mount.h =================================================================== --- sys/sys/mount.h +++ sys/sys/mount.h @@ -231,13 +231,19 @@ /* * Definitions for MNT_VNODE_FOREACH_ALL. */ -struct vnode *__mnt_vnode_next_all(struct vnode **mvp, struct mount *mp); -struct vnode *__mnt_vnode_first_all(struct vnode **mvp, struct mount *mp); +struct vnode *__mnt_vnode_next_all(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *); +struct vnode *__mnt_vnode_first_all(struct vnode **mvp, struct mount *mp, + bool (*cb)(struct vnode *, void *), void *); void __mnt_vnode_markerfree_all(struct vnode **mvp, struct mount *mp); -#define MNT_VNODE_FOREACH_ALL(vp, mp, mvp) \ - for (vp = __mnt_vnode_first_all(&(mvp), (mp)); \ - (vp) != NULL; vp = __mnt_vnode_next_all(&(mvp), (mp))) +#define MNT_VNODE_FOREACH_ALL_FILTER(vp, mp, mvp, cb, cbarg) \ + for (vp = __mnt_vnode_first_all(&(mvp), (mp), (cb), (cbarg)); \ + (vp) != NULL; vp = __mnt_vnode_next_all(&(mvp), (mp), (cb),\ + (cbarg))) + +#define MNT_VNODE_FOREACH_ALL(vp, mp, mvp) \ + MNT_VNODE_FOREACH_ALL_FILTER(vp, mp, mvp, NULL, NULL) #define MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp) \ do { \