Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Aug 2019 14:06:34 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r351547 - head/sys/kern
Message-ID:  <201908271406.x7RE6Ynj079322@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Tue Aug 27 14:06:34 2019
New Revision: 351547
URL: https://svnweb.freebsd.org/changeset/base/351547

Log:
  Fix several logic issues in domainset_empty_vm().
  
  - Don't add 1 to the result of DOMAINSET_FLS.
  - Do not modify domainsets containing only empty domains.
  - Always flatten a _PREFER policy to _ROUNDROBIN if the preferred
    domain is empty.  Previously we were doing this only when ds_cnt > 1.
  
  These bugs could cause hangs during boot if a VM domain is empty.
  
  Tested by:	hselasky
  Reviewed by:	hselasky, kib
  MFC after:	1 week
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D21420

Modified:
  head/sys/kern/kern_cpuset.c

Modified: head/sys/kern/kern_cpuset.c
==============================================================================
--- head/sys/kern/kern_cpuset.c	Tue Aug 27 14:04:32 2019	(r351546)
+++ head/sys/kern/kern_cpuset.c	Tue Aug 27 14:06:34 2019	(r351547)
@@ -500,25 +500,31 @@ _domainset_create(struct domainset *domain, struct dom
 static bool
 domainset_empty_vm(struct domainset *domain)
 {
-	int i, j, max;
+	domainset_t empty;
+	int i, j;
 
-	max = DOMAINSET_FLS(&domain->ds_mask) + 1;
-	for (i = 0; i < max; i++)
-		if (DOMAINSET_ISSET(i, &domain->ds_mask) && VM_DOMAIN_EMPTY(i))
-			DOMAINSET_CLR(i, &domain->ds_mask);
+	DOMAINSET_ZERO(&empty);
+	for (i = 0; i < vm_ndomains; i++)
+		if (VM_DOMAIN_EMPTY(i))
+			DOMAINSET_SET(i, &empty);
+	if (DOMAINSET_SUBSET(&empty, &domain->ds_mask))
+		return (true);
+
+	/* Remove empty domains from the set and recompute. */
+	DOMAINSET_NAND(&domain->ds_mask, &empty);
 	domain->ds_cnt = DOMAINSET_COUNT(&domain->ds_mask);
-	max = DOMAINSET_FLS(&domain->ds_mask) + 1;
-	for (i = j = 0; i < max; i++) {
+	for (i = j = 0; i < DOMAINSET_FLS(&domain->ds_mask); 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;
-		}
+
+	/* Convert a PREFER policy referencing an empty domain to RR. */
+	if (domain->ds_policy == DOMAINSET_POLICY_PREFER &&
+	    DOMAINSET_ISSET(domain->ds_prefer, &empty)) {
+		domain->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
+		domain->ds_prefer = -1;
 	}
 
-	return (DOMAINSET_EMPTY(&domain->ds_mask));
+	return (false);
 }
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201908271406.x7RE6Ynj079322>