From 9042a10235cf9f1d5980d946303ef5539f5a5319 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Thu, 30 Apr 2026 14:20:03 +0000 Subject: [PATCH 01/11] arena: Create the basis for new collection --- includes/netdata_arena_common.h | 49 ++++++++++++++++++++++++++++++ includes/netdata_cachestat_arena.h | 11 +++++++ includes/netdata_common.h | 8 +++++ includes/netdata_dc_arena.h | 11 +++++++ includes/netdata_dns_arena.h | 11 +++++++ includes/netdata_fd_arena.h | 11 +++++++ includes/netdata_oomkill_arena.h | 11 +++++++ includes/netdata_process_arena.h | 11 +++++++ includes/netdata_shm_arena.h | 11 +++++++ includes/netdata_swap_arena.h | 11 +++++++ includes/netdata_vfs_arena.h | 11 +++++++ kernel/Makefile | 17 +++++++++-- kernel/cachestat_arena_kern.c | 21 +++++++++++++ kernel/dc_arena_kern.c | 21 +++++++++++++ kernel/dns_arena_kern.c | 24 +++++++++++++++ kernel/fd_arena_kern.c | 25 +++++++++++++++ kernel/oomkill_arena_kern.c | 21 +++++++++++++ kernel/process_arena_kern.c | 25 +++++++++++++++ kernel/shm_arena_kern.c | 21 +++++++++++++ kernel/swap_arena_kern.c | 21 +++++++++++++ kernel/vfs_arena_kern.c | 25 +++++++++++++++ 21 files changed, 375 insertions(+), 2 deletions(-) create mode 100644 includes/netdata_arena_common.h create mode 100644 includes/netdata_cachestat_arena.h create mode 100644 includes/netdata_dc_arena.h create mode 100644 includes/netdata_dns_arena.h create mode 100644 includes/netdata_fd_arena.h create mode 100644 includes/netdata_oomkill_arena.h create mode 100644 includes/netdata_process_arena.h create mode 100644 includes/netdata_shm_arena.h create mode 100644 includes/netdata_swap_arena.h create mode 100644 includes/netdata_vfs_arena.h create mode 100644 kernel/cachestat_arena_kern.c create mode 100644 kernel/dc_arena_kern.c create mode 100644 kernel/dns_arena_kern.c create mode 100644 kernel/fd_arena_kern.c create mode 100644 kernel/oomkill_arena_kern.c create mode 100644 kernel/process_arena_kern.c create mode 100644 kernel/shm_arena_kern.c create mode 100644 kernel/swap_arena_kern.c create mode 100644 kernel/vfs_arena_kern.c diff --git a/includes/netdata_arena_common.h b/includes/netdata_arena_common.h new file mode 100644 index 00000000..1af139c9 --- /dev/null +++ b/includes/netdata_arena_common.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_ARENA_COMMON_ +#define _NETDATA_ARENA_COMMON_ 1 + +#if defined(__BPF_FEATURE_ADDR_SPACE_CAST) +#define __arena __attribute__((address_space(1))) +#define __arena_global __attribute__((address_space(1))) +#else +#define __arena +#define __arena_global SEC(".addr_space.1") +#endif + +#ifndef __arg_arena +#define __arg_arena __attribute__((btf_decl_tag("arg:arena"))) +#endif + +#if defined(__TARGET_ARCH_arm64) +#define NETDATA_ARENA_MAP_EXTRA (0x1ull << 32) +#else +#define NETDATA_ARENA_MAP_EXTRA (0x1ull << 44) +#endif + +#define NETDATA_ARENA_MAP_PAGES 256 +#define NETDATA_ARENA_EVENT_SLOTS 1024 + +#define NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) \ + struct { \ + __uint(type, BPF_MAP_TYPE_ARENA); \ + __uint(map_flags, BPF_F_MMAPABLE); \ + __uint(max_entries, NETDATA_ARENA_MAP_PAGES); \ + __ulong(map_extra, NETDATA_ARENA_MAP_EXTRA); \ + } NAME SEC(".maps") + +#define NETDATA_ARENA_QUEUE_DECL(PREFIX, EVENT_TYPE, SLOT_COUNT) \ + struct netdata_##PREFIX##_arena_state_t { \ + __u32 head; \ + EVENT_TYPE events[SLOT_COUNT]; \ + }; \ + extern struct netdata_##PREFIX##_arena_state_t PREFIX##_arena_state; \ + static __always_inline EVENT_TYPE *netdata_##PREFIX##_arena_reserve(void) { \ + __u32 idx = __sync_fetch_and_add(&PREFIX##_arena_state.head, 1); \ + return &PREFIX##_arena_state.events[idx % SLOT_COUNT]; \ + } \ + static __always_inline void netdata_##PREFIX##_arena_submit(EVENT_TYPE *ev) { \ + (void)ev; \ + } + +#endif /* _NETDATA_ARENA_COMMON_ */ diff --git a/includes/netdata_cachestat_arena.h b/includes/netdata_cachestat_arena.h new file mode 100644 index 00000000..821c25bd --- /dev/null +++ b/includes/netdata_cachestat_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_CACHESTAT_ARENA_H_ +#define _NETDATA_CACHESTAT_ARENA_H_ 1 + +#include "netdata_cache_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(cachestat, struct netdata_cachestat_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_CACHESTAT_ARENA_H_ */ diff --git a/includes/netdata_common.h b/includes/netdata_common.h index e6df9e0e..4e5b3d47 100644 --- a/includes/netdata_common.h +++ b/includes/netdata_common.h @@ -252,11 +252,15 @@ static __always_inline __u32 monitor_apps(void *ctrl_tbl) #define NETDATA_BPF_PERCPU_ARRAY_DEF(NAME, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \ NETDATA_BPF_MAP_DEF(NAME, BPF_MAP_TYPE_PERCPU_ARRAY, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) +#ifndef NETDATA_BPF_RINGBUF_DEF #define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) \ NETDATA_BPF_RINGBUF_MAP_DEF(NAME, BPF_MAP_TYPE_RINGBUF, MAX_ENTRIES) +#endif +#ifndef NETDATA_BPF_USER_RINGBUF_DEF #define NETDATA_BPF_USER_RINGBUF_DEF(NAME, MAX_ENTRIES) \ NETDATA_BPF_RINGBUF_MAP_DEF(NAME, BPF_MAP_TYPE_USER_RINGBUF, MAX_ENTRIES) +#endif #else #define NETDATA_BPF_HASH_DEF(NAME, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \ NETDATA_BPF_MAP_DEF(NAME, BPF_MAP_TYPE_HASH, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) @@ -270,12 +274,16 @@ static __always_inline __u32 monitor_apps(void *ctrl_tbl) #define NETDATA_BPF_PERCPU_ARRAY_DEF(NAME, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \ NETDATA_BPF_MAP_DEF(NAME, BPF_MAP_TYPE_ARRAY, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) +#ifndef NETDATA_BPF_RINGBUF_DEF #define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) \ NETDATA_BPF_RINGBUF_MAP_DEF(NAME, BPF_MAP_TYPE_RINGBUF, MAX_ENTRIES) +#endif +#ifndef NETDATA_BPF_USER_RINGBUF_DEF #define NETDATA_BPF_USER_RINGBUF_DEF(NAME, MAX_ENTRIES) \ NETDATA_BPF_RINGBUF_MAP_DEF(NAME, BPF_MAP_TYPE_USER_RINGBUF, MAX_ENTRIES) #endif +#endif #else #define NETDATA_BPF_MAP_DEF(NAME, TYPE, KEY_TYPE, VALUE_TYPE, MAX_ENTRIES) \ diff --git a/includes/netdata_dc_arena.h b/includes/netdata_dc_arena.h new file mode 100644 index 00000000..2c46bce0 --- /dev/null +++ b/includes/netdata_dc_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_DC_ARENA_H_ +#define _NETDATA_DC_ARENA_H_ 1 + +#include "netdata_dc_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(dc, struct netdata_dc_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_DC_ARENA_H_ */ diff --git a/includes/netdata_dns_arena.h b/includes/netdata_dns_arena.h new file mode 100644 index 00000000..4793a52c --- /dev/null +++ b/includes/netdata_dns_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_DNS_ARENA_H_ +#define _NETDATA_DNS_ARENA_H_ 1 + +#include "netdata_dns_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(dns, struct netdata_dns_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_DNS_ARENA_H_ */ diff --git a/includes/netdata_fd_arena.h b/includes/netdata_fd_arena.h new file mode 100644 index 00000000..2821632e --- /dev/null +++ b/includes/netdata_fd_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_FD_ARENA_H_ +#define _NETDATA_FD_ARENA_H_ 1 + +#include "netdata_fd_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(fd, struct netdata_fd_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_FD_ARENA_H_ */ diff --git a/includes/netdata_oomkill_arena.h b/includes/netdata_oomkill_arena.h new file mode 100644 index 00000000..93b69ccc --- /dev/null +++ b/includes/netdata_oomkill_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_OOMKILL_ARENA_H_ +#define _NETDATA_OOMKILL_ARENA_H_ 1 + +#include "netdata_oomkill_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(oomkill, struct netdata_oomkill_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_OOMKILL_ARENA_H_ */ diff --git a/includes/netdata_process_arena.h b/includes/netdata_process_arena.h new file mode 100644 index 00000000..5ad1c659 --- /dev/null +++ b/includes/netdata_process_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_PROCESS_ARENA_H_ +#define _NETDATA_PROCESS_ARENA_H_ 1 + +#include "netdata_process_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(process, struct netdata_process_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_PROCESS_ARENA_H_ */ diff --git a/includes/netdata_shm_arena.h b/includes/netdata_shm_arena.h new file mode 100644 index 00000000..31c9a7fd --- /dev/null +++ b/includes/netdata_shm_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_SHM_ARENA_H_ +#define _NETDATA_SHM_ARENA_H_ 1 + +#include "netdata_shm_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(shm, struct netdata_shm_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_SHM_ARENA_H_ */ diff --git a/includes/netdata_swap_arena.h b/includes/netdata_swap_arena.h new file mode 100644 index 00000000..a46ddaed --- /dev/null +++ b/includes/netdata_swap_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_SWAP_ARENA_H_ +#define _NETDATA_SWAP_ARENA_H_ 1 + +#include "netdata_swap_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(swap, struct netdata_swap_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_SWAP_ARENA_H_ */ diff --git a/includes/netdata_vfs_arena.h b/includes/netdata_vfs_arena.h new file mode 100644 index 00000000..dacb820f --- /dev/null +++ b/includes/netdata_vfs_arena.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef _NETDATA_VFS_ARENA_H_ +#define _NETDATA_VFS_ARENA_H_ 1 + +#include "netdata_vfs_buffer.h" +#include "netdata_arena_common.h" + +NETDATA_ARENA_QUEUE_DECL(vfs, struct netdata_vfs_event_t, NETDATA_ARENA_EVENT_SLOTS); + +#endif /* _NETDATA_VFS_ARENA_H_ */ diff --git a/kernel/Makefile b/kernel/Makefile index 5f7bcf76..f5cd479b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -123,9 +123,20 @@ else NETDATA_RINGBUF_APPS= endif -all: $(NETDATA_APPS) $(NETDATA_RINGBUF_APPS) +NETDATA_ARENA_APPS= cachestat_arena \ + dc_arena \ + dns_arena \ + fd_arena \ + oomkill_arena \ + process_arena \ + shm_arena \ + swap_arena \ + vfs_arena \ + # -dev: ${NETDATA_ALL_APPS} ${NETDATA_RINGBUF_APPS} +all: $(NETDATA_APPS) $(NETDATA_RINGBUF_APPS) $(NETDATA_ARENA_APPS) + +dev: ${NETDATA_ALL_APPS} ${NETDATA_RINGBUF_APPS} ${NETDATA_ARENA_APPS} libbpf: # -fPIE added to be compatible with olders clang/gcc @@ -170,6 +181,8 @@ ${NETDATA_ALL_APPS}: %: %_kern.o ${NETDATA_RINGBUF_APPS}: %: %_kern.o +${NETDATA_ARENA_APPS}: %: %_kern.o + tester: libbpf cd ../tests && $(MAKE) tester diff --git a/kernel/cachestat_arena_kern.c b/kernel/cachestat_arena_kern.c new file mode 100644 index 00000000..1457f5aa --- /dev/null +++ b/kernel/cachestat_arena_kern.c @@ -0,0 +1,21 @@ +#define KBUILD_MODNAME "cachestat_arena_kern" +#include +#include + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_cachestat_arena.h" + +struct netdata_cachestat_arena_state_t cachestat_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_cachestat_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_cachestat_arena_submit(EV) + +#include "cachestat_buffer_kern.c" diff --git a/kernel/dc_arena_kern.c b/kernel/dc_arena_kern.c new file mode 100644 index 00000000..1a90312c --- /dev/null +++ b/kernel/dc_arena_kern.c @@ -0,0 +1,21 @@ +#define KBUILD_MODNAME "dc_arena_kern" +#include +#include + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_dc_arena.h" + +struct netdata_dc_arena_state_t dc_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_dc_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_dc_arena_submit(EV) + +#include "dc_buffer_kern.c" diff --git a/kernel/dns_arena_kern.c b/kernel/dns_arena_kern.c new file mode 100644 index 00000000..8d6200bb --- /dev/null +++ b/kernel/dns_arena_kern.c @@ -0,0 +1,24 @@ +#define KBUILD_MODNAME "dns_arena_kern" +#include +#include +#include +#include +#include + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_dns_arena.h" + +struct netdata_dns_arena_state_t dns_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_dns_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_dns_arena_submit(EV) + +#include "dns_buffer_kern.c" diff --git a/kernel/fd_arena_kern.c b/kernel/fd_arena_kern.c new file mode 100644 index 00000000..d67c0205 --- /dev/null +++ b/kernel/fd_arena_kern.c @@ -0,0 +1,25 @@ +#define KBUILD_MODNAME "fd_arena_kern" +#include +#include +#include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,10,17)) +# include +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_fd_arena.h" + +struct netdata_fd_arena_state_t fd_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_fd_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_fd_arena_submit(EV) + +#include "fd_buffer_kern.c" diff --git a/kernel/oomkill_arena_kern.c b/kernel/oomkill_arena_kern.c new file mode 100644 index 00000000..0552d060 --- /dev/null +++ b/kernel/oomkill_arena_kern.c @@ -0,0 +1,21 @@ +#define KBUILD_MODNAME "oomkill_arena_kern" +#include +#include + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_oomkill_arena.h" + +struct netdata_oomkill_arena_state_t oomkill_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_oomkill_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_oomkill_arena_submit(EV) + +#include "oomkill_buffer_kern.c" diff --git a/kernel/process_arena_kern.c b/kernel/process_arena_kern.c new file mode 100644 index 00000000..404377d8 --- /dev/null +++ b/kernel/process_arena_kern.c @@ -0,0 +1,25 @@ +#define KBUILD_MODNAME "process_arena_kern" +#include +#include +#include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,10,17)) +# include +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_process_arena.h" + +struct netdata_process_arena_state_t process_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_process_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_process_arena_submit(EV) + +#include "process_buffer_kern.c" diff --git a/kernel/shm_arena_kern.c b/kernel/shm_arena_kern.c new file mode 100644 index 00000000..0a602b22 --- /dev/null +++ b/kernel/shm_arena_kern.c @@ -0,0 +1,21 @@ +#define KBUILD_MODNAME "shm_arena_kern" +#include +#include + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_shm_arena.h" + +struct netdata_shm_arena_state_t shm_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_shm_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_shm_arena_submit(EV) + +#include "shm_buffer_kern.c" diff --git a/kernel/swap_arena_kern.c b/kernel/swap_arena_kern.c new file mode 100644 index 00000000..cd3104ae --- /dev/null +++ b/kernel/swap_arena_kern.c @@ -0,0 +1,21 @@ +#define KBUILD_MODNAME "swap_arena_kern" +#include +#include + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_swap_arena.h" + +struct netdata_swap_arena_state_t swap_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_swap_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_swap_arena_submit(EV) + +#include "swap_buffer_kern.c" diff --git a/kernel/vfs_arena_kern.c b/kernel/vfs_arena_kern.c new file mode 100644 index 00000000..8a469656 --- /dev/null +++ b/kernel/vfs_arena_kern.c @@ -0,0 +1,25 @@ +#define KBUILD_MODNAME "vfs_arena_kern" +#include +#include +#include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,10,17)) +# include +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) +#include +#else +#include +#endif +#include "bpf_tracing.h" +#include "bpf_helpers.h" +#include "netdata_arena_common.h" +#include "netdata_vfs_arena.h" + +struct netdata_vfs_arena_state_t vfs_arena_state __arena_global; + +#define NETDATA_BPF_RINGBUF_DEF(NAME, MAX_ENTRIES) NETDATA_BPF_ARENA_DEF(NAME, MAX_ENTRIES) +#define bpf_ringbuf_reserve(MAP, SIZE, FLAGS) netdata_vfs_arena_reserve() +#define bpf_ringbuf_submit(EV, FLAGS) netdata_vfs_arena_submit(EV) + +#include "vfs_buffer_kern.c" From e32829ca1bf5eb86cc27a257508ad9b03403f480 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Thu, 30 Apr 2026 17:46:48 +0000 Subject: [PATCH 02/11] arena: Try to fix CI (P1) --- kernel/Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/Makefile b/kernel/Makefile index f5cd479b..cde82bd4 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -123,6 +123,8 @@ else NETDATA_RINGBUF_APPS= endif +# BPF_MAP_TYPE_ARENA requires kernel >= 6.9 (395520 = 6 * 65536 + 9 * 256) +ifeq ($(shell test $(CURRENT_KERNEL) -ge 395520 ; echo $$?),0) NETDATA_ARENA_APPS= cachestat_arena \ dc_arena \ dns_arena \ @@ -133,6 +135,9 @@ NETDATA_ARENA_APPS= cachestat_arena \ swap_arena \ vfs_arena \ # +else +NETDATA_ARENA_APPS= +endif all: $(NETDATA_APPS) $(NETDATA_RINGBUF_APPS) $(NETDATA_ARENA_APPS) From 3cc6cf55bc21c5b2f543de37c14d9641e084f00f Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Fri, 1 May 2026 01:53:29 +0000 Subject: [PATCH 03/11] arena: Add code to testers --- gotests/main.go | 91 ++++++++++++++++++++++++++++-------------- gotests/main_test.go | 51 ++++++++++++++++++++++-- tests/tester_user.c | 95 ++++++++++++++++++++++++++++++++++---------- tests/tester_user.h | 5 ++- 4 files changed, 188 insertions(+), 54 deletions(-) diff --git a/gotests/main.go b/gotests/main.go index 817e3270..6ed856be 100644 --- a/gotests/main.go +++ b/gotests/main.go @@ -37,6 +37,7 @@ const ( netdataEBPFKernel515 = 331520 netdataEBPFKernel516 = 331776 netdataEBPFKernel68 = 395264 + netdataEBPFKernel69 = 395520 netdataEBPFKernel612 = 396288 netdataV310 = 1 << 0 @@ -99,6 +100,7 @@ type specifyName struct { type module struct { kernels uint32 bufferKernels uint32 + arenaKernels uint32 flags uint64 name string updateNames *[]specifyName @@ -116,6 +118,7 @@ type options struct { unitTest bool showHelp bool bufferMode bool + arenaMode bool } type logState struct { @@ -217,11 +220,11 @@ var ( ebpfModules = []module{ {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV510 | netdataV514, flags: flagBtrfs, name: "btrfs", ctrlTable: "btrfs_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV515 | netdataV514 | netdataV516, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagCachestat, name: "cachestat", ctrlTable: "cstat_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagDC, name: "dc", updateNames: &dcOptionalNames, ctrlTable: "dcstat_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV515 | netdataV514 | netdataV516, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagCachestat, name: "cachestat", ctrlTable: "cstat_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagDC, name: "dc", updateNames: &dcOptionalNames, ctrlTable: "dcstat_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagDisk, name: "disk", ctrlTable: "disk_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagExt4, name: "ext4", ctrlTable: "ext4_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV511 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagFD, name: "fd", ctrlTable: "fd_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV511 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagFD, name: "fd", ctrlTable: "fd_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "fdatasync"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "fsync"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagHardIRQ, name: "hardirq"}, @@ -229,18 +232,18 @@ var ( {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagMount, name: "mount"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "msync"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSocket, name: "socket", ctrlTable: "socket_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagDNS, name: "dns"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagDNS, name: "dns"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagNFS, name: "nfs", ctrlTable: "nfs_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagNetworkViewer, name: "network_viewer", ctrlTable: "nv_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagOOMKill, name: "oomkill"}, - {kernels: netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514 | netdataV510 | netdataV612, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagProcess, name: "process", ctrlTable: "process_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagSHM, name: "shm", ctrlTable: "shm_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagOOMKill, name: "oomkill"}, + {kernels: netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514 | netdataV510 | netdataV612, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagProcess, name: "process", ctrlTable: "process_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagSHM, name: "shm", ctrlTable: "shm_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSoftIRQ, name: "softirq"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "sync"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "syncfs"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "sync_file_range"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514 | netdataV68 | netdataV612, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagSwap, name: "swap", updateNames: &swapOptionalNames, ctrlTable: "swap_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagVFS, name: "vfs", ctrlTable: "vfs_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514 | netdataV68 | netdataV612, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagSwap, name: "swap", updateNames: &swapOptionalNames, ctrlTable: "swap_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagVFS, name: "vfs", ctrlTable: "vfs_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagXFS, name: "xfs", ctrlTable: "xfs_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagZFS, name: "zfs", updateNames: &zfsOptionalNames, ctrlTable: "zfs_ctrl"}, } @@ -415,7 +418,8 @@ func helpText(exe string) string { "--content Test content stored inside hash tables.\n"+ "--iteration Number of iterations when content is read, default value is 1.\n"+ "--pid Specify the number that identifies PID that will be monitored: 0 - Real Parent PID (Default), 1 - Parent PID, 2 - All PID, and 3 - Ignore PID (ring buffer mode).\n"+ - "--buffer Test ring buffer versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns).\n\n"+ + "--buffer Test ring buffer versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns).\n"+ + "--arena Test arena versions of collectors (cachestat, dc, fd, oomkill, process, shm, swap, vfs, dns).\n\n"+ "You can also specify an unique eBPF program developed by Netdata with the following\n"+ "options:\n"+ "--btrfs Latency for btrfs.\n"+ @@ -554,6 +558,9 @@ func parseArguments(args []string, kernelVersion int, logger *logState) (options case "buffer": opts.bufferMode = true opts.flags |= flagContent + case "arena": + opts.arenaMode = true + opts.flags |= flagContent } } @@ -570,6 +577,11 @@ func parseArguments(args []string, kernelVersion int, logger *logState) (options return opts, 1 } + if opts.arenaMode && kernelVersion < netdataEBPFKernel69 { + fmt.Fprintf(logger.writer, "\"Error\" : \"Arena support requires kernel >= 6.9, current version is not supported.\",\n") + return opts, 1 + } + return opts, 0 } @@ -637,13 +649,18 @@ func resolveBinaryDir(netdataPath string) string { return netdataPath } -func candidateMatches(filename string, moduleName string, isReturn bool, version string, rhfVersion int, bufferMode bool) bool { - var prefix string +func modeSuffix(bufferMode bool, arenaMode bool) string { + if arenaMode { + return "_arena" + } if bufferMode { - prefix = fmt.Sprintf("%cnetdata_ebpf_%s_buffer.", map[bool]rune{true: 'r', false: 'p'}[isReturn], moduleName) - } else { - prefix = fmt.Sprintf("%cnetdata_ebpf_%s.", map[bool]rune{true: 'r', false: 'p'}[isReturn], moduleName) + return "_buffer" } + return "" +} + +func candidateMatches(filename string, moduleName string, isReturn bool, version string, rhfVersion int, bufferMode bool, arenaMode bool) bool { + prefix := fmt.Sprintf("%cnetdata_ebpf_%s%s.", map[bool]rune{true: 'r', false: 'p'}[isReturn], moduleName, modeSuffix(bufferMode, arenaMode)) if !strings.HasPrefix(filename, prefix) || !strings.HasSuffix(filename, ".o") { return false } @@ -664,7 +681,7 @@ func candidateMatches(filename string, moduleName string, isReturn bool, version return !hasRHF } -func candidateVersionIndex(filename string, moduleName string, isReturn bool, rhfVersion int, kernels uint32, maxIndex uint32, bufferMode bool) int { +func candidateVersionIndex(filename string, moduleName string, isReturn bool, rhfVersion int, kernels uint32, maxIndex uint32, bufferMode bool, arenaMode bool) int { if rhfVersion == -1 { kernels &^= netdataV514 } @@ -673,7 +690,7 @@ func candidateVersionIndex(filename string, moduleName string, isReturn bool, rh if kernels&(1<= 6.9, current version is not supported.\",\n"); + exit(1); + } + // When user does not specify any flag, we will use common value if (!(flags & NETDATA_FLAG_COLLECTORS)) flags |= ebpf_set_common_flag(); diff --git a/tests/tester_user.h b/tests/tester_user.h index 51ef07f1..b598c7cc 100644 --- a/tests/tester_user.h +++ b/tests/tester_user.h @@ -53,6 +53,7 @@ enum netdata_ebpf_kernel_versions { NETDATA_EBPF_KERNEL_5_15 = 331520, // 331520 = 5 * 65536 + 15 * 256 NETDATA_EBPF_KERNEL_5_16 = 331776, // 331776 = 5 * 65536 + 16 * 256 NETDATA_EBPF_KERNEL_6_8 = 395264, // 395264 = 6 * 65536 + 8 * 256 + NETDATA_EBPF_KERNEL_6_9 = 395520, // 395520 = 6 * 65536 + 9 * 256 NETDATA_EBPF_KERNEL_6_12 = 396288 // 396288 = 6 * 65536 + 12 * 256 }; @@ -164,7 +165,8 @@ enum netdata_thread_OPT { NETDATA_OPT_CONTENT, NETDATA_OPT_ITERATION, NETDATA_OPT_PID, - NETDATA_OPT_BUFFER + NETDATA_OPT_BUFFER, + NETDATA_OPT_ARENA }; typedef struct ebpf_specify_name { @@ -178,6 +180,7 @@ typedef struct ebpf_specify_name { typedef struct ebpf_module { uint32_t kernels; uint32_t buffer_kernels; /* kernel bitmask for buffer mode; 0 = use kernels */ + uint32_t arena_kernels; /* kernel bitmask for arena mode; 0 = use kernels */ uint64_t flags; char *name; ebpf_specify_name_t *update_names; From 5102dfd83479a60e1fbd6d3ad6b5800d79236f98 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Fri, 1 May 2026 02:33:24 +0000 Subject: [PATCH 04/11] arena: Try to fix CI --- includes/netdata_arena_common.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/netdata_arena_common.h b/includes/netdata_arena_common.h index 1af139c9..e7afad03 100644 --- a/includes/netdata_arena_common.h +++ b/includes/netdata_arena_common.h @@ -39,7 +39,9 @@ }; \ extern struct netdata_##PREFIX##_arena_state_t PREFIX##_arena_state; \ static __always_inline EVENT_TYPE *netdata_##PREFIX##_arena_reserve(void) { \ - __u32 idx = __sync_fetch_and_add(&PREFIX##_arena_state.head, 1); \ + /* BPF backend rejects using the XADD return value directly. */ \ + __sync_fetch_and_add(&PREFIX##_arena_state.head, 1); \ + __u32 idx = PREFIX##_arena_state.head - 1; \ return &PREFIX##_arena_state.events[idx % SLOT_COUNT]; \ } \ static __always_inline void netdata_##PREFIX##_arena_submit(EVENT_TYPE *ev) { \ From 6e4d70fde7145a52cf7b5376cd95d3f9114aedef Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Fri, 1 May 2026 23:32:53 +0000 Subject: [PATCH 05/11] arena: Try to fix issues (P1) --- includes/netdata_arena_common.h | 2 +- kernel/Makefile | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/includes/netdata_arena_common.h b/includes/netdata_arena_common.h index e7afad03..4c49f2fc 100644 --- a/includes/netdata_arena_common.h +++ b/includes/netdata_arena_common.h @@ -37,7 +37,7 @@ __u32 head; \ EVENT_TYPE events[SLOT_COUNT]; \ }; \ - extern struct netdata_##PREFIX##_arena_state_t PREFIX##_arena_state; \ + extern __arena struct netdata_##PREFIX##_arena_state_t PREFIX##_arena_state; \ static __always_inline EVENT_TYPE *netdata_##PREFIX##_arena_reserve(void) { \ /* BPF backend rejects using the XADD return value directly. */ \ __sync_fetch_and_add(&PREFIX##_arena_state.head, 1); \ diff --git a/kernel/Makefile b/kernel/Makefile index cde82bd4..39de9cb4 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -139,6 +139,11 @@ else NETDATA_ARENA_APPS= endif +# Arena objects need address-space-cast support so the verifier sees PTR_TO_ARENA +ifneq ($(NETDATA_ARENA_APPS),) +$(addsuffix _kern.o,$(NETDATA_ARENA_APPS)): EXTRA_CFLAGS += -D__BPF_FEATURE_ADDR_SPACE_CAST +endif + all: $(NETDATA_APPS) $(NETDATA_RINGBUF_APPS) $(NETDATA_ARENA_APPS) dev: ${NETDATA_ALL_APPS} ${NETDATA_RINGBUF_APPS} ${NETDATA_ARENA_APPS} From ba07882f15092580715c0ba993a1bc6d10146b11 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Sat, 2 May 2026 00:45:27 +0000 Subject: [PATCH 06/11] arena: Try to fix issues (P2) --- includes/netdata_arena_common.h | 2 +- kernel/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/netdata_arena_common.h b/includes/netdata_arena_common.h index 4c49f2fc..58a70421 100644 --- a/includes/netdata_arena_common.h +++ b/includes/netdata_arena_common.h @@ -42,7 +42,7 @@ /* BPF backend rejects using the XADD return value directly. */ \ __sync_fetch_and_add(&PREFIX##_arena_state.head, 1); \ __u32 idx = PREFIX##_arena_state.head - 1; \ - return &PREFIX##_arena_state.events[idx % SLOT_COUNT]; \ + return (EVENT_TYPE *)&PREFIX##_arena_state.events[idx % SLOT_COUNT]; \ } \ static __always_inline void netdata_##PREFIX##_arena_submit(EVENT_TYPE *ev) { \ (void)ev; \ diff --git a/kernel/Makefile b/kernel/Makefile index 39de9cb4..5dc2ff21 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -141,7 +141,7 @@ endif # Arena objects need address-space-cast support so the verifier sees PTR_TO_ARENA ifneq ($(NETDATA_ARENA_APPS),) -$(addsuffix _kern.o,$(NETDATA_ARENA_APPS)): EXTRA_CFLAGS += -D__BPF_FEATURE_ADDR_SPACE_CAST +$(addsuffix _kern.o,$(NETDATA_ARENA_APPS)): EXTRA_CFLAGS += -D__BPF_FEATURE_ADDR_SPACE_CAST -Wno-address-space-conversion endif all: $(NETDATA_APPS) $(NETDATA_RINGBUF_APPS) $(NETDATA_ARENA_APPS) From 49e81f6d98ec1fc2c5032dc694cc4931a8f0651b Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Sat, 2 May 2026 01:25:48 +0000 Subject: [PATCH 07/11] arena: Try to fix issues (P3) --- includes/netdata_arena_common.h | 6 +++--- kernel/cachestat_buffer_kern.c | 25 +++++++++++++++++-------- kernel/dc_buffer_kern.c | 19 ++++++++++++++----- kernel/dns_buffer_kern.c | 3 ++- kernel/fd_buffer_kern.c | 19 ++++++++++++++----- kernel/oomkill_buffer_kern.c | 7 +++++-- kernel/process_buffer_kern.c | 27 ++++++++++++++++++--------- kernel/shm_buffer_kern.c | 23 ++++++++++++++++------- kernel/swap_buffer_kern.c | 19 ++++++++++++++----- kernel/vfs_buffer_kern.c | 31 ++++++++++++++++++++----------- 10 files changed, 123 insertions(+), 56 deletions(-) diff --git a/includes/netdata_arena_common.h b/includes/netdata_arena_common.h index 58a70421..6624fe65 100644 --- a/includes/netdata_arena_common.h +++ b/includes/netdata_arena_common.h @@ -38,13 +38,13 @@ EVENT_TYPE events[SLOT_COUNT]; \ }; \ extern __arena struct netdata_##PREFIX##_arena_state_t PREFIX##_arena_state; \ - static __always_inline EVENT_TYPE *netdata_##PREFIX##_arena_reserve(void) { \ + static __always_inline __arena EVENT_TYPE *netdata_##PREFIX##_arena_reserve(void) { \ /* BPF backend rejects using the XADD return value directly. */ \ __sync_fetch_and_add(&PREFIX##_arena_state.head, 1); \ __u32 idx = PREFIX##_arena_state.head - 1; \ - return (EVENT_TYPE *)&PREFIX##_arena_state.events[idx % SLOT_COUNT]; \ + return &PREFIX##_arena_state.events[idx % SLOT_COUNT]; \ } \ - static __always_inline void netdata_##PREFIX##_arena_submit(EVENT_TYPE *ev) { \ + static __always_inline void netdata_##PREFIX##_arena_submit(__arena EVENT_TYPE *ev) { \ (void)ev; \ } diff --git a/kernel/cachestat_buffer_kern.c b/kernel/cachestat_buffer_kern.c index 65dbbe67..3f44bdfb 100644 --- a/kernel/cachestat_buffer_kern.c +++ b/kernel/cachestat_buffer_kern.c @@ -11,6 +11,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_cache.h" #include "netdata_cache_buffer.h" @@ -30,15 +31,23 @@ NETDATA_BPF_ARRAY_DEF(cstat_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_cachestat_fill_event(struct netdata_cachestat_event_t *ev, void *ctrl) +static __always_inline void netdata_cachestat_fill_event(struct netdata_cachestat_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -59,7 +68,7 @@ int netdata_add_to_page_cache_lru_buffer(struct pt_regs *ctx) if (!monitor_apps(&cstat_ctrl)) return 0; - struct netdata_cachestat_event_t *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); + struct netdata_cachestat_event_t __arena *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); if (!ev) return 0; @@ -78,7 +87,7 @@ int netdata_mark_page_accessed_buffer(struct pt_regs *ctx) if (!monitor_apps(&cstat_ctrl)) return 0; - struct netdata_cachestat_event_t *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); + struct netdata_cachestat_event_t __arena *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); if (!ev) return 0; @@ -111,7 +120,7 @@ int netdata_set_page_dirty_buffer(struct pt_regs *ctx) if (!monitor_apps(&cstat_ctrl)) return 0; - struct netdata_cachestat_event_t *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); + struct netdata_cachestat_event_t __arena *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); if (!ev) return 0; @@ -136,7 +145,7 @@ int netdata_account_page_dirtied_buffer(struct pt_regs *ctx) if (!monitor_apps(&cstat_ctrl)) return 0; - struct netdata_cachestat_event_t *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); + struct netdata_cachestat_event_t __arena *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); if (!ev) return 0; @@ -157,7 +166,7 @@ int netdata_mark_buffer_dirty_buffer(struct pt_regs *ctx) if (!monitor_apps(&cstat_ctrl)) return 0; - struct netdata_cachestat_event_t *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); + struct netdata_cachestat_event_t __arena *ev = bpf_ringbuf_reserve(&cachestat_events, sizeof(*ev), 0); if (!ev) return 0; diff --git a/kernel/dc_buffer_kern.c b/kernel/dc_buffer_kern.c index a2f20ce2..87a6544d 100644 --- a/kernel/dc_buffer_kern.c +++ b/kernel/dc_buffer_kern.c @@ -10,6 +10,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_dc.h" #include "netdata_dc_buffer.h" @@ -29,15 +30,23 @@ NETDATA_BPF_PERCPU_ARRAY_DEF(dcstat_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_dc_fill_event(struct netdata_dc_event_t *ev, void *ctrl) +static __always_inline void netdata_dc_fill_event(struct netdata_dc_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -58,7 +67,7 @@ int netdata_lookup_fast_buffer(struct pt_regs *ctx) if (!monitor_apps(&dcstat_ctrl)) return 0; - struct netdata_dc_event_t *ev = bpf_ringbuf_reserve(&dc_events, sizeof(*ev), 0); + struct netdata_dc_event_t __arena *ev = bpf_ringbuf_reserve(&dc_events, sizeof(*ev), 0); if (!ev) return 0; @@ -81,7 +90,7 @@ int netdata_d_lookup_buffer(struct pt_regs *ctx) if (!monitor_apps(&dcstat_ctrl)) return 0; - struct netdata_dc_event_t *ev = bpf_ringbuf_reserve(&dc_events, sizeof(*ev), 0); + struct netdata_dc_event_t __arena *ev = bpf_ringbuf_reserve(&dc_events, sizeof(*ev), 0); if (!ev) return 0; diff --git a/kernel/dns_buffer_kern.c b/kernel/dns_buffer_kern.c index b98971b5..b4041dc3 100644 --- a/kernel/dns_buffer_kern.c +++ b/kernel/dns_buffer_kern.c @@ -17,6 +17,7 @@ #include "bpf_endian.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_dns_buffer.h" /************************************************************************************ @@ -174,7 +175,7 @@ int socket__dns_filter_buffer(struct __sk_buff *skb) if (!is_query && !is_response) return 0; - struct netdata_dns_event_t *ev = bpf_ringbuf_reserve(&dns_events, sizeof(*ev), 0); + struct netdata_dns_event_t __arena *ev = bpf_ringbuf_reserve(&dns_events, sizeof(*ev), 0); if (!ev) return 0; diff --git a/kernel/fd_buffer_kern.c b/kernel/fd_buffer_kern.c index 485107c6..c74e0f14 100644 --- a/kernel/fd_buffer_kern.c +++ b/kernel/fd_buffer_kern.c @@ -14,6 +14,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_fd.h" #include "netdata_fd_buffer.h" @@ -33,15 +34,23 @@ NETDATA_BPF_ARRAY_DEF(fd_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_fd_fill_event(struct netdata_fd_event_t *ev, void *ctrl) +static __always_inline void netdata_fd_fill_event(struct netdata_fd_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -82,7 +91,7 @@ int netdata_sys_open_buffer(struct pt_regs *ctx) if (!monitor_apps(&fd_ctrl)) return 0; - struct netdata_fd_event_t *ev = bpf_ringbuf_reserve(&fd_events, sizeof(*ev), 0); + struct netdata_fd_event_t __arena *ev = bpf_ringbuf_reserve(&fd_events, sizeof(*ev), 0); if (!ev) return 0; @@ -132,7 +141,7 @@ int netdata_close_buffer(struct pt_regs *ctx) if (!monitor_apps(&fd_ctrl)) return 0; - struct netdata_fd_event_t *ev = bpf_ringbuf_reserve(&fd_events, sizeof(*ev), 0); + struct netdata_fd_event_t __arena *ev = bpf_ringbuf_reserve(&fd_events, sizeof(*ev), 0); if (!ev) return 0; diff --git a/kernel/oomkill_buffer_kern.c b/kernel/oomkill_buffer_kern.c index 18fe1061..263a87aa 100644 --- a/kernel/oomkill_buffer_kern.c +++ b/kernel/oomkill_buffer_kern.c @@ -10,6 +10,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_oomkill.h" #include "netdata_oomkill_buffer.h" @@ -30,13 +31,15 @@ NETDATA_BPF_RINGBUF_DEF(oomkill_events, NETDATA_OOMKILL_RINGBUF_SIZE); SEC("tracepoint/oom/mark_victim") int netdata_oom_mark_victim_buffer(struct netdata_oom_mark_victim_entry *ptr) { - struct netdata_oomkill_event_t *ev = bpf_ringbuf_reserve(&oomkill_events, sizeof(*ev), 0); + struct netdata_oomkill_event_t __arena *ev = bpf_ringbuf_reserve(&oomkill_events, sizeof(*ev), 0); if (!ev) return 0; + __u32 pid; ev->ct = bpf_ktime_get_ns(); ev->pad = 0; - bpf_probe_read(&ev->pid, sizeof(ev->pid), &ptr->pid); + bpf_probe_read(&pid, sizeof(pid), &ptr->pid); + ev->pid = pid; bpf_ringbuf_submit(ev, 0); return 0; diff --git a/kernel/process_buffer_kern.c b/kernel/process_buffer_kern.c index 41b091f0..a1e6f1e8 100644 --- a/kernel/process_buffer_kern.c +++ b/kernel/process_buffer_kern.c @@ -14,6 +14,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_process.h" #include "netdata_process_buffer.h" @@ -33,15 +34,23 @@ NETDATA_BPF_ARRAY_DEF(process_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_process_fill_event(struct netdata_process_event_t *ev, void *ctrl) +static __always_inline void netdata_process_fill_event(struct netdata_process_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -62,7 +71,7 @@ int netdata_tracepoint_sched_process_exit_buffer(struct netdata_sched_process_ex if (!monitor_apps(&process_ctrl)) return 0; - struct netdata_process_event_t *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); + struct netdata_process_event_t __arena *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); if (!ev) return 0; @@ -81,7 +90,7 @@ int netdata_release_task_buffer(struct pt_regs *ctx) if (!monitor_apps(&process_ctrl)) return 0; - struct netdata_process_event_t *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); + struct netdata_process_event_t __arena *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); if (!ev) return 0; @@ -100,7 +109,7 @@ int netdata_tracepoint_sched_process_exec_buffer(struct netdata_sched_process_ex if (!monitor_apps(&process_ctrl)) return 0; - struct netdata_process_event_t *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); + struct netdata_process_event_t __arena *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); if (!ev) return 0; @@ -139,7 +148,7 @@ int netdata_tracepoint_sched_process_fork_buffer(void *ctx) if (!monitor_apps(&process_ctrl)) return 0; - struct netdata_process_event_t *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); + struct netdata_process_event_t __arena *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); if (!ev) return 0; @@ -173,7 +182,7 @@ int netdata_fork_buffer(struct pt_regs *ctx) libnetdata_update_global(&tbl_total_stats, NETDATA_KEY_ERROR_PROCESS, 1); if (monitor_apps(&process_ctrl)) { - struct netdata_process_event_t *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); + struct netdata_process_event_t __arena *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); if (ev) { netdata_process_fill_event(ev, &process_ctrl); ev->action = NETDATA_PROCESS_EVENT_FORK_ERR; @@ -200,7 +209,7 @@ int netdata_sys_clone_buffer(struct pt_regs *ctx) libnetdata_update_global(&tbl_total_stats, NETDATA_KEY_ERROR_PROCESS, 1); if (monitor_apps(&process_ctrl)) { - struct netdata_process_event_t *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); + struct netdata_process_event_t __arena *ev = bpf_ringbuf_reserve(&process_events, sizeof(*ev), 0); if (ev) { netdata_process_fill_event(ev, &process_ctrl); ev->action = NETDATA_PROCESS_EVENT_FORK_ERR; diff --git a/kernel/shm_buffer_kern.c b/kernel/shm_buffer_kern.c index 94243715..eb7a7225 100644 --- a/kernel/shm_buffer_kern.c +++ b/kernel/shm_buffer_kern.c @@ -10,6 +10,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_shm.h" #include "netdata_shm_buffer.h" @@ -29,15 +30,23 @@ NETDATA_BPF_ARRAY_DEF(shm_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_shm_fill_event(struct netdata_shm_event_t *ev, void *ctrl) +static __always_inline void netdata_shm_fill_event(struct netdata_shm_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -62,7 +71,7 @@ int netdata_syscall_shmget_buffer(struct pt_regs *ctx) if (!monitor_apps(&shm_ctrl)) return 0; - struct netdata_shm_event_t *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); + struct netdata_shm_event_t __arena *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); if (!ev) return 0; @@ -85,7 +94,7 @@ int netdata_syscall_shmat_buffer(struct pt_regs *ctx) if (!monitor_apps(&shm_ctrl)) return 0; - struct netdata_shm_event_t *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); + struct netdata_shm_event_t __arena *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); if (!ev) return 0; @@ -108,7 +117,7 @@ int netdata_syscall_shmdt_buffer(struct pt_regs *ctx) if (!monitor_apps(&shm_ctrl)) return 0; - struct netdata_shm_event_t *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); + struct netdata_shm_event_t __arena *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); if (!ev) return 0; @@ -131,7 +140,7 @@ int netdata_syscall_shmctl_buffer(struct pt_regs *ctx) if (!monitor_apps(&shm_ctrl)) return 0; - struct netdata_shm_event_t *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); + struct netdata_shm_event_t __arena *ev = bpf_ringbuf_reserve(&shm_events, sizeof(*ev), 0); if (!ev) return 0; diff --git a/kernel/swap_buffer_kern.c b/kernel/swap_buffer_kern.c index cd740782..f0cf8183 100644 --- a/kernel/swap_buffer_kern.c +++ b/kernel/swap_buffer_kern.c @@ -10,6 +10,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_swap.h" #include "netdata_swap_buffer.h" @@ -29,15 +30,23 @@ NETDATA_BPF_ARRAY_DEF(swap_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_swap_fill_event(struct netdata_swap_event_t *ev, void *ctrl) +static __always_inline void netdata_swap_fill_event(struct netdata_swap_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -62,7 +71,7 @@ int netdata_swap_readpage_buffer(struct pt_regs *ctx) if (!monitor_apps(&swap_ctrl)) return 0; - struct netdata_swap_event_t *ev = bpf_ringbuf_reserve(&swap_events, sizeof(*ev), 0); + struct netdata_swap_event_t __arena *ev = bpf_ringbuf_reserve(&swap_events, sizeof(*ev), 0); if (!ev) return 0; @@ -85,7 +94,7 @@ int netdata_swap_writepage_buffer(struct pt_regs *ctx) if (!monitor_apps(&swap_ctrl)) return 0; - struct netdata_swap_event_t *ev = bpf_ringbuf_reserve(&swap_events, sizeof(*ev), 0); + struct netdata_swap_event_t __arena *ev = bpf_ringbuf_reserve(&swap_events, sizeof(*ev), 0); if (!ev) return 0; diff --git a/kernel/vfs_buffer_kern.c b/kernel/vfs_buffer_kern.c index 3799638c..3b26eeb3 100644 --- a/kernel/vfs_buffer_kern.c +++ b/kernel/vfs_buffer_kern.c @@ -14,6 +14,7 @@ #include "bpf_tracing.h" #include "bpf_helpers.h" #include "netdata_common.h" +#include "netdata_arena_common.h" #include "netdata_vfs.h" #include "netdata_vfs_buffer.h" @@ -33,15 +34,23 @@ NETDATA_BPF_ARRAY_DEF(vfs_ctrl, __u32, __u64, NETDATA_CONTROLLER_END); * ***********************************************************************************/ -static __always_inline void netdata_vfs_fill_event(struct netdata_vfs_event_t *ev, void *ctrl) +static __always_inline void netdata_vfs_fill_event(struct netdata_vfs_event_t __arena *ev, void *ctrl) { __u32 tgid = 0; + char comm[TASK_COMM_LEN]; ev->ct = bpf_ktime_get_ns(); ev->pid = netdata_get_pid(ctrl, &tgid); ev->tgid = tgid; - libnetdata_update_uid_gid(&ev->uid, &ev->gid); + { + __u64 uid_gid = bpf_get_current_uid_gid(); + ev->uid = (__u32)uid_gid; + ev->gid = (__u32)(uid_gid >> 32); + } #if (LINUX_VERSION_CODE > KERNEL_VERSION(4,11,0)) - bpf_get_current_comm(ev->name, TASK_COMM_LEN); + bpf_get_current_comm(comm, TASK_COMM_LEN); +#pragma unroll + for (int i = 0; i < TASK_COMM_LEN; i++) + ev->name[i] = comm[i]; #else ev->name[0] = '\0'; #endif @@ -78,7 +87,7 @@ int netdata_sys_write_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -115,7 +124,7 @@ int netdata_sys_writev_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -152,7 +161,7 @@ int netdata_sys_read_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -189,7 +198,7 @@ int netdata_sys_readv_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -224,7 +233,7 @@ int netdata_sys_unlink_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -259,7 +268,7 @@ int netdata_vfs_fsync_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -294,7 +303,7 @@ int netdata_vfs_open_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; @@ -329,7 +338,7 @@ int netdata_vfs_create_buffer(struct pt_regs *ctx) if (!monitor_apps(&vfs_ctrl)) return 0; - struct netdata_vfs_event_t *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); + struct netdata_vfs_event_t __arena *ev = bpf_ringbuf_reserve(&vfs_events, sizeof(*ev), 0); if (!ev) return 0; From f1bb492e4f1ed0994a33a0def9ad31769bf87256 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Sat, 2 May 2026 23:43:13 +0000 Subject: [PATCH 08/11] arena: Fix swap runtime on Alma 9 --- gotests/main.go | 19 +++++++++++++++++++ tests/tester_user.c | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/gotests/main.go b/gotests/main.go index 6ed856be..4524bf4d 100644 --- a/gotests/main.go +++ b/gotests/main.go @@ -173,6 +173,20 @@ var ( retprobe: false, required: true, }, + { + programName: "netdata_swap_readpage_buffer", + functionToAttach: "swap_read_folio", + fallbackFunction: "swap_readpage", + retprobe: false, + required: true, + }, + { + programName: "netdata_swap_writepage_buffer", + functionToAttach: "__swap_writepage", + fallbackFunction: "swap_writepage", + retprobe: false, + required: true, + }, } zfsOptionalNames = []specifyName{ @@ -927,6 +941,11 @@ func updateNames(names []specifyName) { continue } + // Reject prefix-only matches (e.g. "swap_read_folio_bdev_sync" != "swap_read_folio") + if len(data) > len(candidate) && data[len(candidate)] != ' ' && data[len(candidate)] != '\t' { + continue + } + end := strings.IndexAny(data, " \n") if end < 0 { end = len(data) diff --git a/tests/tester_user.c b/tests/tester_user.c index 9aec9c4f..47b0cbee 100644 --- a/tests/tester_user.c +++ b/tests/tester_user.c @@ -41,6 +41,11 @@ static ebpf_specify_name_t swap_optional_name[] = { {.program_name = "netdata_sw .fallback_function_to_attach = "swap_writepage", .optional = NULL, .retprobe = 0}, + {.program_name = "netdata_swap_readpage_buffer", + .function_to_attach = "swap_read_folio", + .fallback_function_to_attach = "swap_readpage", + .optional = NULL, + .retprobe = 0}, {.program_name = "netdata_swap_writepage_buffer", .function_to_attach = "__swap_writepage", .fallback_function_to_attach = "swap_writepage", @@ -1208,6 +1213,10 @@ static void ebpf_update_names(ebpf_specify_name_t *names) if (strncmp(cmp, data, len)) continue; + /* Reject prefix-only matches (e.g. "swap_read_folio_bdev_sync" != "swap_read_folio") */ + if (data[len] != ' ' && data[len] != '\n' && data[len] != '\0') + continue; + end = strchr(data, ' '); if (!end) end = strchr(data, '\n'); From 05de9f6c335fc25b744bc7535356969c34d8c9fe Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Sun, 3 May 2026 00:06:13 +0000 Subject: [PATCH 09/11] arena: Reset logs before starting tests --- gotests/main.go | 2 +- tests/tester_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gotests/main.go b/gotests/main.go index 4524bf4d..9030353a 100644 --- a/gotests/main.go +++ b/gotests/main.go @@ -543,7 +543,7 @@ func parseArguments(args []string, kernelVersion int, logger *logState) (options case "log-path": value, i = optionValue(args, i, value) opts.logPath = value - file, err := os.OpenFile(value, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644) + file, err := os.OpenFile(value, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0o644) if err != nil { logger.writer = os.Stderr fmt.Fprintf(logger.writer, "\"Error\": \"Cannot open %s\",\n", value) diff --git a/tests/tester_user.c b/tests/tester_user.c index 47b0cbee..13774f85 100644 --- a/tests/tester_user.c +++ b/tests/tester_user.c @@ -2213,7 +2213,7 @@ uint64_t ebpf_parse_arguments(int argc, char **argv, int kver) case NETDATA_OPT_LOG_PATH: { log_path = optarg; - stdlog = fopen(log_path, "a+"); + stdlog = fopen(log_path, "w"); if (!stdlog) { stdlog = stderr; fprintf(stdlog, "\"Error\": \"Cannot open %s\",\n", log_path); From 7461702f44731f154859f61e077fc540bb141c59 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Sun, 3 May 2026 01:03:39 +0000 Subject: [PATCH 10/11] arena: Additional try on RH family --- gotests/main.go | 8 ++++---- gotests/main_test.go | 38 +++++++++++++++++++++++++++++++++----- tests/tester_user.c | 15 ++++++++------- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/gotests/main.go b/gotests/main.go index 9030353a..c9a2c5ef 100644 --- a/gotests/main.go +++ b/gotests/main.go @@ -281,7 +281,7 @@ func run() int { } logger := &logState{writer: os.Stderr} - opts, parseCode := parseArguments(os.Args[1:], kernelVersion, logger) + opts, parseCode := parseArguments(os.Args[1:], kernelVersion, rhfVersion, logger) if logger.file != nil { defer logger.file.Close() } @@ -469,7 +469,7 @@ func setCommonFlag() uint64 { return flagCollectors & ^(flagFS | flagLoadBinary | flagMDFlush | flagContent) } -func parseArguments(args []string, kernelVersion int, logger *logState) (options, int) { +func parseArguments(args []string, kernelVersion int, rhfVersion int, logger *logState) (options, int) { opts := options{ iterations: 1, mapLevel: 0, @@ -586,12 +586,12 @@ func parseArguments(args []string, kernelVersion int, logger *logState) (options opts.flags &^= flagOOMKill } - if opts.bufferMode && kernelVersion < netdataEBPFKernel58 { + if opts.bufferMode && rhfVersion == -1 && kernelVersion < netdataEBPFKernel58 { fmt.Fprintf(logger.writer, "\"Error\" : \"Ring buffer support requires kernel >= 5.8, current version is not supported.\",\n") return opts, 1 } - if opts.arenaMode && kernelVersion < netdataEBPFKernel69 { + if opts.arenaMode && rhfVersion == -1 && kernelVersion < netdataEBPFKernel69 { fmt.Fprintf(logger.writer, "\"Error\" : \"Arena support requires kernel >= 6.9, current version is not supported.\",\n") return opts, 1 } diff --git a/gotests/main_test.go b/gotests/main_test.go index 20a8d099..a79f30e6 100644 --- a/gotests/main_test.go +++ b/gotests/main_test.go @@ -337,7 +337,7 @@ func TestBinaryAndIPHelpers(t *testing.T) { func TestParseArgumentsUnitTest(t *testing.T) { var log bytes.Buffer - opts, code := parseArguments([]string{"--unit-test"}, netdataEBPFKernel68, &logState{writer: &log}) + opts, code := parseArguments([]string{"--unit-test"}, netdataEBPFKernel68, -1, &logState{writer: &log}) if code != 0 { t.Fatalf("unexpected parse code: %d", code) } @@ -355,7 +355,7 @@ func TestParseArgumentsUnitTest(t *testing.T) { func TestParseArgumentsAll(t *testing.T) { t.Run("--all enables content flag for PID collection", func(t *testing.T) { var log bytes.Buffer - opts, code := parseArguments([]string{"--all"}, netdataEBPFKernel68, &logState{writer: &log}) + opts, code := parseArguments([]string{"--all"}, netdataEBPFKernel68, -1, &logState{writer: &log}) if code != 0 { t.Fatalf("unexpected parse code: %d", code) } @@ -369,7 +369,7 @@ func TestParseArgumentsAll(t *testing.T) { t.Run("--pid 3 is accepted", func(t *testing.T) { var log bytes.Buffer - opts, code := parseArguments([]string{"--all", "--pid", "3"}, netdataEBPFKernel68, &logState{writer: &log}) + opts, code := parseArguments([]string{"--all", "--pid", "3"}, netdataEBPFKernel68, -1, &logState{writer: &log}) if code != 0 { t.Fatalf("unexpected parse code: %d", code) } @@ -385,7 +385,7 @@ func TestParseArgumentsAll(t *testing.T) { func TestParseArgumentsBuffer(t *testing.T) { t.Run("--buffer enables content flag for ring buffer data", func(t *testing.T) { var log bytes.Buffer - opts, code := parseArguments([]string{"--buffer"}, netdataEBPFKernel612, &logState{writer: &log}) + opts, code := parseArguments([]string{"--buffer"}, netdataEBPFKernel612, -1, &logState{writer: &log}) if code != 0 { t.Fatalf("unexpected parse code: %d", code) } @@ -399,7 +399,7 @@ func TestParseArgumentsBuffer(t *testing.T) { t.Run("--arena enables content flag for arena data", func(t *testing.T) { var log bytes.Buffer - opts, code := parseArguments([]string{"--arena"}, netdataEBPFKernel69, &logState{writer: &log}) + opts, code := parseArguments([]string{"--arena"}, netdataEBPFKernel69, -1, &logState{writer: &log}) if code != 0 { t.Fatalf("unexpected parse code: %d", code) } @@ -411,6 +411,34 @@ func TestParseArgumentsBuffer(t *testing.T) { } }) + t.Run("--buffer on RH kernel below 5.8 skips version abort", func(t *testing.T) { + var log bytes.Buffer + // netdataMinimumEBPFKernel (4.11) is below the 5.8 ring-buffer threshold. + // On a non-RH kernel this must be rejected; on RH it must proceed. + _, nonRHCode := parseArguments([]string{"--buffer"}, netdataMinimumEBPFKernel, -1, &logState{writer: &log}) + if nonRHCode == 0 { + t.Fatal("non-RH kernel below 5.8 must be rejected for --buffer") + } + log.Reset() + _, rhCode := parseArguments([]string{"--buffer"}, netdataMinimumEBPFKernel, 1, &logState{writer: &log}) + if rhCode != 0 { + t.Fatalf("RH kernel must bypass version check for --buffer, got code %d", rhCode) + } + }) + + t.Run("--arena on RH kernel below 6.9 skips version abort", func(t *testing.T) { + var log bytes.Buffer + _, nonRHCode := parseArguments([]string{"--arena"}, netdataEBPFKernel514, -1, &logState{writer: &log}) + if nonRHCode == 0 { + t.Fatal("non-RH kernel below 6.9 must be rejected for --arena") + } + log.Reset() + _, rhCode := parseArguments([]string{"--arena"}, netdataEBPFKernel514, 1, &logState{writer: &log}) + if rhCode != 0 { + t.Fatalf("RH kernel must bypass version check for --arena, got code %d", rhCode) + } + }) + t.Run("mountName uses arena suffix", func(t *testing.T) { got := mountName(11, "swap", false, -1, "/tmp", false, true) want := "/tmp/pnetdata_ebpf_swap_arena.6.12.o" diff --git a/tests/tester_user.c b/tests/tester_user.c index 13774f85..d1a9e0fb 100644 --- a/tests/tester_user.c +++ b/tests/tester_user.c @@ -2003,13 +2003,14 @@ static uint64_t ebpf_set_common_flag() * * Parse arguments given from command line. * - * @param argc is the number of arguments - * @param argv vector with values. - * @param kver is the current kernel version + * @param argc is the number of arguments + * @param argv vector with values. + * @param kver is the current kernel version + * @param rhf_version Red Hat family version (-1 if not RH) * * @return It returns the flags used during the simulation. */ -uint64_t ebpf_parse_arguments(int argc, char **argv, int kver) +uint64_t ebpf_parse_arguments(int argc, char **argv, int kver, int rhf_version) { uint64_t flags = 0; int option_index = 0; @@ -2260,12 +2261,12 @@ uint64_t ebpf_parse_arguments(int argc, char **argv, int kver) } } - if (buffer_mode && kver < NETDATA_EBPF_KERNEL_5_8) { + if (buffer_mode && rhf_version == -1 && kver < NETDATA_EBPF_KERNEL_5_8) { fprintf(stdlog, "\"Error\" : \"Ring buffer support requires kernel >= 5.8, current version is not supported.\",\n"); exit(1); } - if (arena_mode && kver < NETDATA_EBPF_KERNEL_6_9) { + if (arena_mode && rhf_version == -1 && kver < NETDATA_EBPF_KERNEL_6_9) { fprintf(stdlog, "\"Error\" : \"Arena support requires kernel >= 6.9, current version is not supported.\",\n"); exit(1); } @@ -2345,7 +2346,7 @@ int main(int argc, char **argv) nprocesses = NETDATA_DEFAULT_PROCESS_NUMBER; } - uint64_t flags = ebpf_parse_arguments(argc, argv, my_kernel); + uint64_t flags = ebpf_parse_arguments(argc, argv, my_kernel, rhf_version); // Start JSON output fprintf(stdlog, "{"); From e83bb33e77f15eb3bd5928e5274ccac5fab34be8 Mon Sep 17 00:00:00 2001 From: thiagoftsm Date: Sun, 3 May 2026 16:45:22 +0000 Subject: [PATCH 11/11] arena: Additional fixes for different distributions --- gotests/main.go | 56 +++++++++++++++++++++++++++++++++++++++++-- gotests/main_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++++ tests/tester_user.c | 54 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 162 insertions(+), 5 deletions(-) diff --git a/gotests/main.go b/gotests/main.go index c9a2c5ef..5f8dffa5 100644 --- a/gotests/main.go +++ b/gotests/main.go @@ -189,6 +189,17 @@ var ( }, } + // close_fd replaced __close_fd in kernel 5.11; RH backported this rename to their 5.10 kernels. + fdOptionalNames = []specifyName{ + { + programName: "netdata_close_buffer", + functionToAttach: "close_fd", + fallbackFunction: "__close_fd", + retprobe: false, + required: true, + }, + } + zfsOptionalNames = []specifyName{ { programName: "netdata_zpl_iter_read", @@ -238,7 +249,7 @@ var ( {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagDC, name: "dc", updateNames: &dcOptionalNames, ctrlTable: "dcstat_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagDisk, name: "disk", ctrlTable: "disk_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagExt4, name: "ext4", ctrlTable: "ext4_ctrl"}, - {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV511 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagFD, name: "fd", ctrlTable: "fd_ctrl"}, + {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV511 | netdataV514, bufferKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, arenaKernels: netdataV510 | netdataV511 | netdataV514 | netdataV515 | netdataV516 | netdataV68 | netdataV612, flags: flagFD, name: "fd", updateNames: &fdOptionalNames, ctrlTable: "fd_ctrl"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "fdatasync"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagSync, name: "fsync"}, {kernels: netdataV310 | netdataV414 | netdataV416 | netdataV418 | netdataV54 | netdataV514, flags: flagHardIRQ, name: "hardirq"}, @@ -378,11 +389,51 @@ func parseKernelRelease(version string) int { func getRedHatRelease() int { data, err := os.ReadFile("/etc/redhat-release") + if err == nil { + if result := parseRedHatRelease(string(data)); result != -1 { + return result + } + } + + data, err = os.ReadFile("/etc/os-release") if err != nil { return -1 } + return parseOSRelease(string(data)) +} + +// parseOSRelease detects RH-family distros from /etc/os-release. +// Matches ID or ID_LIKE containing "rhel", "centos", "almalinux", or "rocky", +// then parses VERSION_ID=X.Y to return X*256+Y. Returns -1 on no match. +func parseOSRelease(content string) int { + major := 0 + minor := 0 + isRHEL := false + + for _, line := range strings.Split(content, "\n") { + if strings.HasPrefix(line, "ID=") || strings.HasPrefix(line, "ID_LIKE=") { + low := strings.ToLower(line) + if strings.Contains(low, "rhel") || strings.Contains(low, "centos") || + strings.Contains(low, "almalinux") || strings.Contains(low, "rocky") { + isRHEL = true + } + } else if strings.HasPrefix(line, "VERSION_ID=") { + val := strings.TrimPrefix(line, "VERSION_ID=") + val = strings.Trim(val, "\"") + parts := strings.SplitN(val, ".", 2) + if len(parts) >= 1 { + major = parseLeadingLong(parts[0]) + } + if len(parts) >= 2 { + minor = parseLeadingLong(parts[1]) + } + } + } - return parseRedHatRelease(string(data)) + if isRHEL && major > 0 { + return major*256 + minor + } + return -1 } func parseRedHatRelease(release string) int { @@ -898,6 +949,7 @@ func writeMapCompatibilityDebug(w io.Writer, unsupportedType uint32, supported m func fillNames() { updateNames(dcOptionalNames) updateNames(swapOptionalNames) + updateNames(fdOptionalNames) updateNames(zfsOptionalNames) } diff --git a/gotests/main_test.go b/gotests/main_test.go index a79f30e6..4f327810 100644 --- a/gotests/main_test.go +++ b/gotests/main_test.go @@ -92,6 +92,63 @@ func TestKernelSelectionHelpers(t *testing.T) { }) } + osReleaseCases := []struct { + name string + content string + want int + }{ + { + name: "alma 9 without redhat-release", + content: `NAME="AlmaLinux" +VERSION="9.4 (Seafoam Ocelot)" +ID="almalinux" +ID_LIKE="rhel centos fedora" +VERSION_ID="9.4" +PLATFORM_ID="platform:el9" +`, + want: 9*256 + 4, + }, + { + name: "rhel 8 via ID_LIKE", + content: `NAME="Red Hat Enterprise Linux" +VERSION="8.9 (Ootpa)" +ID="rhel" +VERSION_ID="8.9" +`, + want: 8*256 + 9, + }, + { + name: "rocky linux", + content: `NAME="Rocky Linux" +ID="rocky" +ID_LIKE="rhel centos fedora" +VERSION_ID="9.3" +`, + want: 9*256 + 3, + }, + { + name: "debian ignored", + content: `NAME="Debian GNU/Linux" +ID=debian +VERSION_ID="12" +`, + want: -1, + }, + { + name: "empty content", + content: ``, + want: -1, + }, + } + + for _, tc := range osReleaseCases { + t.Run("os-release "+tc.name, func(t *testing.T) { + if got := parseOSRelease(tc.content); got != tc.want { + t.Fatalf("unexpected parsed os-release for %q: got %d want %d", tc.name, got, tc.want) + } + }) + } + leadingCases := []struct { input string want int diff --git a/tests/tester_user.c b/tests/tester_user.c index d1a9e0fb..58e8de20 100644 --- a/tests/tester_user.c +++ b/tests/tester_user.c @@ -57,6 +57,18 @@ static ebpf_specify_name_t swap_optional_name[] = { {.program_name = "netdata_sw .optional = NULL, .retprobe = 0}}; +// close_fd replaced __close_fd in kernel 5.11; RH backported this rename to their 5.10 kernels. +static ebpf_specify_name_t fd_optional_name[] = { {.program_name = "netdata_close_buffer", + .function_to_attach = "close_fd", + .fallback_function_to_attach = "__close_fd", + .optional = NULL, + .retprobe = 0}, + {.program_name = NULL, + .function_to_attach = NULL, + .fallback_function_to_attach = NULL, + .optional = NULL, + .retprobe = 0}}; + // Versions 3_10, 4_18 and 5_14 must be always present to keep compatibility with RH family // Version 4_14, 4_16 must be present for syscalls with old name convention // Version 5_4 must be present for kernels newer than 4.17.0 @@ -78,7 +90,7 @@ ebpf_module_t ebpf_modules[] = { { .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 | NETDATA_V5_14, .buffer_kernels = NETDATA_V5_10 | NETDATA_V5_11 | NETDATA_V5_14 | NETDATA_V5_15 | NETDATA_V5_16 | NETDATA_V6_8 | NETDATA_V6_12, .arena_kernels = NETDATA_V5_10 | NETDATA_V5_11 | NETDATA_V5_14 | NETDATA_V5_15 | NETDATA_V5_16 | NETDATA_V6_8 | NETDATA_V6_12, - .flags = NETDATA_FLAG_FD, .name = "fd", .update_names = NULL, .ctrl_table = "fd_ctrl" }, + .flags = NETDATA_FLAG_FD, .name = "fd", .update_names = fd_optional_name, .ctrl_table = "fd_ctrl" }, { .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, .flags = NETDATA_FLAG_SYNC, .name = "fdatasync", .update_names = NULL, .ctrl_table = NULL }, { .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14, @@ -861,6 +873,40 @@ int ebpf_get_kernel_version() * * @param return It returns the Red Hat version on success and -1 otherwise. */ +/* Parse /etc/os-release to detect RH-family distros that lack /etc/redhat-release + * (e.g. minimal Alma 9 containers). Returns major*256+minor on match, -1 otherwise. */ +static int ebpf_get_rh_from_os_release(void) +{ + FILE *fp = fopen("/etc/os-release", "r"); + if (!fp) + return -1; + + char line[VERSION_STRING_LEN + 1]; + int major = 0, minor = 0, is_rhel = 0; + + while (fgets(line, sizeof(line), fp)) { + if (strncmp(line, "ID=", 3) == 0 || strncmp(line, "ID_LIKE=", 8) == 0) { + if (strstr(line, "rhel") || strstr(line, "centos") || + strstr(line, "almalinux") || strstr(line, "rocky")) + is_rhel = 1; + } else if (strncmp(line, "VERSION_ID=", 11) == 0) { + char *val = line + 11; + if (*val == '"') + val++; + char *endp; + major = (int)strtol(val, &endp, 10); + if (*endp == '.') + minor = (int)strtol(endp + 1, NULL, 10); + } + } + + fclose(fp); + + if (is_rhel && major > 0) + return major * 256 + minor; + return -1; +} + int ebpf_get_redhat_release() { char buffer[VERSION_STRING_LEN + 1]; @@ -897,9 +943,9 @@ int ebpf_get_redhat_release() fclose(fp); return ((major * 256) + minor); - } else { - return -1; } + + return ebpf_get_rh_from_os_release(); } /** @@ -2292,6 +2338,7 @@ static void ebpf_fill_names() { ebpf_update_names(dc_optional_name); ebpf_update_names(swap_optional_name); + ebpf_update_names(fd_optional_name); } /** @@ -2303,6 +2350,7 @@ static void ebpf_clean_name_vectors() { ebpf_clean_optional(dc_optional_name); ebpf_clean_optional(swap_optional_name); + ebpf_clean_optional(fd_optional_name); } /**