Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Nov 2020 01:21:12 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r368116 - head/sys/kern
Message-ID:  <202011280121.0AS1LCeV098244@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sat Nov 28 01:21:11 2020
New Revision: 368116
URL: https://svnweb.freebsd.org/changeset/base/368116

Log:
  kern: cpuset: drop the lock to allocate domainsets
  
  Restructure the loop a little bit to make it a little more clear how it
  really operates: we never allocate any domains at the beginning of the first
  iteration, and it will run until we've satisfied the amount we need or we
  encounter an error.
  
  The lock is now taken outside of the loop to make stuff inside the loop
  easier to evaluate w.r.t. locking.
  
  This fixes it to not try and allocate any domains for the freelist under the
  spinlock, which would have happened before if we needed any new domains.
  
  Reported by:	syzbot+6743fa07b9b7528dc561@syzkaller.appspotmail.com
  Reviewed by:	markj
  MFC after:	3 days
  Differential Revision:	https://reviews.freebsd.org/D27371

Modified:
  head/sys/kern/kern_cpuset.c

Modified: head/sys/kern/kern_cpuset.c
==============================================================================
--- head/sys/kern/kern_cpuset.c	Sat Nov 28 01:16:59 2020	(r368115)
+++ head/sys/kern/kern_cpuset.c	Sat Nov 28 01:21:11 2020	(r368116)
@@ -794,14 +794,11 @@ cpuset_modify_domain(struct cpuset *set, struct domain
 		return (EPERM);
 	domainset_freelist_init(&domains, 0);
 	domain = domainset_create(domain);
-	ndomains = needed = 0;
-	do {
-		if (ndomains < needed) {
-			domainset_freelist_add(&domains, needed - ndomains);
-			ndomains = needed;
-		}
+	ndomains = 0;
+
+	mtx_lock_spin(&cpuset_lock);
+	for (;;) {
 		root = cpuset_getroot(set);
-		mtx_lock_spin(&cpuset_lock);
 		dset = root->cs_domain;
 		/*
 		 * Verify that we have access to this set of domains.
@@ -826,7 +823,15 @@ cpuset_modify_domain(struct cpuset *set, struct domain
 		    &needed, 0);
 		if (error)
 			goto out;
-	} while (ndomains < needed);
+		if (ndomains >= needed)
+			break;
+
+		/* Dropping the lock; we'll need to re-evaluate again. */
+		mtx_unlock_spin(&cpuset_lock);
+		domainset_freelist_add(&domains, needed - ndomains);
+		ndomains = needed;
+		mtx_lock_spin(&cpuset_lock);
+	}
 	dset = set->cs_domain;
 	cpuset_update_domain(set, domain, dset, &domains);
 out:



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