Index: sys/vmmeter.h =================================================================== --- sys/vmmeter.h +++ sys/vmmeter.h @@ -187,6 +187,13 @@ return (!DOMAINSET_EMPTY(&vm_severe_domains)); } +static inline int +vm_page_count_severe_set(domainset_t *mask) +{ + + return (DOMAINSET_SUBSET(&vm_severe_domains, mask)); +} + /* * Return TRUE if we are under our minimum low-free-pages threshold. * Index: vm/vm_fault.c =================================================================== --- vm/vm_fault.c +++ vm/vm_fault.c @@ -545,6 +545,7 @@ { struct faultstate fs; struct vnode *vp; + struct domainset *dset; vm_object_t next_object, retry_object; vm_offset_t e_end, e_start; vm_pindex_t retry_pindex; @@ -788,7 +789,11 @@ * there, and allocation can fail, causing * restart and new reading of the p_flag. */ - if (!vm_page_count_severe() || P_KILLED(curproc)) { + dset = fs.object->domain.dr_policy; + if (dset == NULL) + dset = curthread->td_domain.dr_policy; + if (!vm_page_count_severe_set(&dset->ds_mask) || + P_KILLED(curproc)) { #if VM_NRESERVLEVEL > 0 vm_object_color(fs.object, atop(vaddr) - fs.pindex); @@ -803,7 +808,7 @@ } if (fs.m == NULL) { unlock_and_deallocate(&fs); - vm_waitpfault(); + vm_waitpfault(dset); goto RetryFault; } } Index: vm/vm_page.c =================================================================== --- vm/vm_page.c +++ vm/vm_page.c @@ -2959,10 +2959,9 @@ mtx_lock(&vm_domainset_lock); if (DOMAINSET_SUBSET(&vm_min_domains, wdoms)) { vm_min_waiters++; - msleep(&vm_min_domains, &vm_domainset_lock, PVM, - "vmwait", 0); + msleep(&vm_min_domains, &vm_domainset_lock, + PVM | PDROP, "vmwait", 0); } - mtx_unlock(&vm_domainset_lock); } } @@ -3067,15 +3066,20 @@ * this balance without careful testing first. */ void -vm_waitpfault(void) +vm_waitpfault(struct domainset *dset) { + /* + * XXX Ideally we would wait only until the allocation could + * be satisfied. This condition can cause new allocators to + * consume all freed pages while old allocators wait. + */ mtx_lock(&vm_domainset_lock); - if (vm_page_count_min()) { + if (DOMAINSET_SUBSET(&vm_min_domains, &dset->ds_mask)) { vm_min_waiters++; - msleep(&vm_min_domains, &vm_domainset_lock, PUSER, "pfault", 0); + msleep(&vm_min_domains, &vm_domainset_lock, PUSER | PDROP, + "pfault", 0); } - mtx_unlock(&vm_domainset_lock); } struct vm_pagequeue * Index: vm/vm_pageout.h =================================================================== --- vm/vm_pageout.h +++ vm/vm_pageout.h @@ -96,7 +96,7 @@ */ void vm_wait(vm_object_t obj); -void vm_waitpfault(void); +void vm_waitpfault(struct domainset *); void vm_wait_domain(int domain); void vm_wait_min(void); void vm_wait_severe(void);