From 00919af525d0910683778ec45ec290182586c107 Mon Sep 17 00:00:00 2001 From: Gerd Rausch Date: Thu, 18 Jan 2024 11:02:30 -0800 Subject: [PATCH] verbs: Support the PROCMAP_QUERY ioctl The PROCMAP_QUERY ioctl, available since Linux-6.11, is able to obtain the size of an underlying mapping without the need to parse /proc/self/smaps. Because kernels that support the PROCMAP_QUERY ioctl also support copy_on_fork, environment variable RDMAV_USE_MADVISE must be used to bypass the copy_on_fork feature, and allow PROCMAP_QUERY to be used instead. If PROCMAP_QUERY isn't available on the running kernel, the "smaps" file will be parsed afterall. Signed-off-by: Gerd Rausch --- libibverbs/memory.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/libibverbs/memory.c b/libibverbs/memory.c index c9821e664..c50ed1d60 100644 --- a/libibverbs/memory.c +++ b/libibverbs/memory.c @@ -43,6 +43,10 @@ #include #include #include +#include +#include +#include +#include #include "ibverbs.h" #include "util/rdma_nl.h" @@ -90,11 +94,42 @@ static unsigned long smaps_page_size(FILE *file) static unsigned long get_page_size(void *base) { unsigned long ret = page_size; - pid_t pid; + pid_t pid = getpid(); FILE *file; char buf[1024]; +#ifdef PROCMAP_QUERY + static bool procmap_query_unavailable; + + if (!procmap_query_unavailable) { + struct procmap_query query = {}; + int fd; + bool success; + + snprintf(buf, sizeof(buf), "/proc/%d/maps", pid); + + fd = open(buf, O_RDONLY); + if (fd >= 0) { + query.size = sizeof(query); + query.query_addr = (uintptr_t)base; + + if (ioctl(fd, PROCMAP_QUERY, &query) >= 0) { + ret = query.vma_page_size; + success = true; + } else if (errno == ENOENT) + success = true; + else + success = false; + + close(fd); + + if (success) + return ret; + + procmap_query_unavailable = true; + } + } +#endif - pid = getpid(); snprintf(buf, sizeof(buf), "/proc/%d/smaps", pid); file = fopen(buf, "r" STREAM_CLOEXEC); @@ -134,7 +169,8 @@ int ibv_fork_init(void) if (mm_root) return 0; - if (ibv_is_fork_initialized() == IBV_FORK_UNNEEDED) + if (!check_env("RDMAV_USE_MADVISE") && + ibv_is_fork_initialized() == IBV_FORK_UNNEEDED) return 0; if (too_late)