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
This commit is contained in:
parent
15add60d37
commit
e07e3fa3c9
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user