git: e2d3dbe4ced6 - stable/13 - tmpfs: make vm_object point to the tmpfs node instead of vnode

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Fri, 20 Jan 2023 03:23:27 UTC
The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=e2d3dbe4ced68454afe0be0cb426bb2036c37454

commit e2d3dbe4ced68454afe0be0cb426bb2036c37454
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-10-20 12:00:21 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-01-20 03:19:17 +0000

    tmpfs: make vm_object point to the tmpfs node instead of vnode
    
    Tested by:      pho
    
    (cherry picked from commit d9dc64f1589360f2062ad92d63f69e13121e472a)
---
 sys/fs/tmpfs/tmpfs.h        | 17 +++++++++++++++++
 sys/fs/tmpfs/tmpfs_subr.c   | 25 ++++++++-----------------
 sys/fs/tmpfs/tmpfs_vfsops.c |  2 +-
 sys/vm/vm_object.h          | 15 ++++-----------
 4 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h
index 99368d67aaaa..40f32ed62a7b 100644
--- a/sys/fs/tmpfs/tmpfs.h
+++ b/sys/fs/tmpfs/tmpfs.h
@@ -527,6 +527,23 @@ extern int tmpfs_pager_type;
  * specific ones.
  */
 
+static inline struct vnode *
+VM_TO_TMPFS_VP(vm_object_t obj)
+{
+	struct tmpfs_node *node;
+
+	MPASS((obj->flags & OBJ_TMPFS) != 0);
+
+	/*
+	 * swp_priv is the back-pointer to the tmpfs node, if any,
+	 * which uses the vm object as backing store.  The object
+	 * handle is not used to avoid locking sw_alloc_sx on tmpfs
+	 * node instantiation/destroy.
+	 */
+	node = obj->un_pager.swp.swp_priv;
+	return (node->tn_vnode);
+}
+
 static inline struct tmpfs_mount *
 VFS_TO_TMPFS(struct mount *mp)
 {
diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c
index f0ed8ee404fa..7125b16dea33 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -113,7 +113,7 @@ tmpfs_pager_writecount_recalc(vm_object_t object, vm_offset_t old,
 
 	VM_OBJECT_ASSERT_WLOCKED(object);
 
-	vp = object->un_pager.swp.swp_tmpfs;
+	vp = VM_TO_TMPFS_VP(object);
 
 	/*
 	 * Forced unmount?
@@ -194,15 +194,14 @@ tmpfs_pager_getvp(vm_object_t object, struct vnode **vpp, bool *vp_heldp)
 
 	/*
 	 * Tmpfs VREG node, which was reclaimed, has tmpfs_pager_type
-	 * type, but not OBJ_TMPFS flag.  In this case there is no
-	 * v_writecount to adjust.
+	 * type.  In this case there is no v_writecount to adjust.
 	 */
 	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;
+		vp = VM_TO_TMPFS_VP(object);
 		if (vp != NULL) {
 			*vpp = vp;
 			if (vp_heldp != NULL) {
@@ -572,9 +571,10 @@ tmpfs_alloc_node(struct mount *mp, struct tmpfs_mount *tmp, enum vtype type,
 	case VREG:
 		nnode->tn_reg.tn_aobj =
 		    vm_pager_allocate(tmpfs_pager_type, NULL, 0,
-			VM_PROT_DEFAULT, 0,
-			NULL /* XXXKIB - tmpfs needs swap reservation */);
-		/* OBJ_TMPFS is set together with the setting of vp->v_object */
+		    VM_PROT_DEFAULT, 0,
+		    NULL /* XXXKIB - tmpfs needs swap reservation */);
+		nnode->tn_reg.tn_aobj->un_pager.swp.swp_priv = nnode;
+		vm_object_set_flag(nnode->tn_reg.tn_aobj, OBJ_TMPFS);
 		nnode->tn_reg.tn_tmp = tmp;
 		break;
 
@@ -667,14 +667,9 @@ tmpfs_free_node_locked(struct tmpfs_mount *tmp, struct tmpfs_node *node,
 		uobj = node->tn_reg.tn_aobj;
 		if (uobj != NULL && uobj->size != 0)
 			atomic_subtract_long(&tmp->tm_pages_used, uobj->size);
-
 		tmpfs_free_tmp(tmp);
-
-		if (uobj != NULL) {
-			KASSERT((uobj->flags & OBJ_TMPFS) == 0,
-			    ("leaked OBJ_TMPFS node %p vm_obj %p", node, uobj));
+		if (uobj != NULL)
 			vm_object_deallocate(uobj);
-		}
 		break;
 	case VLNK:
 		tmpfs_free_tmp(tmp);
@@ -816,8 +811,6 @@ tmpfs_destroy_vobject(struct vnode *vp, vm_object_t obj)
 		want_vrele = true;
 	}
 
-	vm_object_clear_flag(obj, OBJ_TMPFS);
-	obj->un_pager.swp.swp_tmpfs = NULL;
 	if (vp->v_writecount < 0)
 		vp->v_writecount = 0;
 	VI_UNLOCK(vp);
@@ -970,8 +963,6 @@ loop:
 		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;
-		vm_object_set_flag(object, OBJ_TMPFS);
 		vn_irflag_set_locked(vp, VIRF_PGREAD);
 		VI_UNLOCK(vp);
 		VM_OBJECT_WUNLOCK(object);
diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c
index c80042286948..7cba983a1847 100644
--- a/sys/fs/tmpfs/tmpfs_vfsops.c
+++ b/sys/fs/tmpfs/tmpfs_vfsops.c
@@ -246,7 +246,7 @@ again:
 				VM_OBJECT_RUNLOCK(object);
 				continue;
 			}
-			vp = object->un_pager.swp.swp_tmpfs;
+			vp = VM_TO_TMPFS_VP(object);
 			if (vp->v_mount != mp) {
 				VM_OBJECT_RUNLOCK(object);
 				continue;
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index 4a3c27514eb6..f221f1b0759b 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -156,20 +156,13 @@ struct vm_object {
 		/*
 		 * Swap pager
 		 *
-		 *	swp_tmpfs - back-pointer to the tmpfs vnode,
-		 *		     if any, which uses the vm object
-		 *		     as backing store.  The handle
-		 *		     cannot be reused for linking,
-		 *		     because the vnode can be
-		 *		     reclaimed and recreated, making
-		 *		     the handle changed and hash-chain
-		 *		     invalid.
-		 *
-		 *	swp_blks -   pc-trie of the allocated swap blocks.
+		 *	swp_priv - pager-private.
+		 *	swp_blks - pc-trie of the allocated swap blocks.
+		 *	writemappings - count of bytes mapped for write
 		 *
 		 */
 		struct {
-			void *swp_tmpfs;
+			void *swp_priv;
 			struct pctrie swp_blks;
 			vm_ooffset_t writemappings;
 		} swp;