Add pgo_getvp method

This eliminates the staircase of conditions in vm_map_entry_set_vnode_text().

Reviewed by:	markj
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D30070
This commit is contained in:
Konstantin Belousov 2021-05-01 04:04:04 +03:00
parent c23c555bc1
commit 192112b74f
5 changed files with 68 additions and 32 deletions

View File

@ -435,6 +435,8 @@ static void swap_pager_release_writecount(vm_object_t object,
vm_offset_t start, vm_offset_t end);
static void swap_pager_set_writeable_dirty(vm_object_t object);
static bool swap_pager_mightbedirty(vm_object_t object);
static void swap_pager_getvp(vm_object_t object, struct vnode **vpp,
bool *vp_heldp);
struct pagerops swappagerops = {
.pgo_init = swap_pager_init, /* early system initialization of pager */
@ -449,6 +451,7 @@ struct pagerops swappagerops = {
.pgo_release_writecount = swap_pager_release_writecount,
.pgo_set_writeable_dirty = swap_pager_set_writeable_dirty,
.pgo_mightbedirty = swap_pager_mightbedirty,
.pgo_getvp = swap_pager_getvp,
};
/*
@ -3142,3 +3145,28 @@ swap_pager_mightbedirty(vm_object_t object)
return (vm_object_mightbedirty_(object));
return (false);
}
static void
swap_pager_getvp(vm_object_t object, struct vnode **vpp, bool *vp_heldp)
{
struct vnode *vp;
KASSERT((object->flags & OBJ_TMPFS_NODE) != 0,
("swap_pager_getvp: swap and !TMPFS obj %p", object));
/*
* Tmpfs VREG node, which was reclaimed, has
* OBJ_TMPFS_NODE flag set, but not OBJ_TMPFS. In
* this case there is no v_writecount to adjust.
*/
VM_OBJECT_RLOCK(object);
if ((object->flags & OBJ_TMPFS) != 0) {
vp = object->un_pager.swp.swp_tmpfs;
if (vp != NULL) {
vhold(vp);
*vpp = vp;
*vp_heldp = true;
}
}
VM_OBJECT_RUNLOCK(object);
}

View File

