[PATCH] eal/linux: fix dirty flag for reused hugepages in legacy mem

Maayan Kashani mkashani at nvidia.com
Thu Nov 5 08:17:10 CET 2026


With --huge-unlink=never the hugepage files are kept and mapped again
on the next run. The kernel only zeroes a hugepage the first time it is
mapped from a given file, so these pages still hold the previous run's
content.

The dynamic memory path records this by setting RTE_MEMSEG_FLAG_DIRTY
in alloc_seg(). The legacy path in remap_segment() never sets ms->flags,
so rte_zmalloc_socket() skips the memset and returns stale data.

With --legacy-mem --huge-unlink=never, a second process gets non-zeroed
memory from rte_zmalloc(). mlx5 with sys_mem_en disabled allocates its
internal structures through rte_zmalloc_socket() and then reads stale
pointers from them, which crashes in mlx5_ipool_malloc_cache() during
probe:

  SEGV on unknown address 0x000000000308
    #0 _mlx5_ipool_malloc_cache drivers/net/mlx5/mlx5_utils.c:550
    ...
    #16 mlx5_alloc_shared_dr drivers/net/mlx5/linux/mlx5_os.c:628

Set RTE_MEMSEG_FLAG_DIRTY on segments remapped in legacy mode whenever
existing hugepage files are reused, matching the dynamic path. Why a
reused page is dirty is documented on unlink_existing.

Fixes: 32b4771cd8ef ("eal/linux: allow hugepage file reuse")
Cc: stable at dpdk.org

Suggested-by: Thomas Monjalon <thomas at monjalon.net>
Signed-off-by: Maayan Kashani <mkashani at nvidia.com>
---
 lib/eal/common/eal_internal_cfg.h | 8 +++++++-
 lib/eal/linux/eal_memory.c        | 5 +++--
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/lib/eal/common/eal_internal_cfg.h b/lib/eal/common/eal_internal_cfg.h
index 07cd35167dd..1221e03253f 100644
--- a/lib/eal/common/eal_internal_cfg.h
+++ b/lib/eal/common/eal_internal_cfg.h
@@ -44,7 +44,13 @@ struct simd_bitwidth {
 struct hugepage_file_discipline {
 	/** Unlink files before mapping them to leave no trace in hugetlbfs. */
 	bool unlink_before_mapping;
-	/** Unlink existing files at startup, re-create them before mapping. */
+	/**
+	 * Unlink existing files at startup and re-create them before mapping.
+	 * If false, the files are kept and mapped again. The kernel zeroes a
+	 * hugepage only the first time it is mapped from a given file, so
+	 * reused pages still hold the previous content and must be treated
+	 * as dirty.
+	 */
 	bool unlink_existing;
 };
 
diff --git a/lib/eal/linux/eal_memory.c b/lib/eal/linux/eal_memory.c
index 614f31a308e..0edf66eea5e 100644
--- a/lib/eal/linux/eal_memory.c
+++ b/lib/eal/linux/eal_memory.c
@@ -692,10 +692,10 @@ remap_segment(struct hugepage_file *hugepages, int seg_start, int seg_end)
 	uint64_t page_sz;
 	size_t memseg_len;
 	int socket_id;
-#ifndef RTE_ARCH_64
 	const struct internal_config *internal_conf =
 		eal_get_internal_configuration();
-#endif
+	const bool dirty = !internal_conf->hugepage_file.unlink_existing;
+
 	page_sz = hugepages[seg_start].size;
 	socket_id = hugepages[seg_start].socket_id;
 	seg_len = seg_end - seg_start;
@@ -816,6 +816,7 @@ remap_segment(struct hugepage_file *hugepages, int seg_start, int seg_end)
 		ms->socket_id = hfile->socket_id;
 		ms->nchannel = rte_memory_get_nchannel();
 		ms->nrank = rte_memory_get_nrank();
+		ms->flags = dirty ? RTE_MEMSEG_FLAG_DIRTY : 0;
 
 		rte_fbarray_set_used(arr, ms_idx);
 
-- 
2.25.1



More information about the stable mailing list