svn commit: r340396 - in stable/12/sys: kern vm

Mark Johnston markj at FreeBSD.org
Tue Nov 13 16:51:33 UTC 2018


Author: markj
Date: Tue Nov 13 16:51:30 2018
New Revision: 340396
URL: https://svnweb.freebsd.org/changeset/base/340396

Log:
  MFC r339925:
  Fix some problems that manifest when NUMA domain 0 is empty.
  
  Approved by:	re (gjb)

Modified:
  stable/12/sys/kern/kern_cpuset.c
  stable/12/sys/vm/uma_core.c
  stable/12/sys/vm/vm_init.c
  stable/12/sys/vm/vm_kern.c
  stable/12/sys/vm/vm_page.c
  stable/12/sys/vm/vm_pageout.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/kern/kern_cpuset.c
==============================================================================
--- stable/12/sys/kern/kern_cpuset.c	Tue Nov 13 15:28:27 2018	(r340395)
+++ stable/12/sys/kern/kern_cpuset.c	Tue Nov 13 16:51:30 2018	(r340396)
@@ -492,20 +492,29 @@ _domainset_create(struct domainset *domain, struct dom
 }
 
 /*
- * Are any of the domains in the mask empty? If so, silently
- * remove them.  If only empty domains are present, we must
- * return failure.
+ * Are any of the domains in the mask empty?  If so, silently
+ * remove them and update the domainset accordingly.  If only empty
+ * domains are present, we must return failure.
  */
 static bool
 domainset_empty_vm(struct domainset *domain)
 {
-	int i, max;
+	int i, j, max;
 
 	max = DOMAINSET_FLS(&domain->ds_mask) + 1;
-	for (i = 0; i < max; i++) {
-		if (DOMAINSET_ISSET(i, &domain->ds_mask) &&
-		    VM_DOMAIN_EMPTY(i))
+	for (i = 0; i < max; i++)
+		if (DOMAINSET_ISSET(i, &domain->ds_mask) && VM_DOMAIN_EMPTY(i))
 			DOMAINSET_CLR(i, &domain->ds_mask);
+	domain->ds_cnt = DOMAINSET_COUNT(&domain->ds_mask);
+	max = DOMAINSET_FLS(&domain->ds_mask) + 1;
+	for (i = j = 0; i < max; i++) {
+		if (DOMAINSET_ISSET(i, &domain->ds_mask))
+			domain->ds_order[j++] = i;
+		else if (domain->ds_policy == DOMAINSET_POLICY_PREFER &&
+		    domain->ds_prefer == i && domain->ds_cnt > 1) {
+			domain->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
+			domain->ds_prefer = -1;
+		}
 	}
 
 	return (DOMAINSET_EMPTY(&domain->ds_mask));
@@ -1378,7 +1387,7 @@ cpuset_setithread(lwpid_t id, int cpu)
 
 /*
  * Initialize static domainsets after NUMA information is available.  This is
- * called very early during boot.
+ * called before memory allocators are initialized.
  */
 void
 domainset_init(void)
@@ -1407,7 +1416,7 @@ domainset_init(void)
 void
 domainset_zero(void)
 {
-	struct domainset *dset;
+	struct domainset *dset, *tmp;
 
 	mtx_init(&cpuset_lock, "cpuset", NULL, MTX_SPIN | MTX_RECURSE);
 
@@ -1422,8 +1431,9 @@ domainset_zero(void)
 	kernel_object->domain.dr_policy = _domainset_create(&domainset2, NULL);
 
 	/* Remove empty domains from the global policies. */
-	LIST_FOREACH(dset, &cpuset_domains, ds_link)
-		(void)domainset_empty_vm(dset);
+	LIST_FOREACH_SAFE(dset, &cpuset_domains, ds_link, tmp)
+		if (domainset_empty_vm(dset))
+			LIST_REMOVE(dset, ds_link);
 }
 
 /*

Modified: stable/12/sys/vm/uma_core.c
==============================================================================
--- stable/12/sys/vm/uma_core.c	Tue Nov 13 15:28:27 2018	(r340395)
+++ stable/12/sys/vm/uma_core.c	Tue Nov 13 16:51:30 2018	(r340396)
@@ -3608,29 +3608,30 @@ uma_zone_reserve_kva(uma_zone_t zone, int count)
 void
 uma_prealloc(uma_zone_t zone, int items)
 {
+	struct vm_domainset_iter di;
 	uma_domain_t dom;
 	uma_slab_t slab;
 	uma_keg_t keg;
-	int domain, slabs;
+	int domain, flags, slabs;
 
 	keg = zone_first_keg(zone);
 	if (keg == NULL)
 		return;
 	KEG_LOCK(keg);
 	slabs = items / keg->uk_ipers;
-	domain = 0;
 	if (slabs * keg->uk_ipers < items)
 		slabs++;
+	flags = M_WAITOK;
+	vm_domainset_iter_policy_ref_init(&di, &keg->uk_dr, &domain, &flags);
 	while (slabs-- > 0) {
-		slab = keg_alloc_slab(keg, zone, domain, M_WAITOK);
+		slab = keg_alloc_slab(keg, zone, domain, flags);
 		if (slab == NULL)
 			return;
 		MPASS(slab->us_keg == keg);
 		dom = &keg->uk_domain[slab->us_domain];
 		LIST_INSERT_HEAD(&dom->ud_free_slab, slab, us_link);
-		do {
-			domain = (domain + 1) % vm_ndomains;
-		} while (VM_DOMAIN_EMPTY(domain));
+		if (vm_domainset_iter_policy(&di, &domain) != 0)
+			break;
 	}
 	KEG_UNLOCK(keg);
 }

Modified: stable/12/sys/vm/vm_init.c
==============================================================================
--- stable/12/sys/vm/vm_init.c	Tue Nov 13 15:28:27 2018	(r340395)
+++ stable/12/sys/vm/vm_init.c	Tue Nov 13 16:51:30 2018	(r340396)
@@ -123,11 +123,17 @@ vm_mem_init(void *dummy)
 	domainset_init();
 
 	/*
-	 * Initializes resident memory structures. From here on, all physical
+	 * Initialize resident memory structures.  From here on, all physical
 	 * memory is accounted for, and we use only virtual addresses.
 	 */
 	vm_set_page_size();
 	virtual_avail = vm_page_startup(virtual_avail);
+
+	/*
+	 * Set an initial domain policy for thread0 so that allocations
+	 * can work.
+	 */
+	domainset_zero();
 
 #ifdef	UMA_MD_SMALL_ALLOC
 	/* Announce page availability to UMA. */

Modified: stable/12/sys/vm/vm_kern.c
==============================================================================
--- stable/12/sys/vm/vm_kern.c	Tue Nov 13 15:28:27 2018	(r340395)
+++ stable/12/sys/vm/vm_kern.c	Tue Nov 13 16:51:30 2018	(r340396)
@@ -800,7 +800,6 @@ kmem_bootstrap_free(vm_offset_t start, vm_size_t size)
 		vmd = vm_pagequeue_domain(m);
 		vm_domain_free_lock(vmd);
 		vm_phys_free_pages(m, 0);
-		vmd->vmd_page_count++;
 		vm_domain_free_unlock(vmd);
 
 		vm_domain_freecnt_inc(vmd, 1);

Modified: stable/12/sys/vm/vm_page.c
==============================================================================
--- stable/12/sys/vm/vm_page.c	Tue Nov 13 15:28:27 2018	(r340395)
+++ stable/12/sys/vm/vm_page.c	Tue Nov 13 16:51:30 2018	(r340396)
@@ -855,11 +855,6 @@ vm_page_startup(vm_offset_t vaddr)
 	 */
 	vm_reserv_init();
 #endif
-	/*
-	 * Set an initial domain policy for thread0 so that allocations
-	 * can work.
-	 */
-	domainset_zero();
 
 	return (vaddr);
 }

Modified: stable/12/sys/vm/vm_pageout.c
==============================================================================
--- stable/12/sys/vm/vm_pageout.c	Tue Nov 13 15:28:27 2018	(r340395)
+++ stable/12/sys/vm/vm_pageout.c	Tue Nov 13 16:51:30 2018	(r340396)
@@ -2072,41 +2072,41 @@ vm_pageout_init(void)
 static void
 vm_pageout(void)
 {
-	int error;
-	int i;
+	struct proc *p;
+	struct thread *td;
+	int error, first, i;
 
+	p = curproc;
+	td = curthread;
+
 	swap_pager_swap_init();
-	snprintf(curthread->td_name, sizeof(curthread->td_name), "dom0");
-	error = kthread_add(vm_pageout_laundry_worker, NULL, curproc, NULL,
-	    0, 0, "laundry: dom0");
-	if (error != 0)
-		panic("starting laundry for domain 0, error %d", error);
-	for (i = 1; i < vm_ndomains; i++) {
+	for (first = -1, i = 0; i < vm_ndomains; i++) {
 		if (VM_DOMAIN_EMPTY(i)) {
 			if (bootverbose)
 				printf("domain %d empty; skipping pageout\n",
 				    i);
 			continue;
 		}
-
-		error = kthread_add(vm_pageout_worker, (void *)(uintptr_t)i,
-		    curproc, NULL, 0, 0, "dom%d", i);
-		if (error != 0) {
-			panic("starting pageout for domain %d, error %d\n",
-			    i, error);
+		if (first == -1)
+			first = i;
+		else {
+			error = kthread_add(vm_pageout_worker,
+			    (void *)(uintptr_t)i, p, NULL, 0, 0, "dom%d", i);
+			if (error != 0)
+				panic("starting pageout for domain %d: %d\n",
+				    i, error);
 		}
 		error = kthread_add(vm_pageout_laundry_worker,
-		    (void *)(uintptr_t)i, curproc, NULL, 0, 0,
-		    "laundry: dom%d", i);
+		    (void *)(uintptr_t)i, p, NULL, 0, 0, "laundry: dom%d", i);
 		if (error != 0)
-			panic("starting laundry for domain %d, error %d",
-			    i, error);
+			panic("starting laundry for domain %d: %d", i, error);
 	}
-	error = kthread_add(uma_reclaim_worker, NULL, curproc, NULL,
-	    0, 0, "uma");
+	error = kthread_add(uma_reclaim_worker, NULL, p, NULL, 0, 0, "uma");
 	if (error != 0)
 		panic("starting uma_reclaim helper, error %d\n", error);
-	vm_pageout_worker((void *)(uintptr_t)0);
+
+	snprintf(td->td_name, sizeof(td->td_name), "dom%d", first);
+	vm_pageout_worker((void *)(uintptr_t)first);
 }
 
 /*


More information about the svn-src-all mailing list