@ -561,38 +561,7 @@ vm_map_entry_set_vnode_text(vm_map_entry_t entry, bool add)
* referenced by the entry we are processing, so it cannot go
* away.
*/
vp = NULL;
vp_held = false;
if (object->type == OBJT_DEAD) {
/*
* For OBJT_DEAD objects, v_writecount was handled in
* vnode_pager_dealloc().
*/
} else if (object->type == OBJT_VNODE) {
vp = object->handle;
} else if (object->type == OBJT_SWAP) {
KASSERT((object->flags & OBJ_TMPFS_NODE) != 0,
("vm_map_entry_set_vnode_text: swap and !TMPFS "
"entry %p, object %p, add %d", entry, object, add));
/*
* Tmpfs VREG node, which was reclaimed, has
* OBJ_TMPFS_NODE flag set, but not OBJ_TMPFS. In
* this case there is no v_writecount to adjust.
*/
VM_OBJECT_RLOCK(object);
if ((object->flags & OBJ_TMPFS) != 0) {
vp = object->un_pager.swp.swp_tmpfs;
if (vp != NULL) {
vhold(vp);
vp_held = true;
}
}
VM_OBJECT_RUNLOCK(object);
} else {
KASSERT(0,
("vm_map_entry_set_vnode_text: wrong object type, "
"entry %p, object %p, add %d", entry, object, add));
}
vm_pager_getvp(object, &vp, &vp_held);
if (vp != NULL) {
if (add) {
VOP_SET_TEXT_CHECKED(vp);

View File

@ -100,6 +100,7 @@ static vm_object_t dead_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
static void dead_pager_putpages(vm_object_t, vm_page_t *, int, int, int *);
static boolean_t dead_pager_haspage(vm_object_t, vm_pindex_t, int *, int *);
static void dead_pager_dealloc(vm_object_t);
static void dead_pager_getvp(vm_object_t, struct vnode **, bool *);
static int
dead_pager_getpages(vm_object_t obj, vm_page_t *ma, int count, int *rbehind,
@ -144,12 +145,22 @@ dead_pager_dealloc(vm_object_t object)
}
static void
dead_pager_getvp(vm_object_t object, struct vnode **vpp, bool *vp_heldp)
{
/*
* For OBJT_DEAD objects, v_writecount was handled in
* vnode_pager_dealloc().
*/
}
static struct pagerops deadpagerops = {
.pgo_alloc = dead_pager_alloc,
.pgo_dealloc = dead_pager_dealloc,
.pgo_getpages = dead_pager_getpages,
.pgo_putpages = dead_pager_putpages,
.pgo_haspage = dead_pager_haspage,
.pgo_getvp = dead_pager_getvp,
};
struct pagerops *pagertab[] = {

View File

@ -47,6 +47,7 @@
#include <sys/queue.h>
TAILQ_HEAD(pagerlst, vm_object);
struct vnode;
typedef void pgo_init_t(void);
typedef vm_object_t pgo_alloc_t(void *, vm_ooffset_t, vm_prot_t, vm_ooffset_t,
@ -64,6 +65,8 @@ typedef void pgo_pageunswapped_t(vm_page_t);
typedef void pgo_writecount_t(vm_object_t, vm_offset_t, vm_offset_t);
typedef void pgo_set_writeable_dirty_t(vm_object_t);
typedef bool pgo_mightbedirty_t(vm_object_t);
typedef void pgo_getvp_t(vm_object_t object, struct vnode **vpp,
bool *vp_heldp);
struct pagerops {
pgo_init_t *pgo_init; /* Initialize pager. */
@ -79,6 +82,7 @@ struct pagerops {
pgo_writecount_t *pgo_release_writecount;
pgo_set_writeable_dirty_t *pgo_set_writeable_dirty;
pgo_mightbedirty_t *pgo_mightbedirty;
pgo_getvp_t *pgo_getvp;
};
extern struct pagerops defaultpagerops;
@ -216,6 +220,22 @@ vm_pager_release_writecount(vm_object_t object, vm_offset_t start,
method(object, start, end);
}
static __inline void
vm_pager_getvp(vm_object_t object, struct vnode **vpp, bool *vp_heldp)
{
pgo_getvp_t *method;
*vpp = NULL;
*vp_heldp = false;
method = pagertab[object->type]->pgo_getvp;
if (method != NULL) {
method(object, vpp, vp_heldp);
} else {
KASSERT(0,
("vm_pager_getvp: wrong object type obj %p", object));
}
}
struct cdev_pager_ops {
int (*cdev_pg_fault)(vm_object_t vm_obj, vm_ooffset_t offset,
int prot, vm_page_t *mres);

View File

@ -105,6 +105,7 @@ static void vnode_pager_update_writecount(vm_object_t, vm_offset_t,
vm_offset_t);
static void vnode_pager_release_writecount(vm_object_t, vm_offset_t,
vm_offset_t);
static void vnode_pager_getvp(vm_object_t, struct vnode **, bool *);
struct pagerops vnodepagerops = {
.pgo_alloc = vnode_pager_alloc,
@ -117,6 +118,7 @@ struct pagerops vnodepagerops = {
.pgo_release_writecount = vnode_pager_release_writecount,
.pgo_set_writeable_dirty = vm_object_set_writeable_dirty_,
.pgo_mightbedirty = vm_object_mightbedirty_,
.pgo_getvp = vnode_pager_getvp,
};
static struct domainset *vnode_domainset = NULL;
@ -1602,3 +1604,9 @@ vnode_pager_release_writecount(vm_object_t object, vm_offset_t start,
if (mp != NULL)
vn_finished_write(mp);
}
static void
vnode_pager_getvp(vm_object_t object, struct vnode **vpp, bool *vp_heldp)
{
*vpp = object->handle;
}