From: Stephen Hemminger <stephen@networkplumber.org>
To: dev@dpdk.org
Cc: Stephen Hemminger <stephen@networkplumber.org>,
Parav Pandit <parav@nvidia.com>, Xueming Li <xuemingl@nvidia.com>,
Nipun Gupta <nipun.gupta@amd.com>,
Nikhil Agarwal <nikhil.agarwal@amd.com>,
Chenbo Xia <chenbox@nvidia.com>,
Tomasz Duszynski <tduszynski@marvell.com>,
Long Li <longli@microsoft.com>, Wei Hu <weh@microsoft.com>,
Nithin Dabilpuram <ndabilpuram@marvell.com>,
Kiran Kumar K <kirankumark@marvell.com>,
Sunil Kumar Kori <skori@marvell.com>,
Satha Rao <skoteshwar@marvell.com>,
Harman Kalra <hkalra@marvell.com>,
Dariusz Sosnowski <dsosnowski@nvidia.com>,
Viacheslav Ovsiienko <viacheslavo@nvidia.com>,
Bing Zhao <bingz@nvidia.com>, Ori Kam <orika@nvidia.com>,
Suanming Mou <suanmingm@nvidia.com>,
Matan Azrad <matan@nvidia.com>,
Ciara Loftus <ciara.loftus@intel.com>,
Maryam Tahhan <mtahhan@redhat.com>
Subject: [PATCH 1/9] eal: add common sysfs value routines
Date: Fri, 11 Sep 2026 23:30:20 -0700 [thread overview]
Message-ID: <20260912063319.4117869-2-stephen@networkplumber.org> (raw)
In-Reply-To: <20260912063319.4117869-1-stephen@networkplumber.org>
Many drivers in DPDK read single values, and each one
open codes the same sequence: build a path with snprintf, open the
file, read a line, and convert it. Several drivers grew their own
private copy of that helper, and most of them parse with fscanf()
which cannot tell a failed conversion from a legitimate zero and
silently accepts trailing garbage.
Add a single set of routines in EAL that build the path from a
printf style format and do the conversion with strtoul()/strtol():
rte_sysfs_parse_uint() unsigned value
rte_sysfs_parse_int() signed value
rte_sysfs_parse_string() string value, newline stripped
rte_sysfs_write_string() write a string
rte_sysfs_vparse_uint() takes a va_list, so that a wrapper such
as the one in the power library can forward its arguments without
formatting the path a second time.
Folding the path construction into the routine removes the separate
snprintf() and its truncation check from every caller.
The signed variant exists because some attributes are genuinely
signed: numa_node is -1 when the device is not tied to a node.
These replace eal_parse_sysfs_value(), which was declared in the
internal eal_filesystem.h yet exported as a stable symbol, and was
reached by drivers through that private header.
Convert all of the existing callers.
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
app/test/test_eal_fs.c | 135 ++++++++++---
drivers/bus/auxiliary/linux/auxiliary.c | 13 +-
drivers/bus/cdx/cdx.c | 7 +-
drivers/bus/pci/linux/pci.c | 44 ++---
drivers/bus/platform/platform.c | 10 +-
drivers/bus/vmbus/linux/vmbus_bus.c | 25 +--
drivers/common/cnxk/roc_model.c | 40 +---
drivers/common/cnxk/roc_platform.h | 3 +-
.../common/mlx5/linux/mlx5_common_auxiliary.c | 13 +-
drivers/net/af_xdp/rte_eth_af_xdp.c | 13 +-
lib/eal/common/eal_filesystem.h | 4 +-
lib/eal/include/meson.build | 1 +
lib/eal/include/rte_sysfs.h | 121 ++++++++++++
lib/eal/linux/eal_hugepage_info.c | 32 +--
lib/eal/linux/eal_lcore.c | 18 +-
lib/eal/unix/eal_filesystem.c | 31 ---
lib/eal/unix/eal_unix_sysfs.c | 187 ++++++++++++++++++
lib/eal/unix/meson.build | 1 +
18 files changed, 493 insertions(+), 205 deletions(-)
create mode 100644 lib/eal/include/rte_sysfs.h
create mode 100644 lib/eal/unix/eal_unix_sysfs.c
diff --git a/app/test/test_eal_fs.c b/app/test/test_eal_fs.c
index 62eea98677..00c676c4d6 100644
--- a/app/test/test_eal_fs.c
+++ b/app/test/test_eal_fs.c
@@ -7,8 +7,10 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
-#include "eal_filesystem.h"
+#include <rte_sysfs.h>
#ifdef RTE_EXEC_ENV_WINDOWS
static int
@@ -30,13 +32,15 @@ test_parse_sysfs_value(void)
FILE *fd = NULL;
unsigned valid_number;
unsigned long retval = 0;
+ char strval[64];
+ long sretval = 0;
#ifdef RTE_EXEC_ENV_FREEBSD
/* BSD doesn't have /proc/pid/fd */
return 0;
#endif
- printf("Testing function eal_parse_sysfs_value()\n");
+ printf("Testing sysfs value functions\n");
/* get a temporary filename to use for all tests - create temp file handle and then
* use /proc to get the actual file that we can open */
@@ -54,8 +58,8 @@ test_parse_sysfs_value(void)
/* test we get an error value if we use file before it's created */
printf("Test reading a missing file ...\n");
- if (eal_parse_sysfs_value("/dev/not-quite-null", &retval) == 0) {
- printf("Error with eal_parse_sysfs_value() - returned success on reading empty file\n");
+ if (rte_sysfs_parse_uint(&retval, "/dev/not-quite-null") == 0) {
+ printf("Error with rte_sysfs_parse_uint() - returned success on reading empty file\n");
goto error;
}
printf("Confirmed return error when reading empty file\n");
@@ -71,12 +75,12 @@ test_parse_sysfs_value(void)
fprintf(fd,"%u\n", valid_number);
fclose(fd);
fd = NULL;
- if (eal_parse_sysfs_value(filename, &retval) < 0) {
- printf("eal_parse_sysfs_value() returned error - test failed\n");
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) < 0) {
+ printf("rte_sysfs_parse_uint() returned error - test failed\n");
goto error;
}
if (retval != valid_number) {
- printf("Invalid value read by eal_parse_sysfs_value() - test failed\n");
+ printf("Invalid value read by rte_sysfs_parse_uint() - test failed\n");
goto error;
}
printf("Read '%u\\n' ok\n", valid_number);
@@ -91,43 +95,93 @@ test_parse_sysfs_value(void)
fprintf(fd,"0x%x\n", valid_number);
fclose(fd);
fd = NULL;
- if (eal_parse_sysfs_value(filename, &retval) < 0) {
- printf("eal_parse_sysfs_value() returned error - test failed\n");
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) < 0) {
+ printf("rte_sysfs_parse_uint() returned error - test failed\n");
goto error;
}
if (retval != valid_number) {
- printf("Invalid value read by eal_parse_sysfs_value() - test failed\n");
+ printf("Invalid value read by rte_sysfs_parse_uint() - test failed\n");
goto error;
}
printf("Read '0x%x\\n' ok\n", valid_number);
- printf("Test reading invalid values ...\n");
+ /* a value without a trailing newline is accepted */
+ valid_number = 3;
+ fd = fopen(filename, "w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd, "%u", valid_number);
+ fclose(fd);
+ fd = NULL;
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) < 0 || retval != valid_number) {
+ printf("rte_sysfs_parse_uint() failed without trailing newline - test failed\n");
+ goto error;
+ }
+ printf("Read '%u' (no newline) ok\n", valid_number);
- /* test reading an empty file - expect failure!*/
- fd = fopen(filename,"w");
+ /* a negative value is rejected by the unsigned variant ... */
+ fd = fopen(filename, "w");
if (fd == NULL) {
printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
goto error;
}
+ fprintf(fd, "-1\n");
fclose(fd);
fd = NULL;
- if (eal_parse_sysfs_value(filename, &retval) == 0) {
- printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) == 0) {
+ printf("rte_sysfs_parse_uint() accepted a negative value - test failed\n");
goto error;
}
- /* test reading a valid number value *without* "\n" on the end - expect failure!*/
- valid_number = 3;
+ /* ... and read correctly by the signed one, as for numa_node */
+ if (rte_sysfs_parse_int(&sretval, "%s", filename) < 0 || sretval != -1) {
+ printf("rte_sysfs_parse_int() failed to read -1 - test failed\n");
+ goto error;
+ }
+ printf("Read '-1' as signed ok\n");
+
+ /* string read strips the trailing newline */
+ fd = fopen(filename, "w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd, "performance\n");
+ fclose(fd);
+ fd = NULL;
+ if (rte_sysfs_parse_string(strval, sizeof(strval), "%s", filename) < 0 ||
+ strcmp(strval, "performance") != 0) {
+ printf("rte_sysfs_parse_string() returned '%s' - test failed\n", strval);
+ goto error;
+ }
+ printf("Read 'performance' ok\n");
+
+ /* write it back and read it again */
+ if (rte_sysfs_write_string("powersave", "%s", filename) < 0) {
+ printf("rte_sysfs_write_string() returned error - test failed\n");
+ goto error;
+ }
+ if (rte_sysfs_parse_string(strval, sizeof(strval), "%s", filename) < 0 ||
+ strcmp(strval, "powersave") != 0) {
+ printf("read back '%s' after write - test failed\n", strval);
+ goto error;
+ }
+ printf("Wrote and read back 'powersave' ok\n");
+
+ printf("Test reading invalid values ...\n");
+
+ /* test reading an empty file - expect failure!*/
fd = fopen(filename,"w");
if (fd == NULL) {
printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
goto error;
}
- fprintf(fd,"%u", valid_number);
fclose(fd);
fd = NULL;
- if (eal_parse_sysfs_value(filename, &retval) == 0) {
- printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) == 0) {
+ printf("rte_sysfs_parse_uint() read invalid value - test failed\n");
goto error;
}
@@ -141,8 +195,8 @@ test_parse_sysfs_value(void)
fprintf(fd,"%uJ\n", valid_number);
fclose(fd);
fd = NULL;
- if (eal_parse_sysfs_value(filename, &retval) == 0) {
- printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) == 0) {
+ printf("rte_sysfs_parse_uint() read invalid value - test failed\n");
goto error;
}
@@ -155,14 +209,45 @@ test_parse_sysfs_value(void)
fprintf(fd,"error\n");
fclose(fd);
fd = NULL;
- if (eal_parse_sysfs_value(filename, &retval) == 0) {
- printf("eal_parse_sysfs_value() read invalid value - test failed\n");
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) == 0) {
+ printf("rte_sysfs_parse_uint() read invalid value - test failed\n");
+ goto error;
+ }
+
+ /* test reading a negative value as unsigned - expect failure! */
+ fd = fopen(filename, "w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd, "-1\n");
+ fclose(fd);
+ fd = NULL;
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) == 0) {
+ printf("rte_sysfs_parse_uint() read negative value - test failed\n");
+ goto error;
+ }
+
+ /*
+ * Same, but with leading whitespace: strtoul() skips it before it
+ * negates, so the sign has to be looked for past the whitespace.
+ */
+ fd = fopen(filename, "w");
+ if (fd == NULL) {
+ printf("line %d, Error opening %s: %s\n", __LINE__, filename, strerror(errno));
+ goto error;
+ }
+ fprintf(fd, " -1\n");
+ fclose(fd);
+ fd = NULL;
+ if (rte_sysfs_parse_uint(&retval, "%s", filename) == 0) {
+ printf("rte_sysfs_parse_uint() read negative value - test failed\n");
goto error;
}
close(tmp_file_handle);
unlink(filename);
- printf("eal_parse_sysfs_value() - OK\n");
+ printf("sysfs value functions - OK\n");
return 0;
error:
diff --git a/drivers/bus/auxiliary/linux/auxiliary.c b/drivers/bus/auxiliary/linux/auxiliary.c
index 3a2dca2865..c8d289eecb 100644
--- a/drivers/bus/auxiliary/linux/auxiliary.c
+++ b/drivers/bus/auxiliary/linux/auxiliary.c
@@ -9,6 +9,7 @@
#include <rte_malloc.h>
#include <rte_devargs.h>
#include <rte_memcpy.h>
+#include <rte_sysfs.h>
#include <eal_filesystem.h>
#include "../private.h"
@@ -21,8 +22,7 @@ auxiliary_scan_one(const char *dirname, const char *name)
{
struct rte_auxiliary_device *dev;
struct rte_auxiliary_device *dev2;
- char filename[PATH_MAX];
- unsigned long tmp;
+ long num;
int ret;
dev = malloc(sizeof(*dev));
@@ -36,12 +36,9 @@ auxiliary_scan_one(const char *dirname, const char *name)
}
dev->device.name = dev->name;
- /* Get NUMA node, default to 0 if not present */
- snprintf(filename, sizeof(filename), "%s/%s/numa_node",
- dirname, name);
- if (access(filename, F_OK) == 0 &&
- eal_parse_sysfs_value(filename, &tmp) == 0)
- dev->device.numa_node = tmp;
+ /* Get NUMA node, default to SOCKET_ID_ANY if not present */
+ if (rte_sysfs_parse_int(&num, "%s/%s/numa_node", dirname, name) == 0)
+ dev->device.numa_node = num;
else
dev->device.numa_node = SOCKET_ID_ANY;
diff --git a/drivers/bus/cdx/cdx.c b/drivers/bus/cdx/cdx.c
index c0b46a41ad..8cbe2473a9 100644
--- a/drivers/bus/cdx/cdx.c
+++ b/drivers/bus/cdx/cdx.c
@@ -74,6 +74,7 @@
#include <rte_kvargs.h>
#include <rte_malloc.h>
#include <rte_vfio.h>
+#include <rte_sysfs.h>
#include <eal_export.h>
#include <eal_filesystem.h>
@@ -179,16 +180,14 @@ cdx_scan_one(const char *dirname, const char *dev_name)
}
/* get vendor id */
- snprintf(filename, sizeof(filename), "%s/vendor", dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/vendor", dirname) < 0) {
ret = -1;
goto err;
}
dev->id.vendor_id = (uint16_t)tmp;
/* get device id */
- snprintf(filename, sizeof(filename), "%s/device", dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/device", dirname) < 0) {
ret = -1;
goto err;
}
diff --git a/drivers/bus/pci/linux/pci.c b/drivers/bus/pci/linux/pci.c
index 9aae0a5d14..d40a09e78a 100644
--- a/drivers/bus/pci/linux/pci.c
+++ b/drivers/bus/pci/linux/pci.c
@@ -12,6 +12,7 @@
#include <rte_devargs.h>
#include <rte_memcpy.h>
#include <rte_vfio.h>
+#include <rte_sysfs.h>
#include <eal_export.h>
#include "eal_filesystem.h"
@@ -205,6 +206,7 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
{
char filename[PATH_MAX];
unsigned long tmp;
+ long num;
struct rte_pci_device_internal *pdev;
struct rte_pci_device *dev;
char driver[PATH_MAX];
@@ -221,43 +223,35 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
dev->addr = *addr;
/* get vendor id */
- snprintf(filename, sizeof(filename), "%s/vendor", dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/vendor", dirname) < 0) {
pci_free(pdev);
return -1;
}
dev->id.vendor_id = (uint16_t)tmp;
/* get device id */
- snprintf(filename, sizeof(filename), "%s/device", dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/device", dirname) < 0) {
pci_free(pdev);
return -1;
}
dev->id.device_id = (uint16_t)tmp;
/* get subsystem_vendor id */
- snprintf(filename, sizeof(filename), "%s/subsystem_vendor",
- dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/subsystem_vendor", dirname) < 0) {
pci_free(pdev);
return -1;
}
dev->id.subsystem_vendor_id = (uint16_t)tmp;
/* get subsystem_device id */
- snprintf(filename, sizeof(filename), "%s/subsystem_device",
- dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/subsystem_device", dirname) < 0) {
pci_free(pdev);
return -1;
}
dev->id.subsystem_device_id = (uint16_t)tmp;
/* get class_id */
- snprintf(filename, sizeof(filename), "%s/class",
- dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/class", dirname) < 0) {
pci_free(pdev);
return -1;
}
@@ -266,25 +260,15 @@ pci_scan_one(const char *dirname, const struct rte_pci_addr *addr)
/* get max_vfs */
dev->max_vfs = 0;
- snprintf(filename, sizeof(filename), "%s/max_vfs", dirname);
- if (!access(filename, F_OK) &&
- eal_parse_sysfs_value(filename, &tmp) == 0)
+ if (rte_sysfs_parse_uint(&tmp, "%s/max_vfs", dirname) == 0)
+ dev->max_vfs = (uint16_t)tmp;
+ /* for non igb_uio driver, need kernel version >= 3.8 */
+ else if (rte_sysfs_parse_uint(&tmp, "%s/sriov_numvfs", dirname) == 0)
dev->max_vfs = (uint16_t)tmp;
- else {
- /* for non igb_uio driver, need kernel version >= 3.8 */
- snprintf(filename, sizeof(filename),
- "%s/sriov_numvfs", dirname);
- if (!access(filename, F_OK) &&
- eal_parse_sysfs_value(filename, &tmp) == 0)
- dev->max_vfs = (uint16_t)tmp;
- }
-
- /* get numa node, default to 0 if not present */
- snprintf(filename, sizeof(filename), "%s/numa_node", dirname);
- if (access(filename, F_OK) == 0 &&
- eal_parse_sysfs_value(filename, &tmp) == 0)
- dev->device.numa_node = tmp;
+ /* get numa node, default to SOCKET_ID_ANY if not present */
+ if (rte_sysfs_parse_int(&num, "%s/numa_node", dirname) == 0)
+ dev->device.numa_node = num;
else
dev->device.numa_node = SOCKET_ID_ANY;
diff --git a/drivers/bus/platform/platform.c b/drivers/bus/platform/platform.c
index 90d865a8df..9585fb79e9 100644
--- a/drivers/bus/platform/platform.c
+++ b/drivers/bus/platform/platform.c
@@ -24,6 +24,7 @@
#include <rte_memory.h>
#include <rte_string_fns.h>
#include <rte_vfio.h>
+#include <rte_sysfs.h>
#include "private.h"
@@ -49,8 +50,7 @@ static int
dev_add(const char *dev_name)
{
struct rte_platform_device *pdev, *tmp;
- char path[PATH_MAX];
- unsigned long val;
+ long val;
pdev = calloc(1, sizeof(*pdev));
if (pdev == NULL)
@@ -59,8 +59,10 @@ dev_add(const char *dev_name)
rte_strscpy(pdev->name, dev_name, sizeof(pdev->name));
pdev->device.name = pdev->name;
pdev->device.devargs = rte_bus_find_devargs(&platform_bus, dev_name);
- snprintf(path, sizeof(path), PLATFORM_BUS_DEVICES_PATH "/%s/numa_node", dev_name);
- pdev->device.numa_node = eal_parse_sysfs_value(path, &val) ? rte_socket_id() : val;
+ if (rte_sysfs_parse_int(&val, PLATFORM_BUS_DEVICES_PATH "/%s/numa_node", dev_name) == 0)
+ pdev->device.numa_node = val;
+ else
+ pdev->device.numa_node = rte_socket_id();
RTE_BUS_FOREACH_DEV(tmp, &platform_bus) {
if (!strcmp(tmp->name, pdev->name)) {
diff --git a/drivers/bus/vmbus/linux/vmbus_bus.c b/drivers/bus/vmbus/linux/vmbus_bus.c
index 779ea50b92..9ee7983eb6 100644
--- a/drivers/bus/vmbus/linux/vmbus_bus.c
+++ b/drivers/bus/vmbus/linux/vmbus_bus.c
@@ -19,6 +19,7 @@
#include <rte_malloc.h>
#include <rte_bus_vmbus.h>
#include <rte_kvargs.h>
+#include <rte_sysfs.h>
#include <eal_export.h>
#include "eal_filesystem.h"
@@ -202,11 +203,8 @@ rte_vmbus_map_device(struct rte_vmbus_device *dev)
return -1;
}
- snprintf(filename, sizeof(filename),
- "%s/size", dirname);
- if (eal_parse_sysfs_value(filename, &len) < 0) {
- VMBUS_LOG(ERR,
- "could not read %s", filename);
+ if (rte_sysfs_parse_uint(&len, "%s/size", dirname) < 0) {
+ VMBUS_LOG(ERR, "could not read size of %s", dirname);
return -1;
}
res->len = len;
@@ -280,6 +278,7 @@ vmbus_scan_one(const char *name)
char filename[PATH_MAX];
char dirname[PATH_MAX];
unsigned long tmp;
+ long num;
dev = calloc(1, sizeof(*dev));
if (dev == NULL)
@@ -314,14 +313,12 @@ vmbus_scan_one(const char *name)
goto error;
/* get relid */
- snprintf(filename, sizeof(filename), "%s/id", dirname);
- if (eal_parse_sysfs_value(filename, &tmp) < 0)
+ if (rte_sysfs_parse_uint(&tmp, "%s/id", dirname) < 0)
goto error;
dev->relid = tmp;
/* get monitor id */
- snprintf(filename, sizeof(filename), "%s/monitor_id", dirname);
- if (eal_parse_sysfs_value(filename, &tmp) >= 0) {
+ if (rte_sysfs_parse_uint(&tmp, "%s/monitor_id", dirname) >= 0) {
dev->monitor_id = tmp;
} else {
VMBUS_LOG(NOTICE, "monitor disabled on %s", name);
@@ -333,14 +330,8 @@ vmbus_scan_one(const char *name)
dev->device.numa_node = SOCKET_ID_ANY;
if (vmbus_use_numa(dev)) {
/* get numa node (if present) */
- snprintf(filename, sizeof(filename), "%s/numa_node",
- dirname);
-
- if (access(filename, R_OK) == 0) {
- if (eal_parse_sysfs_value(filename, &tmp) < 0)
- goto error;
- dev->device.numa_node = tmp;
- }
+ if (rte_sysfs_parse_int(&num, "%s/numa_node", dirname) == 0)
+ dev->device.numa_node = num;
}
/* device is valid, add in list (sorted) */
diff --git a/drivers/common/cnxk/roc_model.c b/drivers/common/cnxk/roc_model.c
index f0312a5400..800e1ef013 100644
--- a/drivers/common/cnxk/roc_model.c
+++ b/drivers/common/cnxk/roc_model.c
@@ -105,20 +105,17 @@ is_rvu_device(unsigned long val)
static int
rvu_device_lookup(const char *dirname, uint32_t *part, uint32_t *pass)
{
- char filename[PATH_MAX];
unsigned long val;
/* Check if vendor id is cavium */
- snprintf(filename, sizeof(filename), "%s/vendor", dirname);
- if (plt_sysfs_value_parse(filename, &val) < 0)
+ if (plt_sysfs_value_parse(&val, "%s/vendor", dirname) < 0)
goto error;
if (val != PCI_VENDOR_ID_CAVIUM)
goto error;
/* Get device id */
- snprintf(filename, sizeof(filename), "%s/device", dirname);
- if (plt_sysfs_value_parse(filename, &val) < 0)
+ if (plt_sysfs_value_parse(&val, "%s/device", dirname) < 0)
goto error;
/* Check if device ID belongs to any RVU device */
@@ -126,15 +123,13 @@ rvu_device_lookup(const char *dirname, uint32_t *part, uint32_t *pass)
goto error;
/* Get subsystem_device id */
- snprintf(filename, sizeof(filename), "%s/subsystem_device", dirname);
- if (plt_sysfs_value_parse(filename, &val) < 0)
+ if (plt_sysfs_value_parse(&val, "%s/subsystem_device", dirname) < 0)
goto error;
*part = val >> MODEL_CN10K_PART_SHIFT;
/* Get revision for pass value*/
- snprintf(filename, sizeof(filename), "%s/revision", dirname);
- if (plt_sysfs_value_parse(filename, &val) < 0)
+ if (plt_sysfs_value_parse(&val, "%s/revision", dirname) < 0)
goto error;
*pass = val & MODEL_CN10K_PASS_MASK;
@@ -230,31 +225,14 @@ populate_model(struct roc_model *model, uint32_t midr)
static int
midr_get(unsigned long *val)
{
- const char *file =
- "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1";
- int rc = UTIL_ERR_FS;
- char buf[BUFSIZ];
- char *end = NULL;
- FILE *f;
-
if (val == NULL)
- goto err;
- f = fopen(file, "r");
- if (f == NULL)
- goto err;
-
- if (fgets(buf, sizeof(buf), f) == NULL)
- goto fclose;
+ return UTIL_ERR_FS;
- *val = strtoul(buf, &end, 0);
- if ((buf[0] == '\0') || (end == NULL) || (*end != '\n'))
- goto fclose;
+ if (plt_sysfs_value_parse(val,
+ "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1") < 0)
+ return UTIL_ERR_FS;
- rc = 0;
-fclose:
- fclose(f);
-err:
- return rc;
+ return 0;
}
static void
diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h
index ac4f76473f..71f9d9a256 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h
@@ -23,6 +23,7 @@
#include <rte_seqcount.h>
#include <rte_spinlock.h>
#include <rte_string_fns.h>
+#include <rte_sysfs.h>
#include <rte_tailq.h>
#include <rte_telemetry.h>
@@ -109,7 +110,7 @@
#define plt_pci_device rte_pci_device
#define plt_pci_read_config rte_pci_read_config
#define plt_pci_find_ext_capability rte_pci_find_ext_capability
-#define plt_sysfs_value_parse eal_parse_sysfs_value
+#define plt_sysfs_value_parse rte_sysfs_parse_uint
#define plt_log2_u32 rte_log2_u32
#define plt_cpu_to_be_16 rte_cpu_to_be_16
diff --git a/drivers/common/mlx5/linux/mlx5_common_auxiliary.c b/drivers/common/mlx5/linux/mlx5_common_auxiliary.c
index 3ee2f4638a..07bb899f9e 100644
--- a/drivers/common/mlx5/linux/mlx5_common_auxiliary.c
+++ b/drivers/common/mlx5/linux/mlx5_common_auxiliary.c
@@ -10,6 +10,7 @@
#include <rte_errno.h>
#include <bus_auxiliary_driver.h>
#include <rte_common.h>
+#include <rte_sysfs.h>
#include <eal_export.h>
#include "eal_filesystem.h"
@@ -93,16 +94,12 @@ mlx5_auxiliary_get_pci_str(const struct rte_auxiliary_device *dev,
static int
mlx5_auxiliary_get_numa(const struct rte_auxiliary_device *dev)
{
- unsigned long numa;
- char numa_path[PATH_MAX];
+ char pci_path[PATH_MAX];
+ long numa;
- if (mlx5_auxiliary_get_pci_path(dev, numa_path, sizeof(numa_path)) != 0)
+ if (mlx5_auxiliary_get_pci_path(dev, pci_path, sizeof(pci_path)) != 0)
return SOCKET_ID_ANY;
- if (strcat(numa_path, "/numa_node") == NULL) {
- rte_errno = ENAMETOOLONG;
- return SOCKET_ID_ANY;
- }
- if (eal_parse_sysfs_value(numa_path, &numa) != 0) {
+ if (rte_sysfs_parse_int(&numa, "%s/numa_node", pci_path) != 0) {
rte_errno = EINVAL;
return SOCKET_ID_ANY;
}
diff --git a/drivers/net/af_xdp/rte_eth_af_xdp.c b/drivers/net/af_xdp/rte_eth_af_xdp.c
index 2cdb533276..9fc48e113b 100644
--- a/drivers/net/af_xdp/rte_eth_af_xdp.c
+++ b/drivers/net/af_xdp/rte_eth_af_xdp.c
@@ -38,6 +38,7 @@
#include <rte_ring.h>
#include <rte_spinlock.h>
#include <rte_power_intrinsics.h>
+#include <rte_sysfs.h>
#include "compat.h"
#include "eal_filesystem.h"
@@ -2568,15 +2569,13 @@ rte_pmd_af_xdp_probe(struct rte_vdev_device *dev)
/* get numa node id from net sysfs */
if (dev->device.numa_node == SOCKET_ID_ANY) {
- unsigned long numa = 0;
- char numa_path[PATH_MAX];
+ long numa;
- snprintf(numa_path, sizeof(numa_path), "/sys/class/net/%s/device/numa_node",
- if_name);
- if (access(numa_path, R_OK) != 0 || eal_parse_sysfs_value(numa_path, &numa) != 0)
- dev->device.numa_node = rte_socket_id();
- else
+ if (rte_sysfs_parse_int(&numa, "/sys/class/net/%s/device/numa_node",
+ if_name) == 0)
dev->device.numa_node = numa;
+ else
+ dev->device.numa_node = rte_socket_id();
}
busy_budget = busy_budget == -1 ? ETH_AF_XDP_DFLT_BUSY_BUDGET :
diff --git a/lib/eal/common/eal_filesystem.h b/lib/eal/common/eal_filesystem.h
index 912f446f64..9859fe7241 100644
--- a/lib/eal/common/eal_filesystem.h
+++ b/lib/eal/common/eal_filesystem.h
@@ -128,8 +128,6 @@ eal_get_hugefile_list_seg_path(char *buffer, size_t buflen,
/** define the default filename prefix for the %s values above */
#define HUGEFILE_PREFIX_DEFAULT "rte"
-/** Function to read a single numeric value from a file on the filesystem.
- * Used to read information from files on /sys */
-int eal_parse_sysfs_value(const char *filename, unsigned long *val);
+/* Reading and writing of sysfs values is in <rte_sysfs.h> */
#endif /* EAL_FILESYSTEM_H */
diff --git a/lib/eal/include/meson.build b/lib/eal/include/meson.build
index aef5824e5f..8c0a59f3d7 100644
--- a/lib/eal/include/meson.build
+++ b/lib/eal/include/meson.build
@@ -61,6 +61,7 @@ headers += files(
driver_sdk_headers = files(
'bus_driver.h',
'dev_driver.h',
+ 'rte_sysfs.h',
)
# special case install the generic headers, since they go in a subdir
diff --git a/lib/eal/include/rte_sysfs.h b/lib/eal/include/rte_sysfs.h
new file mode 100644
index 0000000000..d9b59f58c3
--- /dev/null
+++ b/lib/eal/include/rte_sysfs.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Stephen Hemminger
+ */
+
+#ifndef RTE_SYSFS_H
+#define RTE_SYSFS_H
+
+/**
+ * @file
+ * @internal
+ *
+ * Helpers to read and write single values in sysfs, used across DPDK.
+ *
+ * All of these build the path from a printf-style format, so that
+ * callers do not have to construct it separately.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+
+#include <rte_common.h>
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Read an unsigned numeric value from a file, typically under /sys.
+ *
+ * The value is parsed with strtoul() using base 0, so decimal, octal
+ * and 0x-prefixed hexadecimal are all accepted. A negative value is
+ * rejected rather than wrapping; use rte_sysfs_parse_int() for the
+ * attributes that are signed.
+ *
+ * @param val
+ * Where to store the parsed value, unmodified on failure.
+ * @param format
+ * printf-style format describing the path to read.
+ * @return
+ * 0 on success, -1 on error.
+ */
+__rte_internal
+__rte_format_printf(2, 3)
+int rte_sysfs_parse_uint(unsigned long *val, const char *format, ...);
+
+/**
+ * Read an unsigned numeric value from a file, typically under /sys.
+ *
+ * As rte_sysfs_parse_uint(), but takes a va_list, so that a wrapper
+ * can forward its arguments without formatting the path itself.
+ *
+ * @param val
+ * Where to store the parsed value, unmodified on failure.
+ * @param format
+ * printf-style format describing the path to read.
+ * @param ap
+ * Arguments for the format.
+ * @return
+ * 0 on success, -1 on error.
+ */
+__rte_internal
+__rte_format_printf(2, 0)
+int rte_sysfs_vparse_uint(unsigned long *val, const char *format, va_list ap);
+
+/**
+ * Read a signed numeric value from a file, typically under /sys.
+ *
+ * The value is parsed with strtol() using base 0. Some sysfs
+ * attributes are signed, most notably "numa_node" which is -1 when
+ * the device is not associated with any NUMA node.
+ *
+ * @param val
+ * Where to store the parsed value, unmodified on failure.
+ * @param format
+ * printf-style format describing the path to read.
+ * @return
+ * 0 on success, -1 on error.
+ */
+__rte_internal
+__rte_format_printf(2, 3)
+int rte_sysfs_parse_int(long *val, const char *format, ...);
+
+/**
+ * Read a string value from a file, typically under /sys.
+ *
+ * The trailing newline, if any, is stripped.
+ *
+ * @param buf
+ * Where to store the NUL-terminated value. The contents are
+ * indeterminate on failure.
+ * @param buflen
+ * Size of buf, the value is truncated if it does not fit.
+ * @param format
+ * printf-style format describing the path to read.
+ * @return
+ * 0 on success, -1 on error.
+ */
+__rte_internal
+__rte_format_printf(3, 4)
+int rte_sysfs_parse_string(char *buf, size_t buflen, const char *format, ...);
+
+/**
+ * Write a string value to a file, typically under /sys.
+ *
+ * @param str
+ * The NUL-terminated value to write.
+ * @param format
+ * printf-style format describing the path to write.
+ * @return
+ * 0 on success, -1 on error.
+ */
+__rte_internal
+__rte_format_printf(2, 3)
+int rte_sysfs_write_string(const char *str, const char *format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_SYSFS_H */
diff --git a/lib/eal/linux/eal_hugepage_info.c b/lib/eal/linux/eal_hugepage_info.c
index 05c5b3f613..a8da0d5455 100644
--- a/lib/eal/linux/eal_hugepage_info.c
+++ b/lib/eal/linux/eal_hugepage_info.c
@@ -25,6 +25,7 @@
#include <rte_debug.h>
#include <rte_log.h>
#include <rte_common.h>
+#include <rte_sysfs.h>
#include "rte_string_fns.h"
#include "eal_private.h"
@@ -68,18 +69,6 @@ create_shared_memory(const char *filename, const size_t mem_size)
return map_shared_memory(filename, mem_size, O_RDWR | O_CREAT);
}
-static int get_hp_sysfs_value(const char *subdir, const char *file, unsigned long *val)
-{
- char *path = NULL;
- int ret;
-
- if (asprintf(&path, "%s/%s/%s", sys_dir_path, subdir, file) < 0)
- return -1;
- ret = eal_parse_sysfs_value(path, val);
- free(path);
- return ret;
-}
-
/* this function is only called from eal_hugepage_info_init which itself
* is only called from a primary process */
static uint32_t
@@ -92,16 +81,16 @@ get_num_hugepages(const char *subdir, size_t sz, unsigned int reusable_pages)
const char *nr_splus_file = "surplus_hugepages";
/* first, check how many reserved pages kernel reports */
- if (get_hp_sysfs_value(subdir, nr_rsvd_file, &resv_pages) < 0)
+ if (rte_sysfs_parse_uint(&resv_pages, "%s/%s/%s", sys_dir_path, subdir, nr_rsvd_file) < 0)
return 0;
- if (get_hp_sysfs_value(subdir, nr_hp_file, &num_pages) < 0)
+ if (rte_sysfs_parse_uint(&num_pages, "%s/%s/%s", sys_dir_path, subdir, nr_hp_file) < 0)
return 0;
- if (get_hp_sysfs_value(subdir, nr_over_file, &over_pages) < 0)
+ if (rte_sysfs_parse_uint(&over_pages, "%s/%s/%s", sys_dir_path, subdir, nr_over_file) < 0)
over_pages = 0;
- if (get_hp_sysfs_value(subdir, nr_splus_file, &surplus_pages) < 0)
+ if (rte_sysfs_parse_uint(&surplus_pages, "%s/%s/%s", sys_dir_path, subdir, nr_splus_file) < 0)
surplus_pages = 0;
/* adjust num_pages */
@@ -138,7 +127,7 @@ get_num_hugepages(const char *subdir, size_t sz, unsigned int reusable_pages)
static uint32_t
get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz)
{
- char *path = NULL, *socketpath = NULL;
+ char *socketpath = NULL;
DIR *socketdir;
unsigned long num_pages = 0;
const char *nr_hp_file = "free_hugepages";
@@ -158,13 +147,7 @@ get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz)
goto nopages;
}
- if (asprintf(&path, "%s/%s/%s", socketpath, subdir, nr_hp_file) < 0) {
- EAL_LOG(ERR, "Can not format free hugepages path");
- path = NULL;
- goto nopages;
- }
-
- if (eal_parse_sysfs_value(path, &num_pages) < 0)
+ if (rte_sysfs_parse_uint(&num_pages, "%s/%s/%s", socketpath, subdir, nr_hp_file) < 0)
goto nopages;
if (num_pages == 0)
@@ -179,7 +162,6 @@ get_num_hugepages_on_node(const char *subdir, unsigned int socket, size_t sz)
num_pages = UINT32_MAX;
nopages:
- free(path);
free(socketpath);
return num_pages;
diff --git a/lib/eal/linux/eal_lcore.c b/lib/eal/linux/eal_lcore.c
index 29b36dd610..ada1c408f4 100644
--- a/lib/eal/linux/eal_lcore.c
+++ b/lib/eal/linux/eal_lcore.c
@@ -6,6 +6,7 @@
#include <limits.h>
#include <rte_log.h>
+#include <rte_sysfs.h>
#include "eal_private.h"
#include "eal_filesystem.h"
@@ -57,18 +58,13 @@ eal_cpu_socket_id(unsigned lcore_id)
unsigned
eal_cpu_core_id(unsigned lcore_id)
{
- char path[PATH_MAX];
unsigned long id;
- int len = snprintf(path, sizeof(path), SYS_CPU_DIR "/%s", lcore_id, CORE_ID_FILE);
- if (len <= 0 || (unsigned)len >= sizeof(path))
- goto err;
- if (eal_parse_sysfs_value(path, &id) != 0)
- goto err;
- return (unsigned)id;
+ if (rte_sysfs_parse_uint(&id, SYS_CPU_DIR "/%s", lcore_id, CORE_ID_FILE) != 0) {
+ EAL_LOG(ERR, "Error reading core id value from %s "
+ "for lcore %u - assuming core 0", SYS_CPU_DIR, lcore_id);
+ return 0;
+ }
-err:
- EAL_LOG(ERR, "Error reading core id value from %s "
- "for lcore %u - assuming core 0", SYS_CPU_DIR, lcore_id);
- return 0;
+ return (unsigned int)id;
}
diff --git a/lib/eal/unix/eal_filesystem.c b/lib/eal/unix/eal_filesystem.c
index 6b8451cd3e..c6e827f805 100644
--- a/lib/eal/unix/eal_filesystem.c
+++ b/lib/eal/unix/eal_filesystem.c
@@ -76,34 +76,3 @@ int eal_create_runtime_dir(void)
return 0;
}
-
-/* parse a sysfs (or other) file containing one integer value */
-RTE_EXPORT_SYMBOL(eal_parse_sysfs_value)
-int eal_parse_sysfs_value(const char *filename, unsigned long *val)
-{
- FILE *f;
- char buf[BUFSIZ];
- char *end = NULL;
-
- if ((f = fopen(filename, "r")) == NULL) {
- EAL_LOG(ERR, "%s(): cannot open sysfs value %s",
- __func__, filename);
- return -1;
- }
-
- if (fgets(buf, sizeof(buf), f) == NULL) {
- EAL_LOG(ERR, "%s(): cannot read sysfs value %s",
- __func__, filename);
- fclose(f);
- return -1;
- }
- *val = strtoul(buf, &end, 0);
- if ((buf[0] == '\0') || (end == NULL) || (*end != '\n')) {
- EAL_LOG(ERR, "%s(): cannot parse sysfs value %s",
- __func__, filename);
- fclose(f);
- return -1;
- }
- fclose(f);
- return 0;
-}
diff --git a/lib/eal/unix/eal_unix_sysfs.c b/lib/eal/unix/eal_unix_sysfs.c
new file mode 100644
index 0000000000..444155b793
--- /dev/null
+++ b/lib/eal/unix/eal_unix_sysfs.c
@@ -0,0 +1,187 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2026 Stephen Hemminger
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_log.h>
+#include <rte_sysfs.h>
+
+#include <eal_export.h>
+#include "eal_private.h"
+
+/* build the path from the format, then read the first line of that file */
+static int
+sysfs_read_line(char *buf, size_t buflen, const char *format, va_list ap)
+{
+ char path[PATH_MAX];
+ FILE *f;
+ int len;
+
+ len = vsnprintf(path, sizeof(path), format, ap);
+ if (len < 0 || len >= (int)sizeof(path)) {
+ EAL_LOG(ERR, "sysfs path too long");
+ return -1;
+ }
+
+ f = fopen(path, "r");
+ if (f == NULL) {
+ /*
+ * A missing attribute is normal: callers probe for optional
+ * ones such as max_vfs or numa_node. Anything else, such as
+ * a permission problem, is worth reporting.
+ */
+ if (errno == ENOENT)
+ EAL_LOG(DEBUG, "cannot open %s: %s", path, strerror(errno));
+ else
+ EAL_LOG(ERR, "cannot open %s: %s", path, strerror(errno));
+ return -1;
+ }
+
+ if (fgets(buf, buflen, f) == NULL) {
+ EAL_LOG(ERR, "cannot read %s", path);
+ fclose(f);
+ return -1;
+ }
+ fclose(f);
+
+ /* sysfs values are newline terminated, strip it */
+ *strchrnul(buf, '\n') = '\0';
+
+ return 0;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_sysfs_vparse_uint)
+int
+rte_sysfs_vparse_uint(unsigned long *val, const char *format, va_list ap)
+{
+ const char *start;
+ char buf[BUFSIZ];
+ unsigned long tmp;
+ char *end;
+
+ if (sysfs_read_line(buf, sizeof(buf), format, ap) < 0)
+ return -1;
+
+ /*
+ * strtoul() skips leading whitespace and then silently negates a
+ * leading '-', so " -1" would come back as ULONG_MAX. Look for the
+ * sign past any whitespace: attributes that are really signed, such
+ * as numa_node, must use rte_sysfs_parse_int() instead.
+ */
+ start = buf;
+ while (isspace((unsigned char)*start))
+ ++start;
+
+ errno = 0;
+ tmp = strtoul(start, &end, 0);
+ if (end == start || *end != '\0' || errno != 0 || *start == '-') {
+ EAL_LOG(ERR, "cannot parse sysfs value '%s'", buf);
+ return -1;
+ }
+
+ *val = tmp;
+ return 0;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_sysfs_parse_uint)
+int
+rte_sysfs_parse_uint(unsigned long *val, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = rte_sysfs_vparse_uint(val, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_sysfs_parse_int)
+int
+rte_sysfs_parse_int(long *val, const char *format, ...)
+{
+ char buf[BUFSIZ];
+ va_list ap;
+ char *end;
+ long tmp;
+ int ret;
+
+ va_start(ap, format);
+ ret = sysfs_read_line(buf, sizeof(buf), format, ap);
+ va_end(ap);
+ if (ret < 0)
+ return -1;
+
+ errno = 0;
+ tmp = strtol(buf, &end, 0);
+ if (end == buf || *end != '\0' || errno != 0) {
+ EAL_LOG(ERR, "cannot parse sysfs value '%s'", buf);
+ return -1;
+ }
+
+ *val = tmp;
+ return 0;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_sysfs_parse_string)
+int
+rte_sysfs_parse_string(char *buf, size_t buflen, const char *format, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, format);
+ ret = sysfs_read_line(buf, buflen, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+RTE_EXPORT_INTERNAL_SYMBOL(rte_sysfs_write_string)
+int
+rte_sysfs_write_string(const char *str, const char *format, ...)
+{
+ char path[PATH_MAX];
+ va_list ap;
+ FILE *f;
+ int len;
+
+ va_start(ap, format);
+ len = vsnprintf(path, sizeof(path), format, ap);
+ va_end(ap);
+ if (len < 0 || len >= (int)sizeof(path)) {
+ EAL_LOG(ERR, "sysfs path too long");
+ return -1;
+ }
+
+ f = fopen(path, "w");
+ if (f == NULL) {
+ if (errno == ENOENT)
+ EAL_LOG(DEBUG, "cannot open %s: %s", path, strerror(errno));
+ else
+ EAL_LOG(ERR, "cannot open %s: %s", path, strerror(errno));
+ return -1;
+ }
+
+ if (fputs(str, f) < 0) {
+ EAL_LOG(ERR, "cannot write '%s' to %s", str, path);
+ fclose(f);
+ return -1;
+ }
+
+ /* errors on a sysfs write are reported at close time */
+ if (fclose(f) != 0) {
+ EAL_LOG(ERR, "cannot write '%s' to %s: %s", str, path, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/lib/eal/unix/meson.build b/lib/eal/unix/meson.build
index 70af352dab..2498e9266e 100644
--- a/lib/eal/unix/meson.build
+++ b/lib/eal/unix/meson.build
@@ -7,6 +7,7 @@ sources += files(
'eal_filesystem.c',
'eal_firmware.c',
'eal_unix_memory.c',
+ 'eal_unix_sysfs.c',
'eal_unix_thread.c',
'eal_unix_timer.c',
'rte_basename.c',
--
2.53.0
next prev parent reply other threads:[~2026-09-12 6:33 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-12 6:30 [PATCH 0/9] consolidate sysfs access Stephen Hemminger
2026-09-12 6:30 ` Stephen Hemminger [this message]
2026-09-12 6:30 ` [PATCH 2/9] dma/idxd: use common sysfs routines Stephen Hemminger
2026-09-12 6:30 ` [PATCH 3/9] common/ionic: " Stephen Hemminger
2026-09-12 6:30 ` [PATCH 4/9] bus/vmbus: " Stephen Hemminger
2026-09-12 6:30 ` [PATCH 5/9] power: " Stephen Hemminger
2026-09-12 6:30 ` [PATCH 6/9] drivers/bus: remove duplicate sysfs string helpers Stephen Hemminger
2026-09-12 6:30 ` [PATCH 7/9] common/mlx5: use common sysfs routines Stephen Hemminger
2026-09-12 6:30 ` [PATCH 8/9] net/mlx5: " Stephen Hemminger
2026-09-12 6:30 ` [PATCH 9/9] net/mana: " Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 0/9] consolidate sysfs access Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 1/9] eal: add common sysfs value routines Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 2/9] dma/idxd: use common sysfs routines Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 3/9] common/ionic: " Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 4/9] bus/vmbus: " Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 5/9] power: " Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 6/9] drivers/bus: remove duplicate sysfs string helpers Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 7/9] common/mlx5: use common sysfs routines Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 8/9] net/mlx5: " Stephen Hemminger
2026-09-12 17:02 ` [PATCH v2 9/9] net/mana: " Stephen Hemminger
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=20260912063319.4117869-2-stephen@networkplumber.org \
--to=stephen@networkplumber.org \
--cc=bingz@nvidia.com \
--cc=chenbox@nvidia.com \
--cc=ciara.loftus@intel.com \
--cc=dev@dpdk.org \
--cc=dsosnowski@nvidia.com \
--cc=hkalra@marvell.com \
--cc=kirankumark@marvell.com \
--cc=longli@microsoft.com \
--cc=matan@nvidia.com \
--cc=mtahhan@redhat.com \
--cc=ndabilpuram@marvell.com \
--cc=nikhil.agarwal@amd.com \
--cc=nipun.gupta@amd.com \
--cc=orika@nvidia.com \
--cc=parav@nvidia.com \
--cc=skori@marvell.com \
--cc=skoteshwar@marvell.com \
--cc=suanmingm@nvidia.com \
--cc=tduszynski@marvell.com \
--cc=viacheslavo@nvidia.com \
--cc=weh@microsoft.com \
--cc=xuemingl@nvidia.com \
/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