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.