DPDK patches and discussions
 help / color / mirror / Atom feed
* [RFC] eal: use C library to parse filesystem table
@ 2025-11-22 19:49 Stephen Hemminger
  2025-11-24 13:53 ` Bruce Richardson
  2025-11-25 23:05 ` [RFC v2] " Stephen Hemminger
  0 siblings, 2 replies; 4+ messages in thread
From: Stephen Hemminger @ 2025-11-22 19:49 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger

Rather than doing parsing of /proc/mounts with open coded string
handling, use the standard C library routines.
These exist in BSD and Linux.

It also avoids any possible issues with escaped strings etc
which the library handles. See getmntent(3) man page.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
 lib/eal/linux/eal_hugepage_info.c | 45 ++++++++++---------------------
 1 file changed, 14 insertions(+), 31 deletions(-)

diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index d47a19c56a..ecc0374204 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -13,6 +13,7 @@
 #include <inttypes.h>
 #include <unistd.h>
 #include <errno.h>
+#include <mntent.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
@@ -195,23 +196,13 @@ get_default_hp_size(void)
 static int
 get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 {
-	enum proc_mount_fieldnames {
-		DEVICE = 0,
-		MOUNTPT,
-		FSTYPE,
-		OPTIONS,
-		_FIELDNAME_MAX
-	};
 	static uint64_t default_size = 0;
 	const char proc_mounts[] = "/proc/mounts";
-	const char hugetlbfs_str[] = "hugetlbfs";
-	const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1;
 	const char pagesize_opt[] = "pagesize=";
 	const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1;
-	const char split_tok = ' ';
-	char *splitstr[_FIELDNAME_MAX];
 	char found[PATH_MAX] = "";
 	char buf[BUFSIZ];
+	struct mntent entry;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 	const size_t hugepage_dir_len = (internal_conf->hugepage_dir != NULL) ?
@@ -226,35 +217,28 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		return -1;
 	}
 
-	FILE *fd = fopen(proc_mounts, "r");
-	if (fd == NULL)
+	FILE *mounts = setmntent(proc_mounts, "r");
+	if (mounts == NULL)
 		rte_panic("Cannot open %s\n", proc_mounts);
 
 	if (default_size == 0)
 		default_size = get_default_hp_size();
 
