git: d9dc64f15893 - main - tmpfs: make vm_object point to the tmpfs node instead of vnode

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Fri, 09 Dec 2022 12:17:36 UTC
The branch main has been updated by kib:

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

commit d9dc64f1589360f2062ad92d63f69e13121e472a
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-10-20 12:00:21 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-12-09 12:15:37 +0000

    tmpfs: make vm_object point to the tmpfs node instead of vnode
    
    The vnode could be reclaimed and allocated again during the lifecycle of
    the node, but the node cannot.  Also, referencing the node would allow
    to reach it and tmpfs mount data from the object, regardless of the
    state of the possibly absent vnode.
    
    Still use swp_tmpfs for back-pointer, instead of using handle. Use of
    named swap objects would incur taking the sw_alloc_sx on node allocation
    and deallocation.
    
    swp_tmpfs is renamed to swp_priv to remove the last bit of tmpfs in vm/.
    
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D37097
---
 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 cdff1daadf33..ad0354f2d474 100644
--- a/sys/fs/tmpfs/tmpfs.h
+++ b/sys/fs/tmpfs/tmpfs.h
@@ -528,6 +528,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 adf31132f82c..0a7f255a4f74 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);
@@ -955,8 +948,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 | VIRF_TEXT_REF);
 		VI_UNLOCK(vp);
 		VM_OBJECT_WUNLOCK(object);
diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c
index 51a16ae6f5cf..ec6120ba72df 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 719198637726..78e7785e513e 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;