Fix VPO_UNMANAGED handling in vm_page_reclaim_run() after r353540.

When allocating a replacement page we must clear VPO_UNMANAGED since we
only ever reclaim pages from managed objects.  vm_page_replace() does
not handle this for us.

Sprinkle some assertions to help catch this sort of issue.

Reported by:	pho
Reviewed by:	alc, kib
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D22868
This commit is contained in:
Mark Johnston 2019-12-21 19:04:05 +00:00
parent 3f791e31fd
commit d07c571806
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=355985

View file

@ -1724,6 +1724,9 @@ vm_page_replace(vm_page_t mnew, vm_object_t object, vm_pindex_t pindex)
mnew->pindex = pindex;
atomic_set_int(&mnew->ref_count, VPRC_OBJREF);
mold = vm_radix_replace(&object->rtree, mnew);
KASSERT((mold->oflags & VPO_UNMANAGED) ==
(mnew->oflags & VPO_UNMANAGED),
("vm_page_replace: mismatched VPO_UNMANAGED"));
/* Keep the resident page list in sorted order. */
TAILQ_INSERT_AFTER(&object->memq, mold, mnew, listq);
@ -2684,8 +2687,7 @@ vm_page_reclaim_run(int req_class, int domain, u_long npages, vm_page_t m_run,
KASSERT(pmap_page_get_memattr(m) ==
VM_MEMATTR_DEFAULT,
("page %p has an unexpected memattr", m));
KASSERT((m->oflags & (VPO_SWAPINPROG |
VPO_SWAPSLEEP | VPO_UNMANAGED)) == 0,
KASSERT(m->oflags == 0,
("page %p has unexpected oflags", m));
/* Don't care: PGA_NOSYNC. */
if (!vm_page_none_valid(m)) {
@ -2753,6 +2755,7 @@ vm_page_reclaim_run(int req_class, int domain, u_long npages, vm_page_t m_run,
~PGA_QUEUE_STATE_MASK;
KASSERT(m_new->oflags == VPO_UNMANAGED,
("page %p is managed", m_new));
m_new->oflags = 0;
pmap_copy_page(m, m_new);
m_new->valid = m->valid;
m_new->dirty = m->dirty;
@ -3676,6 +3679,10 @@ vm_page_free_prep(vm_page_t m)
panic("vm_page_free_prep: freeing shared busy page %p", m);
if (m->object != NULL) {
KASSERT(((m->oflags & VPO_UNMANAGED) != 0) ==
((m->object->flags & OBJ_UNMANAGED) != 0),
("vm_page_free_prep: managed flag mismatch for page %p",
m));
vm_page_object_remove(m);
/*