Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
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


      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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox