Correct a problem in the ZERO_COPY_SOCKETS option, specifically, in

vm_page_cowfault().  Initially, if vm_page_cowfault() sleeps, the given
page is wired, preventing it from being recycled.  However, when
transmission of the page completes, the page is unwired and returned to
the page queues.  At that point, the page is not in any special state
that prevents it from being recycled.  Consequently, vm_page_cowfault()
should verify that the page is still held by the same vm object before
retrying the replacement of the page.  Note: The containing object is,
however, safe from being recycled by virtue of having a non-zero
paging-in-progress count.

While I'm here, add some assertions and comments.

Approved by: re (rwatson)
MFC After: 3 weeks
This commit is contained in:
Alan Cox 2007-07-10 18:41:34 +00:00
parent 08b755600f
commit 20dd22a24e

View File

@ -1697,6 +1697,14 @@ vm_page_test_dirty(vm_page_t m)
int so_zerocp_fullpage = 0;
/*
* Replace the given page with a copy. The copied page assumes
* the portion of the given page's "wire_count" that is not the
* responsibility of this copy-on-write mechanism.
*
* The object containing the given page must have a non-zero
* paging-in-progress count and be locked.
*/
void
vm_page_cowfault(vm_page_t m)
{
@ -1705,6 +1713,10 @@ vm_page_cowfault(vm_page_t m)
vm_pindex_t pindex;
object = m->object;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
KASSERT(object->paging_in_progress != 0,
("vm_page_cowfault: object %p's paging-in-progress count is zero.",
object));
pindex = m->pindex;
retry_alloc:
@ -1717,8 +1729,16 @@ vm_page_cowfault(vm_page_t m)
VM_OBJECT_UNLOCK(object);
VM_WAIT;
VM_OBJECT_LOCK(object);
vm_page_lock_queues();
goto retry_alloc;
if (m == vm_page_lookup(object, pindex)) {
vm_page_lock_queues();
goto retry_alloc;
} else {
/*
* Page disappeared during the wait.
*/
vm_page_lock_queues();
return;
}
}
if (m->cow == 0) {