[PATCH v13 07/17] eal: use C library to parse filesystem table

Stephen Hemminger stephen at networkplumber.org
Tue Jan 27 17:30:21 CET 2026


Replace open-coded string parsing of /proc/mounts with the
standard getmntent(3) routines available on Linux and BSD.

When hugepage_dir is explicitly specified, use statfs() to
validate the mount directly rather than scanning /proc/mounts.

Using the C library handles edge cases like escaped strings
in mount paths automatically.

Signed-off-by: Stephen Hemminger <stephen at networkplumber.org>
Acked-by: Bruce Richardson <bruce.richardson at intel.com>
Acked-by: Konstantin Ananyev <konstantin.ananyev at huawei.com>
---
 lib/eal/linux/eal_hugepage_info.c | 104 +++++++++---------------------
 1 file changed, 29 insertions(+), 75 deletions(-)

diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index d47a19c56a..f6d7098a07 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -13,10 +13,13 @@
 #include <inttypes.h>
 #include <unistd.h>
 #include <errno.h>
+#include <mntent.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/statfs.h>
 
 #include <linux/mman.h> /* for hugetlb-related flags */
+#include <linux/magic.h> /* for HUGETLBFS_MAGIC */
 
 #include <rte_lcore.h>
 #include <rte_debug.h>
@@ -195,109 +198,60 @@ 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];
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
-	const size_t hugepage_dir_len = (internal_conf->hugepage_dir != NULL) ?
-		strlen(internal_conf->hugepage_dir) : 0;
-	struct stat st;
+	struct mntent *mnt;
+	FILE *fp;
 
-	/*
-	 * If the specified dir doesn't exist, we can't match it.
-	 */
-	if (internal_conf->hugepage_dir != NULL &&
-		stat(internal_conf->hugepage_dir, &st) != 0) {
-		return -1;
+	/* Fast path: hugepage_dir explicitly specified */
+	if (internal_conf->hugepage_dir != NULL) {
+		struct statfs sfs;
+
+		/* Query info about mounted filesystem */
+		if (statfs(internal_conf->hugepage_dir, &sfs) != 0 ||
+		    sfs.f_type != HUGETLBFS_MAGIC ||
+		    (uint64_t)sfs.f_bsize != hugepage_sz)
+			return -1;
+
+		strlcpy(hugedir, internal_conf->hugepage_dir, len);
+		return 0;
 	}
 
-	FILE *fd = fopen(proc_mounts, "r");
-	if (fd == NULL)
-		rte_panic("Cannot open %s\n", proc_mounts);
+	/* Discover mount point from /proc/mounts */
+	fp = setmntent("/proc/mounts", "r");
+	if (fp == NULL)
+		rte_panic("Cannot open /proc/mounts\n");
 
 	if (default_size == 0)
 		default_size = get_default_hp_size();
 
-	while (fgets(buf, sizeof(buf), fd)){
+	while ((mnt = getmntent(fp)) != NULL) {
 		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(mnt->mnt_type, "hugetlbfs") != 0)
 			continue;
 
-		pagesz_str = strstr(splitstr[OPTIONS], pagesize_opt);
+		pagesz_str = hasmntopt(mnt, "pagesize");
 
-		/* 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 {
 			uint64_t pagesz = 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.
-		 */
-		if (internal_conf->hugepage_dir == NULL) {
-			strlcpy(found, splitstr[MOUNTPT], len);
-			break;
-		}
-
-		mountpt_len = strlen(splitstr[MOUNTPT]);
-
-		/*
-		 * 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 ||
-			(hugepage_dir_len > mountpt_len &&
-				internal_conf->hugepage_dir[mountpt_len] != '/')) {
-			continue;
-		}
-
-		/*
-		 * We found a match, but only prefer it if it's a longer match
-		 * (so /mnt/1 is preferred over /mnt for matching /mnt/1/2)).
-		 */
-		if (mountpt_len > strlen(found))
-			strlcpy(found, splitstr[MOUNTPT], len);
-	} /* end while fgets */
-
-	fclose(fd);
-
-	if (found[0] != '\0') {
-		/* If needed, return the requested dir, not the mount point. */
-		strlcpy(hugedir, internal_conf->hugepage_dir != NULL ?
-			internal_conf->hugepage_dir : found, len);
+		/* Found a match */
+		strlcpy(hugedir, mnt->mnt_dir, len);
+		endmntent(fp);
 		return 0;
 	}
 
+	endmntent(fp);
 	return -1;
 }
 
-- 
2.51.0



More information about the dev mailing list