summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2020-11-28 01:21:11 +0000
committerKyle Evans <kevans@FreeBSD.org>2020-11-28 01:21:11 +0000
commite07e3fa3c95c74fba6540736f1687ad0ee47537c (patch)
tree90f22b7e614a3f8118c4efdb5e61ba13e8cca2e9 /sys/kern
parent15add60d3743ceb019dd1b5fe3ece68608f65949 (diff)
downloadsrc-test2-e07e3fa3c95c74fba6540736f1687ad0ee47537c.tar.gz
src-test2-e07e3fa3c95c74fba6540736f1687ad0ee47537c.zip
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
Notes
Notes: svn path=/head/; revision=368116
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_cpuset.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/sys/kern/kern_cpuset.c b/sys/kern/kern_cpuset.c
index c5f4583b0d20..2429e535853e 100644
--- a/sys/kern/kern_cpuset.c
+++ b/sys/kern/kern_cpuset.c
@@ -794,14 +794,11 @@ cpuset_modify_domain(struct cpuset *set, struct domainset *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 domainset *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: