diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -185,11 +185,58 @@ VM_OBJECT_ASSERT_UNLOCKED(object); } +static bool +tmpfs_pager_getvp_smr(vm_object_t object, struct vnode **vpp, bool *vp_heldp) +{ + struct vnode *vp; + + MPASS(vp_heldp != NULL); + + vfs_smr_enter(); + vp = atomic_load_ptr(&object->un_pager.swp.swp_tmpfs); + if (vp == NULL) { + vfs_smr_exit(); + return (false); + } + + if (!vhold_smr(vp)) { + vfs_smr_exit(); + return (false); + } + + /* + * Now that we got the reference make sure the vnode did not get replaced + * from under us. + */ + vfs_smr_exit(); + atomic_thread_fence_acq(); + if (vp != atomic_load_ptr(&object->un_pager.swp.swp_tmpfs)) { + vdrop(vp); + return (false); + } + + *vpp = vp; + *vp_heldp = true; + return (true); +} + static void tmpfs_pager_getvp(vm_object_t object, struct vnode **vpp, bool *vp_heldp) { struct vnode *vp; + if (vp_heldp == NULL) + VM_OBJECT_ASSERT_LOCKED(object); + + /* + * First try the lockless variant. + */ + if (vp_heldp != NULL) { + if (tmpfs_pager_getvp_smr(object, vpp, vp_heldp)) { + return; + } + } + /* * Tmpfs VREG node, which was reclaimed, has tmpfs_pager_type * type, but not OBJ_TMPFS flag. In this case there is no @@ -197,8 +244,6 @@ */ if (vp_heldp != NULL) VM_OBJECT_RLOCK(object); - else - VM_OBJECT_ASSERT_LOCKED(object); if ((object->flags & OBJ_TMPFS) != 0) { vp = object->un_pager.swp.swp_tmpfs; if (vp != NULL) { @@ -749,7 +794,7 @@ } vm_object_clear_flag(obj, OBJ_TMPFS); - obj->un_pager.swp.swp_tmpfs = NULL; + atomic_store_ptr(&obj->un_pager.swp.swp_tmpfs, NULL); if (vp->v_writecount < 0) vp->v_writecount = 0; VI_UNLOCK(vp); @@ -902,7 +947,7 @@ VI_LOCK(vp); KASSERT(vp->v_object == NULL, ("Not NULL v_object in tmpfs")); vp->v_object = object; - object->un_pager.swp.swp_tmpfs = vp; + atomic_store_ptr(&object->un_pager.swp.swp_tmpfs, vp); vm_object_set_flag(object, OBJ_TMPFS); vn_irflag_set_locked(vp, VIRF_PGREAD); VI_UNLOCK(vp);