Transfer responsibility for freeing the page taken from the cache
queue and (possibly) unlocking the containing object from vm_page_alloc() to vm_page_select_cache(). Recent optimizations to vm_map_pmap_enter() (see vm_map.c revisions 1.362 and 1.363) and pmap_enter_quick() have resulted in panic()s because vm_page_alloc() mistakenly unlocked objects that had not been locked by vm_page_select_cache(). Reported by: Peter Holm and Kris Kennaway
This commit is contained in:
parent
45a0fd86e1
commit
46fbc58202
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=139835
@ -693,31 +693,35 @@ vm_page_rename(vm_page_t m, vm_object_t new_object, vm_pindex_t new_pindex)
|
||||
/*
|
||||
* vm_page_select_cache:
|
||||
*
|
||||
* Find a page on the cache queue with color optimization. As pages
|
||||
* might be found, but not applicable, they are deactivated. This
|
||||
* keeps us from using potentially busy cached pages.
|
||||
* Move a page of the given color from the cache queue to the free
|
||||
* queue. As pages might be found, but are not applicable, they are
|
||||
* deactivated.
|
||||
*
|
||||
* This routine may not block.
|
||||
*/
|
||||
vm_page_t
|
||||
vm_page_select_cache(int color)
|
||||
{
|
||||
vm_object_t object;
|
||||
vm_page_t m;
|
||||
boolean_t was_trylocked;
|
||||
|
||||
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
|
||||
while ((m = vm_pageq_find(PQ_CACHE, color, FALSE)) != NULL) {
|
||||
if (m->hold_count == 0 && (VM_OBJECT_TRYLOCK(m->object) ||
|
||||
VM_OBJECT_LOCKED(m->object))) {
|
||||
KASSERT(m->dirty == 0, ("Found dirty cache page %p", m));
|
||||
KASSERT(!pmap_page_is_mapped(m),
|
||||
("Found mapped cache page %p", m));
|
||||
KASSERT((m->flags & PG_UNMANAGED) == 0,
|
||||
("Found unmanaged cache page %p", m));
|
||||
KASSERT(m->wire_count == 0, ("Found wired cache page %p", m));
|
||||
if (m->hold_count == 0 && (object = m->object,
|
||||
(was_trylocked = VM_OBJECT_TRYLOCK(object)) ||
|
||||
VM_OBJECT_LOCKED(object))) {
|
||||
KASSERT((m->flags & PG_BUSY) == 0 && m->busy == 0,
|
||||
("Found busy cache page %p", m));
|
||||
KASSERT(m->dirty == 0,
|
||||
("Found dirty cache page %p", m));
|
||||
KASSERT(!pmap_page_is_mapped(m),
|
||||
("Found mapped cache page %p", m));
|
||||
KASSERT((m->flags & PG_UNMANAGED) == 0,
|
||||
("Found unmanaged cache page %p", m));
|
||||
KASSERT(m->wire_count == 0,
|
||||
("Found wired cache page %p", m));
|
||||
vm_page_free(m);
|
||||
if (was_trylocked)
|
||||
VM_OBJECT_UNLOCK(object);
|
||||
break;
|
||||
}
|
||||
vm_page_deactivate(m);
|
||||
@ -746,7 +750,6 @@ vm_page_select_cache(int color)
|
||||
vm_page_t
|
||||
vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
|
||||
{
|
||||
vm_object_t m_object;
|
||||
vm_page_t m = NULL;
|
||||
int color, flags, page_req;
|
||||
|
||||
@ -800,12 +803,7 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
|
||||
pagedaemon_wakeup();
|
||||
return (NULL);
|
||||
}
|
||||
m_object = m->object;
|
||||
VM_OBJECT_LOCK_ASSERT(m_object, MA_OWNED);
|
||||
vm_page_free(m);
|
||||
vm_page_unlock_queues();
|
||||
if (m_object != object)
|
||||
VM_OBJECT_UNLOCK(m_object);
|
||||
goto loop;
|
||||
} else {
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user