diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -3914,6 +3914,9 @@ int aflags, domain; bool rr; + KASSERT((flags & (M_WAITOK | M_NOVM)) != (M_WAITOK | M_NOVM), + ("%s: invalid flags %#x", __func__, flags)); + restart: /* * Use the keg's policy if upper layers haven't already specified a @@ -3939,17 +3942,29 @@ return (slab); /* - * M_NOVM means don't ask at all! + * M_NOVM is used to break the recursion that can otherwise + * occur if low-level memory management routines use UMA. */ - if (flags & M_NOVM) - break; + if ((flags & M_NOVM) == 0) { + slab = keg_alloc_slab(keg, zone, domain, flags, aflags); + if (slab != NULL) + return (slab); + } - slab = keg_alloc_slab(keg, zone, domain, flags, aflags); - if (slab != NULL) - return (slab); - if (!rr && (flags & M_WAITOK) == 0) - break; - if (rr && vm_domainset_iter_policy(&di, &domain) != 0) { + if (!rr) { + if ((flags & M_USE_RESERVE) != 0) { + /* + * Drain reserves from other domains before + * giving up or sleeping. It may be useful to + * support per-domain reserves eventually. + */ + rdomain = UMA_ANYDOMAIN; + goto restart; + } + if ((flags & M_WAITOK) == 0) + break; + vm_wait_domain(domain); + } else if (vm_domainset_iter_policy(&di, &domain) != 0) { if ((flags & M_WAITOK) != 0) { vm_wait_doms(&keg->uk_dr.dr_policy->ds_mask, 0); goto restart;