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
This commit is contained in:
Konstantin Belousov 2022-10-20 15:00:21 +03:00
parent baa1ccceef
commit d9dc64f158
4 changed files with 30 additions and 29 deletions

View file

@ -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)
{

View file

@ -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 @@ tmpfs_alloc_vp(struct mount *mp, struct tmpfs_node *node, int lkflag,
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);

View file

@ -246,7 +246,7 @@ tmpfs_all_rw_maps(struct mount *mp, bool (*cb)(struct mount *mp, vm_map_t,
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;

View file

@ -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;