From: sashiko-bot@kernel.org
To: "Alexander Graf" <graf@amazon.com>,
"Marek Szyprowski" <m.szyprowski@samsung.com>
Cc: "Jonathan Corbet" <corbet@lwn.net>,
"Shuah Khan" <skhan@linuxfoundation.org>,
"Randy Dunlap" <rdunlap@infradead.org>,
"Robin Murphy" <robin.murphy@arm.com>,
"Andrew Morton" <akpm@linux-foundation.org>,
"David Hildenbrand" <david@kernel.org>,
"Mike Rapoport" <rppt@kernel.org>,
nh-open-source@amazon.com, linux-mm@kvack.org,
"The AWS Nitro Enclaves Team"
<aws-nitro-enclaves-devel@amazon.com>
Subject: Re: [PATCH] dma-contiguous: support percentage sizes in cma_pernuma= and numa_cma=
Date: Thu, 12 Nov 2026 14:05:08 +0000 [thread overview]
Message-ID: <sashiko-outbox-211258@kernel.org> (raw)
In-Reply-To: <20261111140440.43024-1-graf@amazon.com>
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] dma-contiguous: numa_cma_parse() accepts empty string and
trailing comma
- [Medium] dma-contiguous: zero byte size fails to override percentage
in dma_numa_cma_reserve()
--
commit 3226f812115ddc4c4b57efe08a3f196e1ea740b7
Author: Alexander Graf <graf@amazon.com>
dma-contiguous: support percentage sizes in cma_pernuma= and numa_cma=
This commit extends the cma_pernuma= and numa_cma= boot parameters to
accept percentage-based sizes with an optional byte amount to subtract,
and validates the parameter string before applying it.
> diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
> index 90937dc7c627d..c04d50ee0f7c8 100644
> --- a/kernel/dma/contiguous.c
> +++ b/kernel/dma/contiguous.c
> @@ -135,45 +136,132 @@ EXPORT_SYMBOL_GPL(dev_get_cma_area);
> static struct cma *dma_contiguous_numa_area[MAX_NUMNODES];
> static phys_addr_t numa_cma_size[MAX_NUMNODES] __initdata;
> static phys_addr_t pernuma_size_bytes __initdata;
> +static unsigned int numa_cma_pct[MAX_NUMNODES] __initdata;
> +static unsigned int pernuma_pct __initdata;
> +static phys_addr_t numa_cma_sub[MAX_NUMNODES] __initdata;
> +static phys_addr_t pernuma_sub __initdata;
> static bool numa_cma_configured __initdata;
>
> -static int __init early_numa_cma(char *p)
> +/*
> + * What numa_cma_parse() does with a string it accepts: NUMA_CMA_CHECK leaves
> + * everything outside the function as it is, so a caller can validate the
> + * whole string before NUMA_CMA_APPLY lets any part of it take effect.
> + */
> +enum numa_cma_action {
> + NUMA_CMA_CHECK,
> + NUMA_CMA_APPLY,
> +};
> +
> +/*
> + * Parse one numa_cma= string: a comma separated list of <node>:<size>, where
> + * <size> is a size or <percent>%[-<size>]. Anything else fails the parse.
> + */
> +static int __init numa_cma_parse(char *p, enum numa_cma_action action)
> {
> int nid, count = 0;
> unsigned long node;
> - phys_addr_t size;
> - char *s = p;
> + phys_addr_t size, sub;
> + char *s = p, *start;
>
> while (*s) {
> - if (sscanf(s, "%lu%n", &node, &count) != 1)
> - break;
> -
> - if (s[count] == ':') {
> - if (node >= MAX_NUMNODES)
> - break;
> - nid = array_index_nospec(node, MAX_NUMNODES);
> -
> - s += count + 1;
> - size = memparse(s, &s);
> + if (sscanf(s, "%lu%n", &node, &count) != 1 || s[count] != ':' ||
> + node >= MAX_NUMNODES)
> + return -EINVAL;
> + nid = array_index_nospec(node, MAX_NUMNODES);
> +
> + start = s + count + 1;
> + size = memparse(start, &s);
> + if (s == start)
> + return -EINVAL;
> +
> + if (*s == '%') {
> + s++;
> + if (size > 100) {
> + pr_warn("numa_cma: node %d percentage %llu%% > 100\n",
> + nid, (unsigned long long)size);
> + return -EINVAL;
> + }
> + sub = 0;
> + if (*s == '-') {
> + start = ++s;
> + sub = memparse(start, &s);
> + if (s == start)
> + return -EINVAL;
> + }
> + if (action == NUMA_CMA_APPLY) {
> + numa_cma_pct[nid] = size;
> + numa_cma_sub[nid] = sub;
> + }
> + } else if (action == NUMA_CMA_APPLY) {
> numa_cma_size[nid] = size;
> + }
>
> - if (*s == ',')
> - s++;
> - else
> - break;
> - } else
> - break;
> + if (*s == ',')
> + s++;
> + else if (*s)
> + return -EINVAL;
> }
>
> - numa_cma_configured = true;
> return 0;
> }
[Severity: Medium]
Does numa_cma_parse() accept an empty string or a trailing comma?
When s is empty initially (numa_cma=) or after advancing past a trailing
comma (such as numa_cma=0:4G,), while (*s) terminates and returns 0
instead of -EINVAL. On a trailing comma, the NUMA_CMA_CHECK pass
succeeds and NUMA_CMA_APPLY applies the preceding entries rather than
rejecting the malformed parameter as documented.
[ ... ]
> @@ -214,16 +329,37 @@ static void __init dma_numa_cma_reserve(void)
> int ret;
>
> if (!node_online(nid)) {
> - if (pernuma_size_bytes || numa_cma_size[nid])
> + if (pernuma_size_bytes || pernuma_pct ||
> + numa_cma_size[nid] || numa_cma_pct[nid])
> pr_warn("invalid node %d specified\n", nid);
> continue;
> }
>
> /* per-node numa setting has the priority */
> - size = numa_cma_size[nid] ?: pernuma_size_bytes;
> - if (!size)
> + if (numa_cma_size[nid])
> + size = numa_cma_size[nid];
> + else if (numa_cma_pct[nid])
> + size = numa_cma_pct_size(nid, numa_cma_pct[nid],
> + numa_cma_sub[nid]);
> + else if (pernuma_size_bytes)
> + size = pernuma_size_bytes;
> + else if (pernuma_pct)
> + size = numa_cma_pct_size(nid, pernuma_pct, pernuma_sub);
> + else
> continue;
[Severity: Medium]
What happens when an explicit byte size of 0 is given alongside a
percentage, such as appending cma_pernuma=0 to override an earlier
cma_pernuma=80%, or passing numa_cma=0:50%,0:0?
Parsing an absolute size leaves pernuma_pct or numa_cma_pct[nid] intact,
and dma_numa_cma_reserve() treats pernuma_size_bytes == 0 and
numa_cma_size[nid] == 0 as unset. Instead of the absolute 0 taking
priority and disabling the reservation as documented in
kernel-parameters.txt, it falls through to the percentage and still
reserves the CMA area.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261111140440.43024-1-graf@amazon.com?part=1
prev parent reply other threads:[~2026-11-12 14:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-11 14:04 [PATCH] dma-contiguous: support percentage sizes in cma_pernuma= and numa_cma= Alexander Graf
2026-11-12 14:05 ` sashiko-bot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-211258@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=aws-nitro-enclaves-devel@amazon.com \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=graf@amazon.com \
--cc=linux-mm@kvack.org \
--cc=m.szyprowski@samsung.com \
--cc=nh-open-source@amazon.com \
--cc=rdunlap@infradead.org \
--cc=robin.murphy@arm.com \
--cc=rppt@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=skhan@linuxfoundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.