Re: [PATCH] setup: dynamically detect default huge page size

Gabriel Krisman Bertazi <[email protected]>
Newsgroups org.kernel.vger.io-uring
Message-ID <[email protected]>
Prateek <[email protected]> writes:

>     Replaces the hardcoded 2MB huge page size with dynamic detection by
>     parsing /proc/meminfo. This fixes no-mmap allocation failures on
>     architectures with different default huge page sizes (like ARM64
>     which often uses 512MB) or x86 systems configured for 1GB pages.
>
>     - Safely parses /proc/meminfo without allocating memory.
>     - Uses raw syscalls and manual byte-by-byte matching to maintain
>       strict compatibility with CONFIG_NOLIBC builds (avoiding strstr).
>     - Drops the MAP_HUGE_2MB mmap flag to allow the kernel to correctly
>       apply the system's default huge page size.
>     - Falls back safely to 2MB if /proc/meminfo is unreadable.
>
> Signed-off-by: Prateek <[email protected]>
> ---
>  src/setup.c | 84 +++++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 68 insertions(+), 16 deletions(-)
>
> diff --git a/src/setup.c b/src/setup.c
> index ea6f11fd..46e20e0b 100644
> --- a/src/setup.c
> +++ b/src/setup.c
> @@ -220,15 +220,67 @@ __cold int io_uring_ring_dontfork(struct io_uring *ring)
>  	return 0;
>  }
>  
> -#ifndef MAP_HUGE_SHIFT
> -#define MAP_HUGE_SHIFT	26
> -#endif
> -#ifndef MAP_HUGE_2MB
> -#define MAP_HUGE_2MB	(21U << MAP_HUGE_SHIFT)
> -#endif
>  
> -/* FIXME */
> -static size_t huge_page_size = 2 * 1024 * 1024;
> +static size_t get_huge_page_size(void)
> +{
> +	static size_t hps;

Please, initialize your static variables to makes it readable. I.e,
should be initialized it to 2MB.

> +	size_t ret = 2 * 1024 * 1024; /* fallback: 2MB */

ret redundant with hps, could go away.

> +	char buf[4096];
> +	char *p, *end;
> +	unsigned long val;
> +	ssize_t n;
> +	int fd;
> +
> +	if (hps)
> +		return hps;
> +
> +	fd = __sys_open("/proc/meminfo", O_RDONLY, 0);
> +	if (fd < 0)
> +		goto out;
> +
> +	n = __sys_read(fd, buf, sizeof(buf) - 1);
> +	__sys_close(fd);
> +	if (n <= 0)
> +		goto out;
> +	buf[n] = '\0';
> +
> +	/*
> +	 * Scan line-by-line for "Hugepagesize:". We avoid strstr() and
> +	 * memcmp() because they are not available in CONFIG_NOLIBC builds.
> +	 */
> +	p = buf;
> +	end = buf + n;
> +	while (p < end) {
> +		/* Check if this line starts with "Hugepagesize:" (13 chars) */
> +		if (p + 13 <= end &&
> +		    p[0]  == 'H' && p[1]  == 'u' && p[2]  == 'g' &&
> +		    p[3]  == 'e' && p[4]  == 'p' && p[5]  == 'a' &&
> +		    p[6]  == 'g' && p[7]  == 'e' && p[8]  == 's' &&
> +		    p[9]  == 'i' && p[10] == 'z' && p[11] == 'e' &&
> +		    p[12] == ':') {

This is unreadable.  It would be much better as a two line loop
iterating over two strings...  But then, why not create it a couple line
implementation of memcmp and atoi in arch/generic/lib.h instead?


> +			p += 13;
> +			while (p < end && (*p == ' ' || *p == '\t'))
> +				p++;
> +			val = 0;
> +			while (p < end && *p >= '0' && *p <= '9') {
> +				val = val * 10 + (*p - '0');
> +				p++;
> +			}
> +			if (val)
> +				ret = val * 1024; /* kB -> bytes */
> +			break;
> +		}
> +		/* Advance to next line */
> +		while (p < end && *p != '\n')
> +			p++;
> +		if (p < end)
> +			p++;
> +	}
> +out:
> +	hps = ret;
> +	return hps;
> +}

This function should go in arch/generic/lib.h too.  A hint is the
get_page_size is already there.

That said, we should be looking into something like the kernel's nolibc
instead of reinventing libc.

-- 
Gabriel Krisman Bertazi
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.