commit 01769e5f5f2822ca0660f55133d2bc1a2dd0f1c8 Author: Mateusz Guzik Date: Tue Apr 19 11:42:09 2022 +0200 reclaim Reviewed by: Differential Revision: diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index fd119afa7f07..4d80ab66da93 100644 --- a/sys/fs/nullfs/null_vfsops.c +++ b/sys/fs/nullfs/null_vfsops.c @@ -201,6 +201,7 @@ nullfs_mount(struct mount *mp) &xmp->notify_node); } + atomic_store_ptr(&mp->mnt_lowermount, lowerrootvp->v_mount); MNT_ILOCK(mp); if ((xmp->nullm_flags & NULLM_CACHE) != 0) { mp->mnt_kern_flag |= lowerrootvp->v_mount->mnt_kern_flag & diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index a495ad86ac46..1059ba0ec8c2 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -688,6 +688,7 @@ vfs_mount_alloc(struct vnode *vp, struct vfsconf *vfsp, const char *fspath, mp->mnt_vfs_ops); (void) vfs_busy(mp, MBF_NOWAIT); atomic_add_acq_int(&vfsp->vfc_refcount, 1); + mp->mnt_lowermount = NULL; mp->mnt_op = vfsp->vfc_vfsops; mp->mnt_vfc = vfsp; mp->mnt_stat.f_type = vfsp->vfc_typenum; diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index a6344e139502..43a1416028a7 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1264,6 +1264,24 @@ SYSCTL_INT(_debug, OID_AUTO, max_vnlru_free, CTLFLAG_RW, &max_vnlru_free, 0, "limit on vnode free requests per call to the vnlru_free routine"); +static bool +vnlru_free_pick(struct vnode *vp, struct vfsops *mnt_op) +{ + struct mount *mp, *lmp; + + mp = atomic_load_ptr(&vp->v_mount); + if (mp == NULL) + return (true); + if (mp->mnt_op == mnt_op) + return (true); + lmp = atomic_load_ptr(&mp->mnt_lowermount); + if (lmp == NULL) + return (false); + if (lmp->mnt_op == mnt_op) + return (true); + return (false); +} + /* * Attempt to reduce the free list by the requested amount. */ @@ -1299,8 +1317,7 @@ vnlru_free_impl(int count, struct vfsops *mnt_op, struct vnode *mvp) * check does not reach unmapped address even if * vnode is reclaimed. */ - if (mnt_op != NULL && (mp = vp->v_mount) != NULL && - mp->mnt_op != mnt_op) { + if (mnt_op != NULL && !vnlru_free_pick(vp, mnt_op)) { continue; } if (__predict_false(vp->v_type == VBAD || vp->v_type == VNON)) { diff --git a/sys/sys/mount.h b/sys/sys/mount.h index 3383bfe8f431..b56e84662960 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -262,6 +262,7 @@ struct mount { STAILQ_ENTRY(mount) mnt_taskqueue_link; /* (d) our place in deferred unmount list */ uint64_t mnt_taskqueue_flags; /* (d) unmount flags passed from taskqueue */ unsigned int mnt_unmount_retries; /* (d) # of failed deferred unmount attempts */ + struct mount *mnt_lowermount; }; #endif /* _WANT_MOUNT || _KERNEL */