Index: sys/vm/vm_fault.c =================================================================== --- sys/vm/vm_fault.c +++ sys/vm/vm_fault.c @@ -151,19 +151,22 @@ "the page fault handler"); static inline void -release_page(struct faultstate *fs) +release_page(vm_page_t *mp) { + vm_page_t m; - if (fs->m != NULL) { + m = *mp; + if (m != NULL) { /* - * fs->m's object lock might not be held, so the page must be - * kept busy until we are done with it. + * We are likely to loop around again and attempt to busy + * this page. Deactivating it leaves it available for + * pageout while optimizing fault restarts. */ - vm_page_lock(fs->m); - vm_page_deactivate(fs->m); - vm_page_unlock(fs->m); - vm_page_xunbusy(fs->m); - fs->m = NULL; + vm_page_lock(m); + vm_page_deactivate(m); + vm_page_unlock(m); + vm_page_xunbusy(m); + *mp = NULL; } } @@ -193,11 +196,8 @@ vm_object_pip_wakeup(fs->object); if (fs->object != fs->first_object) { - VM_OBJECT_WLOCK(fs->first_object); - vm_page_free(fs->first_m); + release_page(&fs->first_m); vm_object_pip_wakeup(fs->first_object); - VM_OBJECT_WUNLOCK(fs->first_object); - fs->first_m = NULL; } vm_object_deallocate(fs->first_object); unlock_map(fs); @@ -678,7 +678,7 @@ } vhold(vp); - release_page(fs); + release_page(&fs->m); unlock_and_deallocate(fs); error = vget(vp, locked | LK_RETRY | LK_CANRECURSE, curthread); vdrop(vp); @@ -847,24 +847,16 @@ */ vm_page_aflag_set(fs.m, PGA_REFERENCED); if (fs.object != fs.first_object) { - if (!VM_OBJECT_TRYWLOCK( - fs.first_object)) { - VM_OBJECT_WUNLOCK(fs.object); - VM_OBJECT_WLOCK(fs.first_object); - VM_OBJECT_WLOCK(fs.object); - } - vm_page_free(fs.first_m); + release_page(&fs.first_m); vm_object_pip_wakeup(fs.first_object); - VM_OBJECT_WUNLOCK(fs.first_object); - fs.first_m = NULL; } unlock_map(&fs); if (fs.m == vm_page_lookup(fs.object, fs.pindex)) { vm_page_sleep_if_busy(fs.m, "vmpfw"); } - vm_object_pip_wakeup(fs.object); VM_OBJECT_WUNLOCK(fs.object); + vm_object_pip_wakeup(fs.object); VM_CNT_INC(v_intrans); vm_object_deallocate(fs.first_object); goto RetryFault; @@ -1278,7 +1270,7 @@ /* * We no longer need the old page or object. */ - release_page(&fs); + release_page(&fs.m); } /* * fs.object != fs.first_object due to above @@ -1316,7 +1308,7 @@ */ if (!fs.lookup_still_valid) { if (!vm_map_trylock_read(fs.map)) { - release_page(&fs); + release_page(&fs.m); unlock_and_deallocate(&fs); goto RetryFault; } @@ -1331,7 +1323,7 @@ * pageout will grab it eventually. */ if (result != KERN_SUCCESS) { - release_page(&fs); + release_page(&fs.m); unlock_and_deallocate(&fs); /* @@ -1344,7 +1336,7 @@ } if ((retry_object != fs.first_object) || (retry_pindex != fs.first_pindex)) { - release_page(&fs); + release_page(&fs.m); unlock_and_deallocate(&fs); goto RetryFault; } @@ -1360,7 +1352,7 @@ prot &= retry_prot; fault_type &= retry_prot; if (prot == 0) { - release_page(&fs); + release_page(&fs.m); unlock_and_deallocate(&fs); goto RetryFault; } Index: sys/vm/vm_object.c =================================================================== --- sys/vm/vm_object.c +++ sys/vm/vm_object.c @@ -1477,6 +1477,18 @@ goto retry; } + /* + * The page was left invalid. Likely placed there by + * an incomplete fault. Just remove and ignore. + */ + if (vm_page_none_valid(m)) { + if (vm_page_remove(m)) + vm_page_free(m); + else + vm_page_xunbusy(m); + continue; + } + /* vm_page_rename() will dirty the page. */ if (vm_page_rename(m, new_object, idx)) { vm_page_xunbusy(m); @@ -1688,8 +1700,18 @@ continue; } - KASSERT(pp == NULL || !vm_page_none_valid(pp), - ("unbusy invalid page %p", pp)); + if (pp != NULL && vm_page_none_valid(pp)) { + /* + * The page was invalid in the parent. Likely placed + * there by an incomplete fault. Just remove and + * ignore. p can replace it. + */ + if (vm_page_remove(pp)) + vm_page_free(pp); + else + vm_page_xunbusy(p); + pp = NULL; + } if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL, NULL)) {