From nobody Sun Jul 27 16:32:16 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bqnFX5JLwz62slt; Sun, 27 Jul 2025 16:32:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bqnFX3PZKz3Zrw; Sun, 27 Jul 2025 16:32:16 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1753633936; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GVMZyLKoQzbjVazQ7x3SxYF0lyxX9PwICq5LapCRryg=; b=hldksjXMGrpDuSvuquqi/k8wkTfLf6n+ybOB/R2L9BDTMRTS+DfkK7b5rHYnz2kARE2Rqb ZPL9RDTzJ6yqYhpI3fbc6rgwgt3EzVRFDoMFV5GCXI/ikptsZcfE3BTypKCkrKzdjDNCXd KWeXCSuCzCmcXLZUVBHmYnnAaNOHpIb0Y4ACSnMiVUzBmrGb4oOTwUQPyTl4mjf8CUYKLG KXA2Zx8g4pLSGUp/82Ez/s8d35sHkmxblhIbp6yIVuZuxPsFzQLOy7aeZcm0S1g7aYT3oW OYr58pv3M0R8Ch2jIBiW+iMJuxQKQnLZ9ntHTPcuLqFw5blNBS9aKCMl8+zRqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1753633936; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=GVMZyLKoQzbjVazQ7x3SxYF0lyxX9PwICq5LapCRryg=; b=Blq8Ewb+khOY+r0B08VA6Kk4oWce8L7nGahlIUJQnl2BKy1Ku+YnogCfO5WCK25Hz7FY4F r8hS8cR3IZUOFs8m0atVvfvAf6XocKTNatP4k2dMDefzEyau4FiQQd/8Ib4LBb72dLvygR aGN0cJL8cNN93F//6odnl/sTIS/ESZKhRj6rlKhtubj3Zm5jikKl3cSjnYwdIUdC4vU/jR fGRwwII0rblC/iQZDGJagdSz37zIXbuJrTMe2nSr5dXyRsiLs4Uqc9uJfB2VPDzTE8mAo3 9GSGP/f2bamG+Yie4701QZ5kOXPzQ0yO/zLjy7sxPPCoOO/w1L/CiXTRzpDuGw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1753633936; a=rsa-sha256; cv=none; b=L5uLKl2++QdfudEwAuzfcbfesUsJpnyNVtERQq51DFq4G89vxhrbkLe0vmmhhgrGgUFapq laEZ487K0d/BoqGp1UR0HLD0HzXdv+ybVkOQDSRg6dzFCMT4GYojo0rJ539wGgdxTk975q kL+l70tvqfVYZGqcI07766dnoc0nA1+Wn+uKyl7a0loaKpheuufhhyFjVzhpS8vT7ZBwcU MUJqRNMTI0AW8pvqVOHQgF5TFikRQ7fhhr3EptQQ5DkJNQ5Xi5Q+SoXucu28LAYWU0MwFs 2XqM5MmdS80km1jNgGe6xkRfyJSUpUbKK/QIT/qciTSaV90+yN4yKqXzkEB+NQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bqnFX2GRHz1Lkt; Sun, 27 Jul 2025 16:32:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 56RGWG0o015675; Sun, 27 Jul 2025 16:32:16 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 56RGWGIG015672; Sun, 27 Jul 2025 16:32:16 GMT (envelope-from git) Date: Sun, 27 Jul 2025 16:32:16 GMT Message-Id: <202507271632.56RGWGIG015672@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Bojan =?utf-8?Q?Novkovi=C4=87?= Subject: git: cf571e08503d - main - domainset(9): Split domainset validation logic into a separate function List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: bnovkov X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: cf571e08503d7401d6eb7cae077058ebf02da116 Auto-Submitted: auto-generated The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=cf571e08503d7401d6eb7cae077058ebf02da116 commit cf571e08503d7401d6eb7cae077058ebf02da116 Author: Bojan Novković AuthorDate: 2024-09-08 16:10:53 +0000 Commit: Bojan Novković CommitDate: 2025-07-27 16:31:48 +0000 domainset(9): Split domainset validation logic into a separate function This change splits the validation and 'struct domainset'-filling logic from kern_cpuset_setdomain into a separate function - domainset_populate. This function's main use is to validate user-provided domainset(9) policies and populate a struct domainset before handing it off to domainset_create. No functional change intended. Differential Revision: https://reviews.freebsd.org/D46608 Reviewed by: markj --- share/man/man9/domainset.9 | 16 +++++++- sys/kern/kern_cpuset.c | 98 +++++++++++++++++++++++++--------------------- sys/sys/domainset.h | 14 +++++++ 3 files changed, 83 insertions(+), 45 deletions(-) diff --git a/share/man/man9/domainset.9 b/share/man/man9/domainset.9 index 816ce29f04f7..702c9f83a88b 100644 --- a/share/man/man9/domainset.9 +++ b/share/man/man9/domainset.9 @@ -22,7 +22,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 14, 2021 +.Dd June 24, 2025 .Dt DOMAINSET 9 .Os .Sh NAME @@ -54,6 +54,8 @@ struct domainset { .Ft struct domainset * .Fn domainset_create "const struct domainset *key" .Ft int +.Fn domainset_populate "struct domainset *domain" "domainset_t *mask" "int policy" "size_t mask_size" +.Ft int .Fn sysctl_handle_domainset "SYSCTL_HANDLER_ARGS" .Sh DESCRIPTION The @@ -137,6 +139,7 @@ These policies should be used in preference to to avoid blocking indefinitely on a .Dv M_WAITOK request. +.Pp The .Fn domainset_create function takes a partially filled in domainset as a key and returns a @@ -148,6 +151,17 @@ is an immutable type that is shared among all matching keys and must not be modified after return. .Pp The +.Fn domainset_populate +function fills a +.Vt domainset +struct using a domain mask and policy. +It is used for validating and +translating a domain mask and policy into a +.Vt domainset +struct when creating a custom domainset using +.Vt domainset_create . +.Pp +The .Fn sysctl_handle_domainset function is provided as a convenience for modifying or viewing domainsets that are not accessible via diff --git a/sys/kern/kern_cpuset.c b/sys/kern/kern_cpuset.c index 5d9e2f2f326b..d7eb82d5f259 100644 --- a/sys/kern/kern_cpuset.c +++ b/sys/kern/kern_cpuset.c @@ -530,7 +530,7 @@ _domainset_create(struct domainset *domain, struct domainlist *freelist) * remove them and update the domainset accordingly. If only empty * domains are present, we must return failure. */ -static bool +bool domainset_empty_vm(struct domainset *domain) { domainset_t empty; @@ -2409,82 +2409,92 @@ sys_cpuset_setdomain(struct thread *td, struct cpuset_setdomain_args *uap) } int -kern_cpuset_setdomain(struct thread *td, cpulevel_t level, cpuwhich_t which, - id_t id, size_t domainsetsize, const domainset_t *maskp, int policy, - const struct cpuset_copy_cb *cb) +domainset_populate(struct domainset *domain, const domainset_t *mask, int policy, + size_t mask_size) { - struct cpuset *nset; - struct cpuset *set; - struct thread *ttd; - struct proc *p; - struct domainset domain; - domainset_t *mask; - int error; - if (domainsetsize < sizeof(domainset_t) || - domainsetsize > DOMAINSET_MAXSIZE / NBBY) - return (ERANGE); if (policy <= DOMAINSET_POLICY_INVALID || - policy > DOMAINSET_POLICY_MAX) + policy > DOMAINSET_POLICY_MAX) { return (EINVAL); - error = cpuset_check_capabilities(td, level, which, id); - if (error != 0) - return (error); - memset(&domain, 0, sizeof(domain)); - mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO); - error = cb->cpuset_copyin(maskp, mask, domainsetsize); - if (error) - goto out; + } + /* * Verify that no high bits are set. */ - if (domainsetsize > sizeof(domainset_t)) { - char *end; - char *cp; + if (mask_size > sizeof(domainset_t)) { + const char *end; + const char *cp; - end = cp = (char *)&mask->__bits; - end += domainsetsize; + end = cp = (const char *)&mask->__bits; + end += mask_size; cp += sizeof(domainset_t); - while (cp != end) + while (cp != end) { if (*cp++ != 0) { - error = EINVAL; - goto out; + return (EINVAL); } + } } if (DOMAINSET_EMPTY(mask)) { - error = EDEADLK; - goto out; + return (EDEADLK); } - DOMAINSET_COPY(mask, &domain.ds_mask); - domain.ds_policy = policy; + DOMAINSET_COPY(mask, &domain->ds_mask); + domain->ds_policy = policy; /* * Sanitize the provided mask. */ - if (!DOMAINSET_SUBSET(&all_domains, &domain.ds_mask)) { - error = EINVAL; - goto out; + if (!DOMAINSET_SUBSET(&all_domains, &domain->ds_mask)) { + return (EINVAL); } /* Translate preferred policy into a mask and fallback. */ if (policy == DOMAINSET_POLICY_PREFER) { /* Only support a single preferred domain. */ - if (DOMAINSET_COUNT(&domain.ds_mask) != 1) { - error = EINVAL; - goto out; + if (DOMAINSET_COUNT(&domain->ds_mask) != 1) { + return (EINVAL); } - domain.ds_prefer = DOMAINSET_FFS(&domain.ds_mask) - 1; + domain->ds_prefer = DOMAINSET_FFS(&domain->ds_mask) - 1; /* This will be constrained by domainset_shadow(). */ - DOMAINSET_COPY(&all_domains, &domain.ds_mask); + DOMAINSET_COPY(&all_domains, &domain->ds_mask); } + return (0); +} + +int +kern_cpuset_setdomain(struct thread *td, cpulevel_t level, cpuwhich_t which, + id_t id, size_t domainsetsize, const domainset_t *maskp, int policy, + const struct cpuset_copy_cb *cb) +{ + struct cpuset *nset; + struct cpuset *set; + struct thread *ttd; + struct proc *p; + struct domainset domain; + domainset_t *mask; + int error; + + error = cpuset_check_capabilities(td, level, which, id); + if (error != 0) + return (error); + if (domainsetsize < sizeof(domainset_t) || + domainsetsize > DOMAINSET_MAXSIZE / NBBY) + return (ERANGE); + memset(&domain, 0, sizeof(domain)); + mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO); + error = cb->cpuset_copyin(maskp, mask, domainsetsize); + if (error) + goto out; + error = domainset_populate(&domain, mask, policy, domainsetsize); + if (error) + goto out; + /* * When given an impossible policy, fall back to interleaving * across all domains. */ if (domainset_empty_vm(&domain)) domainset_copy(domainset2, &domain); - switch (level) { case CPU_LEVEL_ROOT: case CPU_LEVEL_CPUSET: diff --git a/sys/sys/domainset.h b/sys/sys/domainset.h index f98b175e9bc8..f3dc92ec6383 100644 --- a/sys/sys/domainset.h +++ b/sys/sys/domainset.h @@ -113,6 +113,20 @@ void domainset_zero(void); * returned value will not match the key pointer. */ struct domainset *domainset_create(const struct domainset *); + +/* + * Remove empty domains from a given domainset. + * Returns 'false' if the domainset consists entirely of empty domains. + */ +bool domainset_empty_vm(struct domainset *domain); + +/* + * Validate and populate a domainset structure according to the specified + * policy and mask. + */ +int domainset_populate(struct domainset *domain, const domainset_t *mask, int policy, + size_t mask_size); + #ifdef _SYS_SYSCTL_H_ int sysctl_handle_domainset(SYSCTL_HANDLER_ARGS); #endif