r339043 doesn't quite handle the possibility of having NUMA domain 0 be
empty. Prior to that revision, check_domains() would have returned an
error in that case, disabling NUMA awareness in the kernel. With
r339043 we panic during boot instead. A user reported this on the
mailing lists, and I was able to reproduce it by simply unplugging the
DIMMs attached to socket 0 in one of my systems.
This change contains a collection of unrelated fixes:
- Use vm_domainset_* in uma_prealloc(). Before, we only checked for
empty domains after the first allocation attempt, and we were also
computing domain = (domain + 1) % vm_ndomains where "domain" is
signed.
- When starting page daemon threads, don't automatically create a
laundry thread for domain 0, and use the vm_pageout() thread to manage
the first non-empty domain instead of hard-coding domain 0.
- Call domainset_zero() from vm_mem_init() instead of vm_page_startup(),
like domainset_init(). No functional change.
- In domainset_empty_vm() recompute ds_cnt and ds_order after excluding
empty domains. Convert DOMAINSET_PREF() policies to round-robin if
the preferred domain is empty.
- In kmem_bootstrap_free(), avoid adjusting the page count for now.
Some vm_phys segments are added before the system's NUMA topology is
known and are thus always placed in domain 0, which is wrong. When
kmem_bootstrap_free() releases pages (e.g., after a microcode update),
it thus increments vm_dom[0].vmd_page_count, causing the
VM_DOMAIN_EMPTY(0) predicate to return false instead of true.
The real fix is to ensure that the vm_phys segments created early
during boot are assigned to the right domain. For the purpose of
avoiding the current panic-on-boot when domain 0 isn't populated, just
don't update vmd_page_count for now.