if (lp == NULL || (pmap != vmspace_pmap(lp->lwp_vmspace)))
return;
+ lwkt_gettoken(&vm_token);
+
object = entry->object.vm_object;
+ KKASSERT(object != NULL);
+ vm_object_hold(object);
starta = addra - PFBAK * PAGE_SIZE;
if (starta < entry->start)
else if (starta > addra)
starta = 0;
- lwkt_gettoken(&vm_token);
+ KKASSERT(object == entry->object.vm_object);
for (i = 0; i < PAGEORDER_SIZE; i++) {
vm_object_t lobject;
+ vm_object_t nobject;
int allocated = 0;
addr = addra + vm_prefault_pageorder[i];
* In order to not have to check the pager via *haspage*()
* we stop if any non-default object is encountered. e.g.
* a vnode or swap object would stop the loop.
+ *
+ * XXX It is unclear whether hold chaining is sufficient
+ * to maintain the validity of the backing object chain.
*/
index = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT;
lobject = object;
pindex = index;
pprot = prot;
+ KKASSERT(lobject == entry->object.vm_object);
+ vm_object_hold(lobject);
+
while ((m = vm_page_lookup(lobject, pindex)) == NULL) {
if (lobject->type != OBJT_DEFAULT)
break;
vm_page_count_min(0)) {
break;
}
- /* note: allocate from base object */
+
+ /* NOTE: allocated from base object */
m = vm_page_alloc(object, index,
VM_ALLOC_NORMAL | VM_ALLOC_ZERO);
vm_page_zero_fill(m);
} else {
#ifdef PMAP_DEBUG
- pmap_page_assertzero(VM_PAGE_TO_PHYS(m));
+ pmap_page_assertzero(
+ VM_PAGE_TO_PHYS(m));
#endif
vm_page_flag_clear(m, PG_ZERO);
mycpu->gd_cnt.v_ozfod++;
}
if (lobject->backing_object_offset & PAGE_MASK)
break;
- pindex += lobject->backing_object_offset >> PAGE_SHIFT;
- lobject = lobject->backing_object;
+ while ((nobject = lobject->backing_object) != NULL) {
+ vm_object_hold(nobject);
+ if (nobject == lobject->backing_object) {
+ pindex +=
+ lobject->backing_object_offset >>
+ PAGE_SHIFT;
+ vm_object_lock_swap();
+ vm_object_drop(lobject);
+ lobject = nobject;
+ break;
+ }
+ vm_object_drop(nobject);
+ }
+ if (nobject == NULL) {
+ kprintf("vm_prefault: Warning, backing object "
+ "race averted lobject %p\n",
+ lobject);
+ continue;
+ }
pprot &= ~VM_PROT_WRITE;
}
+ vm_object_drop(lobject);
+
/*
* NOTE: lobject now invalid (if we did a zero-fill we didn't
* bother assigning lobject = object).
pmap_enter(pmap, addr, m, pprot, 0);
vm_page_deactivate(m);
vm_page_wakeup(m);
- } else if (((m->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) &&
+ } else if (
+ ((m->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) &&
(m->busy == 0) &&
(m->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) {
-
+ /*
+ * A fully valid page not undergoing soft I/O can
+ * be immediately entered into the pmap.
+ */
vm_page_busy(m);
if ((m->queue - m->pc) == PQ_CACHE) {
vm_page_deactivate(m);
vm_page_wakeup(m);
}
}
+ vm_object_drop(object);
lwkt_reltoken(&vm_token);
}