-	while (fgets(buf, sizeof(buf), fd)){
+	while (getmntent_r(mounts, &entry, buf, sizeof(buf))) {
 		const char *pagesz_str;
 		size_t mountpt_len = 0;
 
-		if (rte_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX,
-				split_tok) != _FIELDNAME_MAX) {
-			EAL_LOG(ERR, "Error parsing %s", proc_mounts);
-			break; /* return NULL */
-		}
-
-		if (strncmp(splitstr[FSTYPE], hugetlbfs_str, htlbfs_str_len) != 0)
+		if (strcmp(entry.mnt_type, "hugetlbfs") != 0)
 			continue;
 
-		pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
+		pagesz_str = strstr(entry.mnt_opts, pagesize_opt);
 
 		/* if no explicit page size, the default page size is compared */
 		if (pagesz_str == NULL) {
 			if (hugepage_sz != default_size)
 				continue;
-		}
-		/* there is an explicit page size, so check it */
-		else {
+		} else {
+			/* there is an explicit page size, so check it */
 			uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
 			if (pagesz != hugepage_sz)
 				continue;
@@ -264,18 +248,17 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		 * If no --huge-dir option has been given, we're done.
 		 */
 		if (internal_conf->hugepage_dir == NULL) {
-			strlcpy(found, splitstr[MOUNTPT], len);
+			strlcpy(found, entry.mnt_dir, len);
 			break;
 		}
 
-		mountpt_len = strlen(splitstr[MOUNTPT]);
+		mountpt_len = strlen(entry.mnt_dir);
 
 		/*
 		 * Ignore any mount that doesn't contain the --huge-dir directory
 		 * or where mount point is not a parent path of --huge-dir
 		 */
-		if (strncmp(internal_conf->hugepage_dir, splitstr[MOUNTPT],
-				mountpt_len) != 0 ||
+		if (strncmp(internal_conf->hugepage_dir, entry.mnt_dir, mountpt_len) != 0 ||
 			(hugepage_dir_len > mountpt_len &&
 				internal_conf->hugepage_dir[mountpt_len] != '/')) {
 			continue;
@@ -286,10 +269,10 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		 * (so /mnt/1 is preferred over /mnt for matching /mnt/1/2)).
 		 */
 		if (mountpt_len > strlen(found))
-			strlcpy(found, splitstr[MOUNTPT], len);
+			strlcpy(found, entry.mnt_dir, len);
 	} /* end while fgets */
 
-	fclose(fd);
+	endmntent(mounts);
 
 	if (found[0] != '\0') {
 		/* If needed, return the requested dir, not the mount point. */
-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC] eal: use C library to parse filesystem table
  2025-11-22 19:49 [RFC] eal: use C library to parse filesystem table Stephen Hemminger
@ 2025-11-24 13:53 ` Bruce Richardson
  2025-11-25 23:05 ` [RFC v2] " Stephen Hemminger
  1 sibling, 0 replies; 4+ messages in thread
From: Bruce Richardson @ 2025-11-24 13:53 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: dev

On Sat, Nov 22, 2025 at 11:49:21AM -0800, Stephen Hemminger wrote:
> Rather than doing parsing of /proc/mounts with open coded string
> handling, use the standard C library routines.
> These exist in BSD and Linux.
> 
> It also avoids any possible issues with escaped strings etc
> which the library handles. See getmntent(3) man page.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
Acked-by: Bruce Richardson <bruce.richardson@intel.com>


>  lib/eal/linux/eal_hugepage_info.c | 45 ++++++++++---------------------
>  1 file changed, 14 insertions(+), 31 deletions(-)
> 

<snip>  

> -		pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
> +		pagesz_str = strstr(entry.mnt_opts, pagesize_opt);
>  
>  		/* if no explicit page size, the default page size is compared */
>  		if (pagesz_str == NULL) {
>  			if (hugepage_sz != default_size)
>  				continue;
> -		}
> -		/* there is an explicit page size, so check it */
> -		else {
> +		} else {
> +			/* there is an explicit page size, so check it */
>  			uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
>  			if (pagesz != hugepage_sz)
>  				continue;

Since you are already changing this part, this if-else block can be
shortened down to avoid duplicating the continue check:

diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index ecc0374204..0e54b35ce1 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -227,22 +227,16 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
        while (getmntent_r(mounts, &entry, buf, sizeof(buf))) {
                const char *pagesz_str;
                size_t mountpt_len = 0;
+               uint64_t pagesz;
 
                if (strcmp(entry.mnt_type, "hugetlbfs") != 0)
                        continue;
 
                pagesz_str = strstr(entry.mnt_opts, pagesize_opt);
-
-               /* if no explicit page size, the default page size is compared */
-               if (pagesz_str == NULL) {
-                       if (hugepage_sz != default_size)
-                               continue;
-               } else {
-                       /* there is an explicit page size, so check it */
-                       uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
-                       if (pagesz != hugepage_sz)
-                               continue;
-               }
+               pagesz = (pagesz_str == NULL) ? default_size :
+                               rte_str_to_size(&pagesz_str[pagesize_opt_len]);
+               if (pagesz != hugepage_sz)
+                       continue;
 
                /*
                 * If no --huge-dir option has been given, we're done.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC v2] eal: use C library to parse filesystem table
  2025-11-22 19:49 [RFC] eal: use C library to parse filesystem table Stephen Hemminger
  2025-11-24 13:53 ` Bruce Richardson
@ 2025-11-25 23:05 ` Stephen Hemminger
  2025-11-28 13:37   ` Konstantin Ananyev
  1 sibling, 1 reply; 4+ messages in thread
From: Stephen Hemminger @ 2025-11-25 23:05 UTC (permalink / raw)
  To: dev; +Cc: Stephen Hemminger, Bruce Richardson

Rather than doing parsing of /proc/mounts with open coded string
handling, use the standard C library routines.
These exist in BSD and Linux.

It also avoids any possible issues with escaped strings etc
which the library handles. See getmntent(3) man page.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson@intel.com>
---
v2 - implement suggestion to simplify conditionals

 lib/eal/linux/eal_hugepage_info.c | 58 ++++++++++---------------------
 1 file changed, 18 insertions(+), 40 deletions(-)

diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index d47a19c56a..7161b1a2fb 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -13,6 +13,7 @@
 #include <inttypes.h>
 #include <unistd.h>
 #include <errno.h>
+#include <mntent.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
@@ -195,23 +196,13 @@ get_default_hp_size(void)
 static int
 get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 {
-	enum proc_mount_fieldnames {
-		DEVICE = 0,
-		MOUNTPT,
-		FSTYPE,
-		OPTIONS,
-		_FIELDNAME_MAX
-	};
 	static uint64_t default_size = 0;
 	const char proc_mounts[] = "/proc/mounts";
-	const char hugetlbfs_str[] = "hugetlbfs";
-	const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1;
 	const char pagesize_opt[] = "pagesize=";
 	const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1;
-	const char split_tok = ' ';
-	char *splitstr[_FIELDNAME_MAX];
 	char found[PATH_MAX] = "";
 	char buf[BUFSIZ];
+	struct mntent entry;
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
 	const size_t hugepage_dir_len = (internal_conf->hugepage_dir != NULL) ?
@@ -226,56 +217,43 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		return -1;
 	}
 
-	FILE *fd = fopen(proc_mounts, "r");
-	if (fd == NULL)
+	FILE *mounts = setmntent(proc_mounts, "r");
+	if (mounts == NULL)
 		rte_panic("Cannot open %s\n", proc_mounts);
 
 	if (default_size == 0)
 		default_size = get_default_hp_size();
 
-	while (fgets(buf, sizeof(buf), fd)){
+	while (getmntent_r(mounts, &entry, buf, sizeof(buf))) {
 		const char *pagesz_str;
-		size_t mountpt_len = 0;
-
-		if (rte_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX,
-				split_tok) != _FIELDNAME_MAX) {
-			EAL_LOG(ERR, "Error parsing %s", proc_mounts);
-			break; /* return NULL */
-		}
+		uint64_t pagesz = default_size;
+		size_t mountpt_len;
 
-		if (strncmp(splitstr[FSTYPE], hugetlbfs_str, htlbfs_str_len) != 0)
+		if (strcmp(entry.mnt_type, "hugetlbfs") != 0)
 			continue;
 
-		pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
+		pagesz_str = strstr(entry.mnt_opts, pagesize_opt);
+		if (pagesz_str)
+			pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
 
-		/* if no explicit page size, the default page size is compared */
-		if (pagesz_str == NULL) {
-			if (hugepage_sz != default_size)
-				continue;
-		}
-		/* there is an explicit page size, so check it */
-		else {
-			uint64_t pagesz = rte_str_to_size(&pagesz_str[pagesize_opt_len]);
-			if (pagesz != hugepage_sz)
-				continue;
-		}
+		if (pagesz != hugepage_sz)
+			continue;
 
 		/*
 		 * If no --huge-dir option has been given, we're done.
 		 */
 		if (internal_conf->hugepage_dir == NULL) {
-			strlcpy(found, splitstr[MOUNTPT], len);
+			strlcpy(found, entry.mnt_dir, len);
 			break;
 		}
 
-		mountpt_len = strlen(splitstr[MOUNTPT]);
+		mountpt_len = strlen(entry.mnt_dir);
 
 		/*
 		 * Ignore any mount that doesn't contain the --huge-dir directory
 		 * or where mount point is not a parent path of --huge-dir
 		 */
-		if (strncmp(internal_conf->hugepage_dir, splitstr[MOUNTPT],
-				mountpt_len) != 0 ||
+		if (strncmp(internal_conf->hugepage_dir, entry.mnt_dir, mountpt_len) != 0 ||
 			(hugepage_dir_len > mountpt_len &&
 				internal_conf->hugepage_dir[mountpt_len] != '/')) {
 			continue;
@@ -286,10 +264,10 @@ get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
 		 * (so /mnt/1 is preferred over /mnt for matching /mnt/1/2)).
 		 */
 		if (mountpt_len > strlen(found))
-			strlcpy(found, splitstr[MOUNTPT], len);
+			strlcpy(found, entry.mnt_dir, len);
 	} /* end while fgets */
 
-	fclose(fd);
+	endmntent(mounts);
 
 	if (found[0] != '\0') {
 		/* If needed, return the requested dir, not the mount point. */
-- 
2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: [RFC v2] eal: use C library to parse filesystem table
  2025-11-25 23:05 ` [RFC v2] " Stephen Hemminger
@ 2025-11-28 13:37   ` Konstantin Ananyev
  0 siblings, 0 replies; 4+ messages in thread
From: Konstantin Ananyev @ 2025-11-28 13:37 UTC (permalink / raw)
  To: Stephen Hemminger, dev; +Cc: Bruce Richardson


> Rather than doing parsing of /proc/mounts with open coded string
> handling, use the standard C library routines.
> These exist in BSD and Linux.
> 
> It also avoids any possible issues with escaped strings etc
> which the library handles. See getmntent(3) man page.
> 
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> Acked-by: Bruce Richardson <bruce.richardson@intel.com>
> ---
> v2 - implement suggestion to simplify conditionals
> 
>  lib/eal/linux/eal_hugepage_info.c | 58 ++++++++++---------------------
>  1 file changed, 18 insertions(+), 40 deletions(-)
> 
> diff --git a/lib/eal/linux/eal_hugepage_info.c
> b/lib/eal/linux/eal_hugepage_info.c
> index d47a19c56a..7161b1a2fb 100644
> --- a/lib/eal/linux/eal_hugepage_info.c
> +++ b/lib/eal/linux/eal_hugepage_info.c
> @@ -13,6 +13,7 @@
>  #include <inttypes.h>
>  #include <unistd.h>
>  #include <errno.h>
> +#include <mntent.h>
>  #include <sys/mman.h>
>  #include <sys/stat.h>
> 
> @@ -195,23 +196,13 @@ get_default_hp_size(void)
>  static int
>  get_hugepage_dir(uint64_t hugepage_sz, char *hugedir, int len)
>  {
> -	enum proc_mount_fieldnames {
> -		DEVICE = 0,
> -		MOUNTPT,
> -		FSTYPE,
> -		OPTIONS,
> -		_FIELDNAME_MAX
> -	};
>  	static uint64_t default_size = 0;
>  	const char proc_mounts[] = "/proc/mounts";
> -	const char hugetlbfs_str[] = "hugetlbfs";
> -	const size_t htlbfs_str_len = sizeof(hugetlbfs_str) - 1;
>  	const char pagesize_opt[] = "pagesize=";
>  	const size_t pagesize_opt_len = sizeof(pagesize_opt) - 1;
> -	const char split_tok = ' ';
> -	char *splitstr[_FIELDNAME_MAX];
>  	char found[PATH_MAX] = "";
>  	char buf[BUFSIZ];
> +	struct mntent entry;
>  	const struct internal_config *internal_conf =
>  		eal_get_internal_configuration();
>  	const size_t hugepage_dir_len = (internal_conf->hugepage_dir != NULL)
> ?
> @@ -226,56 +217,43 @@ get_hugepage_dir(uint64_t hugepage_sz, char
> *hugedir, int len)
>  		return -1;
>  	}
> 
> -	FILE *fd = fopen(proc_mounts, "r");
> -	if (fd == NULL)
> +	FILE *mounts = setmntent(proc_mounts, "r");
> +	if (mounts == NULL)
>  		rte_panic("Cannot open %s\n", proc_mounts);
> 
>  	if (default_size == 0)
>  		default_size = get_default_hp_size();
> 
> -	while (fgets(buf, sizeof(buf), fd)){
> +	while (getmntent_r(mounts, &entry, buf, sizeof(buf))) {
>  		const char *pagesz_str;
> -		size_t mountpt_len = 0;
> -
> -		if (rte_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX,
> -				split_tok) != _FIELDNAME_MAX) {
> -			EAL_LOG(ERR, "Error parsing %s", proc_mounts);
> -			break; /* return NULL */
> -		}
> +		uint64_t pagesz = default_size;
> +		size_t mountpt_len;
> 
> -		if (strncmp(splitstr[FSTYPE], hugetlbfs_str, htlbfs_str_len) != 0)
> +		if (strcmp(entry.mnt_type, "hugetlbfs") != 0)
>  			continue;
> 
> -		pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
> +		pagesz_str = strstr(entry.mnt_opts, pagesize_opt);
> +		if (pagesz_str)
> +			pagesz =
> rte_str_to_size(&pagesz_str[pagesize_opt_len]);
> 
> -		/* if no explicit page size, the default page size is compared */
> -		if (pagesz_str == NULL) {
> -			if (hugepage_sz != default_size)
> -				continue;
> -		}
> -		/* there is an explicit page size, so check it */
> -		else {
> -			uint64_t pagesz =
> rte_str_to_size(&pagesz_str[pagesize_opt_len]);
> -			if (pagesz != hugepage_sz)
> -				continue;
> -		}
> +		if (pagesz != hugepage_sz)
> +			continue;
> 
>  		/*
>  		 * If no --huge-dir option has been given, we're done.
>  		 */
>  		if (internal_conf->hugepage_dir == NULL) {
> -			strlcpy(found, splitstr[MOUNTPT], len);
> +			strlcpy(found, entry.mnt_dir, len);
>  			break;
>  		}
> 
> -		mountpt_len = strlen(splitstr[MOUNTPT]);
> +		mountpt_len = strlen(entry.mnt_dir);
> 
>  		/*
>  		 * Ignore any mount that doesn't contain the --huge-dir directory
>  		 * or where mount point is not a parent path of --huge-dir
>  		 */
> -		if (strncmp(internal_conf->hugepage_dir, splitstr[MOUNTPT],
> -				mountpt_len) != 0 ||
> +		if (strncmp(internal_conf->hugepage_dir, entry.mnt_dir,
> mountpt_len) != 0 ||
>  			(hugepage_dir_len > mountpt_len &&
>  				internal_conf->hugepage_dir[mountpt_len] !=
> '/')) {
>  			continue;
> @@ -286,10 +264,10 @@ get_hugepage_dir(uint64_t hugepage_sz, char
> *hugedir, int len)
>  		 * (so /mnt/1 is preferred over /mnt for matching /mnt/1/2)).
>  		 */
>  		if (mountpt_len > strlen(found))
> -			strlcpy(found, splitstr[MOUNTPT], len);
> +			strlcpy(found, entry.mnt_dir, len);
>  	} /* end while fgets */
> 
> -	fclose(fd);
> +	endmntent(mounts);
> 
>  	if (found[0] != '\0') {
>  		/* If needed, return the requested dir, not the mount point. */
> --

Acked-by: Konstantin Ananyev <konstantin.ananyev@huawei.com>

> 2.51.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-11-28 13:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-22 19:49 [RFC] eal: use C library to parse filesystem table Stephen Hemminger
2025-11-24 13:53 ` Bruce Richardson
2025-11-25 23:05 ` [RFC v2] " Stephen Hemminger
2025-11-28 13:37   ` Konstantin Ananyev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).