@cryptotaxi247 / netdata-1 / commits / 575986a69

Improve PID monitoring (step 2) (#13530)

thiagoftsm committed Aug 23, 2022 at 12:44 UTC 575986a692003638f09c975da847062637b915f4
23 files changed +1018 -77
collectors/ebpf.plugin/README.md
+19
@@ -137,6 +137,25 @@ If you do not need to monitor specific metrics for your `cgroups`, you can enabl
137 `ebpf.d.conf`, and then disable the plugin for a specific `thread` by following the steps in the
138 [Configuration](#configuring-ebpfplugin) section.
139
140 +#### Collect PID
141 +
142 +When one of the previous integrations is enabled, `ebpf.plugin` will use Process Identifier (`PID`) to identify the
143 +process group for which it needs to plot data.
144 +
145 +There are different ways to collect PID, and you can select the way `ebpf.plugin` collects data with the following
146 +values:
147 +
148 +- `real parent`: This is the default mode. Collection will aggregate data for the real parent, the thread that creates
149 + child threads.
150 +- `parent`: Parent and real parent are the same when a process starts, but this value can be changed during run time.
151 +- `all`: This option will store all PIDs that run on the host. Note, this method can be expensive for the host,
152 + because more memory needs to be allocated and parsed.
153 +
154 +The threads that have integration with other collectors have an internal clean up wherein they attach either a
155 +`trampoline` or a `kprobe` to `release_task` internal function. To avoid `overload` on this function, `ebpf.plugin`
156 +will only enable these threads integrated with other collectors when the kernel is compiled with
157 +`CONFIG_DEBUG_INFO_BTF`, unless you enable them manually.
158 +
159 #### Integration Dashboard Elements
160
161 When an integration is enabled, your dashboard will also show the following cgroups and apps charts using low-level
collectors/ebpf.plugin/ebpf.c
+29 -29
@@ -77,7 +77,7 @@ ebpf_module_t ebpf_modules[] = {
77 .load = EBPF_LOAD_LEGACY, .targets = dc_targets, .probe_links = NULL, .objects = NULL},
78 { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
79 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
80 - .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
80 + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
81 .apps_routine = ebpf_swap_create_apps_charts, .maps = NULL,
82 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
83 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
@@ -85,12 +85,12 @@ ebpf_module_t ebpf_modules[] = {
85 .load = EBPF_LOAD_LEGACY, .targets = swap_targets, .probe_links = NULL, .objects = NULL},
86 { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
87 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
88 - .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
88 + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
89 .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
90 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
91 .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE,
92 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_14,
93 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
93 + .load = EBPF_LOAD_LEGACY, .targets = vfs_targets, .probe_links = NULL, .objects = NULL},
94 { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
95 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
96 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -114,13 +114,13 @@ ebpf_module_t ebpf_modules[] = {
114 .load = EBPF_LOAD_LEGACY, .targets = mount_targets, .probe_links = NULL, .objects = NULL},
115 { .thread_name = "fd", .config_name = "fd", .enabled = 0, .start_routine = ebpf_fd_thread,
116 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
117 - .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
117 + .apps_level = NETDATA_APPS_LEVEL_REAL_PARENT, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
118 .apps_routine = ebpf_fd_create_apps_charts, .maps = NULL,
119 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fd_config,
120 .config_file = NETDATA_FD_CONFIG_FILE,
121 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4 | NETDATA_V5_11 |
122 NETDATA_V5_14,
123 - .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
123 + .load = EBPF_LOAD_LEGACY, .targets = fd_targets, .probe_links = NULL, .objects = NULL},
124 { .thread_name = "hardirq", .config_name = "hardirq", .enabled = 0, .start_routine = ebpf_hardirq_thread,
125 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
126 .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -145,7 +145,7 @@ ebpf_module_t ebpf_modules[] = {
145 .load = EBPF_LOAD_LEGACY, .targets = NULL, .probe_links = NULL, .objects = NULL},
146 { .thread_name = "shm", .config_name = "shm", .enabled = 0, .start_routine = ebpf_shm_thread,
147 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = NETDATA_EBPF_APPS_FLAG_NO,
148 - .apps_level = NETDATA_APPS_NOT_SET, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
148 + .apps_level = NETDATA_APPS_LEVEL_ALL, .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
149 .apps_routine = ebpf_shm_create_apps_charts, .maps = NULL,
150 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &shm_config,
151 .config_file = NETDATA_DIRECTORY_SHM_CONFIG_FILE,
@@ -314,6 +314,8 @@ ebpf_plugin_stats_t plugin_statistics = {.core = 0, .legacy = 0, .running = 0, .
314
315 #ifdef LIBBPF_MAJOR_VERSION
316 struct btf *default_btf = NULL;
317 +#else
318 +void *default_btf = NULL;
319 #endif
320 char *btf_path = NULL;
321
@@ -1263,35 +1265,28 @@ static void ebpf_update_table_size()
1265 /**
1266 * Set Load mode
1267 *
1266 - * @param load default load mode.
1268 + * @param origin specify the configuration file loaded
1269 */
1268 -static inline void ebpf_set_load_mode(netdata_ebpf_load_mode_t load)
1270 +static inline void ebpf_set_load_mode(netdata_ebpf_load_mode_t load, netdata_ebpf_load_mode_t origin)
1271 {
1270 -#ifdef LIBBPF_MAJOR_VERSION
1271 - if (load == EBPF_LOAD_CORE || load == EBPF_LOAD_PLAY_DICE) {
1272 - load = (!default_btf) ? EBPF_LOAD_LEGACY : EBPF_LOAD_CORE;
1273 - }
1274 -#else
1275 - load = EBPF_LOAD_LEGACY;
1276 -#endif
1277 -
1272 int i;
1273 for (i = 0; ebpf_modules[i].thread_name; i++) {
1280 - // TO DO: Use `load` variable after we change all threads.
1281 - ebpf_modules[i].load = EBPF_LOAD_LEGACY; // load ;
1274 + ebpf_modules[i].load &= ~NETDATA_EBPF_LOAD_METHODS;
1275 + ebpf_modules[i].load |= load | origin ;
1276 }
1277 }
1278
1279 /**
1280 * Update mode
1281 *
1288 - * @param str value read from configuration file.
1282 + * @param str value read from configuration file.
1283 + * @param origin specify the configuration file loaded
1284 */
1290 -static inline void epbf_update_load_mode(char *str)
1285 +static inline void epbf_update_load_mode(char *str, netdata_ebpf_load_mode_t origin)
1286 {
1287 netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(str);
1288
1294 - ebpf_set_load_mode(load);
1289 + ebpf_set_load_mode(load, origin);
1290 }
1291
1292 /**
@@ -1299,9 +1294,11 @@ static inline void epbf_update_load_mode(char *str)
1294 *
1295 * @param disable_apps variable to store information related to apps.
1296 * @param disable_cgroups variable to store information related to cgroups.
1302 - * @param update_every value to overwrite the update frequency set by the server.
1297 + * @param update_every value to overwrite the update frequency set by the server.
1298 + * @param origin specify the configuration file loaded
1299 */
1304 -static void read_collector_values(int *disable_apps, int *disable_cgroups, int update_every)
1300 +static void read_collector_values(int *disable_apps, int *disable_cgroups,
1301 + int update_every, netdata_ebpf_load_mode_t origin)
1302 {
1303 // Read global section
1304 char *value;
@@ -1323,7 +1320,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups, int u
1320
1321 value = appconfig_get(&collector_config, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, EBPF_CFG_DEFAULT_PROGRAM);
1322
1326 - epbf_update_load_mode(value);
1323 + epbf_update_load_mode(value, origin);
1324
1325 ebpf_update_interval(update_every);
1326
@@ -1501,6 +1498,7 @@ static void read_collector_values(int *disable_apps, int *disable_cgroups, int u
1498 static int load_collector_config(char *path, int *disable_apps, int *disable_cgroups, int update_every)
1499 {
1500 char lpath[4096];
1501 + netdata_ebpf_load_mode_t origin;
1502
1503 snprintf(lpath, 4095, "%s/%s", path, NETDATA_EBPF_CONFIG_FILE);
1504 if (!appconfig_load(&collector_config, lpath, 0, NULL)) {
@@ -1508,9 +1506,11 @@ static int load_collector_config(char *path, int *disable_apps, int *disable_cgr
1506 if (!appconfig_load(&collector_config, lpath, 0, NULL)) {
1507 return -1;
1508 }
1511 - }
1509 + origin = EBPF_LOADED_FROM_STOCK;
1510 + } else
1511 + origin = EBPF_LOADED_FROM_USER;
1512
1513 - read_collector_values(disable_apps, disable_cgroups, update_every);
1513 + read_collector_values(disable_apps, disable_cgroups, update_every, origin);
1514
1515 return 0;
1516 }
@@ -1554,7 +1554,7 @@ static inline void ebpf_load_thread_config()
1554 {
1555 int i;
1556 for (i = 0; ebpf_modules[i].thread_name; i++) {
1557 - ebpf_update_module(&ebpf_modules[i]);
1557 + ebpf_update_module(&ebpf_modules[i], default_btf);
1558 }
1559 }
1560
@@ -1773,14 +1773,14 @@ static void ebpf_parse_args(int argc, char **argv)
1773 break;
1774 }
1775 case EBPF_OPTION_LEGACY: {
1776 - ebpf_set_load_mode(EBPF_LOAD_LEGACY);
1776 + ebpf_set_load_mode(EBPF_LOAD_LEGACY, EBPF_LOADED_FROM_USER);
1777 #ifdef NETDATA_INTERNAL_CHECKS
1778 info("EBPF running with \"LEGACY\" code, because it was started with the option \"[-]-legacy\".");
1779 #endif
1780 break;
1781 }
1782 case EBPF_OPTION_CORE: {
1783 - ebpf_set_load_mode(EBPF_LOAD_CORE);
1783 + ebpf_set_load_mode(EBPF_LOAD_CORE, EBPF_LOADED_FROM_USER);
1784 #ifdef NETDATA_INTERNAL_CHECKS
1785 info("EBPF running with \"CO-RE\" code, because it was started with the option \"[-]-core\".");
1786 #endif
collectors/ebpf.plugin/ebpf.d.conf
+7 -4
@@ -26,16 +26,16 @@
26 #
27 # eBPF Programs
28 #
29 -# The eBPF collector enables and runs the following eBPF programs by default:
29 +# The eBPF collector has the following eBPF programs:
30 #
31 # `cachestat` : Make charts for kernel functions related to page cache.
32 # `dcstat` : Make charts for kernel functions related to directory cache.
33 # `disk` : Monitor I/O latencies for disks
34 # `fd` : This eBPF program creates charts that show information about file manipulation.
35 -# `mdflush` : Monitors flush counts for multi-devices.
36 -# `mount` : Monitor calls for syscalls mount and umount
35 # `filesystem`: Monitor calls for functions used to manipulate specific filesystems
36 # `hardirq` : Monitor latency of serving hardware interrupt requests (hard IRQs).
37 +# `mdflush` : Monitors flush counts for multi-devices.
38 +# `mount` : Monitor calls for syscalls mount and umount
39 # `oomkill` : This eBPF program creates a chart that shows which process got OOM killed and when.
40 # `process` : This eBPF program creates charts that show information about process life.
41 # `shm` : Monitor calls for syscalls shmget, shmat, shmdt and shmctl.
@@ -46,6 +46,9 @@
46 # `swap` : Monitor calls for internal swap functions.
47 # `vfs` : This eBPF program creates charts that show information about process VFS IO, VFS file manipulation and
48 # files removed.
49 +#
50 +# When plugin detects that system has support to BTF, it enables integration with apps.plugin.
51 +#
52 [ebpf programs]
53 cachestat = no
54 dcstat = no
@@ -57,7 +60,7 @@
60 mount = yes
61 oomkill = yes
62 process = yes
60 - shm = yes
63 + shm = no
64 socket = yes
65 softirq = yes
66 sync = yes
collectors/ebpf.plugin/ebpf.d/fd.conf
+3 -1
@@ -11,9 +11,11 @@
11 # The `pid table size` defines the maximum number of PIDs stored inside the hash table.
12 #
13 # Uncomment lines to define specific options for thread.
14 -#[global]
14 +[global]
15 # ebpf load mode = entry
16 # apps = yes
17 # cgroups = no
18 # update every = 10
19 # pid table size = 32768
20 + ebpf type format = auto
21 + ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.d/vfs.conf
+3 -1
@@ -9,9 +9,11 @@
9 # the setting `apps` and `cgroups` to 'no'.
10 #
11 # Uncomment lines to define specific options for thread.
12 -#[global]
12 +[global]
13 # ebpf load mode = entry
14 # apps = yes
15 # cgroups = no
16 # update every = 10
17 # pid table size = 32768
18 + ebpf type format = auto
19 + ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.h
+4
@@ -271,7 +271,11 @@ extern sem_t *shm_sem_ebpf_cgroup;
271 extern pthread_mutex_t mutex_cgroup_shm;
272 extern size_t all_pids_count;
273 extern ebpf_plugin_stats_t plugin_statistics;
274 +#ifdef LIBBPF_MAJOR_VERSION
275 extern struct btf *default_btf;
276 +#else
277 +extern void *default_btf;
278 +#endif
279
280 // Socket functions and variables
281 // Common functions
collectors/ebpf.plugin/ebpf_cachestat.c
+30 -1
@@ -67,6 +67,7 @@ static void ebpf_cachestat_disable_probe(struct cachestat_bpf *obj)
67 bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
68 bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
69 bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_kprobe, false);
70 + bpf_program__set_autoload(obj->progs.netdata_release_task_kprobe, false);
71 }
72
73 /*
@@ -105,6 +106,7 @@ static void ebpf_cachestat_disable_trampoline(struct cachestat_bpf *obj)
106 bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
107 bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
108 bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_fentry, false);
109 + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
110 }
111
112 /*
@@ -156,6 +158,9 @@ static inline void netdata_set_trampoline_target(struct cachestat_bpf *obj)
158
159 bpf_program__set_attach_target(obj->progs.netdata_mark_buffer_dirty_fentry, 0,
160 cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name);
161 +
162 + bpf_program__set_attach_target(obj->progs.netdata_release_task_fentry, 0,
163 + EBPF_COMMON_FNCT_CLEAN_UP);
164 }
165
166 /**
@@ -210,6 +215,13 @@ static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj)
215 if (ret)
216 return -1;
217
218 + obj->links.netdata_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_kprobe,
219 + false,
220 + EBPF_COMMON_FNCT_CLEAN_UP);
221 + ret = libbpf_get_error(obj->links.netdata_release_task_kprobe);
222 + if (ret)
223 + return -1;
224 +
225 return 0;
226 }
227
@@ -241,6 +253,19 @@ static void ebpf_cachestat_set_hash_tables(struct cachestat_bpf *obj)
253 cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd = bpf_map__fd(obj->maps.cstat_ctrl);
254 }
255
256 +/**
257 + * Disable Release Task
258 + *
259 + * Disable release task when apps is not enabled.
260 + *
261 + * @param obj is the main structure for bpf objects.
262 + */
263 +static void ebpf_cachestat_disable_release_task(struct cachestat_bpf *obj)
264 +{
265 + bpf_program__set_autoload(obj->progs.netdata_release_task_kprobe, false);
266 + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
267 +}
268 +
269 /**
270 * Load and attach
271 *
@@ -268,6 +293,9 @@ static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf
293
294 ebpf_cachestat_adjust_map_size(obj, em);
295
296 + if (!em->apps_charts && !em->cgroup_charts)
297 + ebpf_cachestat_disable_release_task(obj);
298 +
299 int ret = cachestat_bpf__load(obj);
300 if (ret) {
301 return ret;
@@ -1227,7 +1255,8 @@ static void ebpf_cachestat_set_internal_value()
1255 static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1256 {
1257 int ret = 0;
1230 - if (em->load == EBPF_LOAD_LEGACY) {
1258 + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].mode);
1259 + if (em->load & EBPF_LOAD_LEGACY) {
1260 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1261 if (!em->probe_links) {
1262 ret = -1;
collectors/ebpf.plugin/ebpf_dcstat.c
+30 -1
@@ -65,6 +65,7 @@ static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
65 {
66 bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
67 bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
68 + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
69 }
70
71 /*
@@ -78,6 +79,7 @@ static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
79 {
80 bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
81 bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
82 + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
83 }
84
85 /**
@@ -94,6 +96,9 @@ static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
96
97 bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
98 dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
99 +
100 + bpf_program__set_attach_target(obj->progs.netdata_dcstat_release_task_fentry, 0,
101 + EBPF_COMMON_FNCT_CLEAN_UP);
102 }
103
104 /**
@@ -125,6 +130,13 @@ static int ebpf_dc_attach_probes(struct dc_bpf *obj)
130 if (ret)
131 return -1;
132
133 + obj->links.netdata_dcstat_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_dcstat_release_task_kprobe,
134 + false,
135 + EBPF_COMMON_FNCT_CLEAN_UP);
136 + ret = libbpf_get_error(obj->links.netdata_dcstat_release_task_kprobe);
137 + if (ret)
138 + return -1;
139 +
140 return 0;
141 }
142
@@ -179,6 +191,19 @@ netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
191 return EBPF_LOAD_RETPROBE;
192 }
193
194 +/**
195 + * Disable Release Task
196 + *
197 + * Disable release task when apps is not enabled.
198 + *
199 + * @param obj is the main structure for bpf objects.
200 + */
201 +static void ebpf_dc_disable_release_task(struct dc_bpf *obj)
202 +{
203 + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
204 + bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
205 +}
206 +
207 /**
208 * Load and attach
209 *
@@ -202,6 +227,9 @@ static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
227
228 ebpf_dc_adjust_map_size(obj, em);
229
230 + if (!em->apps_charts && !em->cgroup_charts)
231 + ebpf_dc_disable_release_task(obj);
232 +
233 int ret = dc_bpf__load(obj);
234 if (ret) {
235 return ret;
@@ -1116,7 +1144,8 @@ static void ebpf_dcstat_allocate_global_vectors(int apps)
1144 static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1145 {
1146 int ret = 0;
1119 - if (em->load == EBPF_LOAD_LEGACY) {
1147 + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode);
1148 + if (em->load & EBPF_LOAD_LEGACY) {
1149 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1150 if (!em->probe_links) {
1151 ret = -1;
collectors/ebpf.plugin/ebpf_fd.c
+325 -6
@@ -38,6 +38,286 @@ static netdata_idx_t *fd_values = NULL;
38 netdata_fd_stat_t *fd_vector = NULL;
39 netdata_fd_stat_t **fd_pid = NULL;
40
41 +netdata_ebpf_targets_t fd_targets[] = { {.name = "open", .mode = EBPF_LOAD_TRAMPOLINE},
42 + {.name = "close", .mode = EBPF_LOAD_TRAMPOLINE},
43 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
44 +
45 +#ifdef LIBBPF_MAJOR_VERSION
46 +#include "includes/fd.skel.h" // BTF code
47 +
48 +static struct fd_bpf *bpf_obj = NULL;
49 +
50 +/**
51 + * Disable probe
52 + *
53 + * Disable all probes to use exclusively another method.
54 + *
55 + * @param obj is the main structure for bpf objects
56 +*/
57 +static inline void ebpf_fd_disable_probes(struct fd_bpf *obj)
58 +{
59 + bpf_program__set_autoload(obj->progs.netdata_sys_open_kprobe, false);
60 + bpf_program__set_autoload(obj->progs.netdata_sys_open_kretprobe, false);
61 + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
62 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
63 + bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
64 + bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
65 + bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
66 + } else {
67 + bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
68 + bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
69 + bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
70 + }
71 +}
72 +
73 +/*
74 + * Disable specific probe
75 + *
76 + * Disable probes according the kernel version
77 + *
78 + * @param obj is the main structure for bpf objects
79 + */
80 +static inline void ebpf_disable_specific_probes(struct fd_bpf *obj)
81 +{
82 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
83 + bpf_program__set_autoload(obj->progs.netdata___close_fd_kretprobe, false);
84 + bpf_program__set_autoload(obj->progs.netdata___close_fd_kprobe, false);
85 + } else {
86 + bpf_program__set_autoload(obj->progs.netdata_close_fd_kretprobe, false);
87 + bpf_program__set_autoload(obj->progs.netdata_close_fd_kprobe, false);
88 + }
89 +}
90 +
91 +/*
92 + * Disable trampoline
93 + *
94 + * Disable all trampoline to use exclusively another method.
95 + *
96 + * @param obj is the main structure for bpf objects.
97 + */
98 +static inline void ebpf_disable_trampoline(struct fd_bpf *obj)
99 +{
100 + bpf_program__set_autoload(obj->progs.netdata_sys_open_fentry, false);
101 + bpf_program__set_autoload(obj->progs.netdata_sys_open_fexit, false);
102 + bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
103 + bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
104 + bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
105 + bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
106 + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
107 +}
108 +
109 +/*
110 + * Disable specific trampoline
111 + *
112 + * Disable trampoline according to kernel version.
113 + *
114 + * @param obj is the main structure for bpf objects.
115 + */
116 +static inline void ebpf_disable_specific_trampoline(struct fd_bpf *obj)
117 +{
118 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
119 + bpf_program__set_autoload(obj->progs.netdata___close_fd_fentry, false);
120 + bpf_program__set_autoload(obj->progs.netdata___close_fd_fexit, false);
121 + } else {
122 + bpf_program__set_autoload(obj->progs.netdata_close_fd_fentry, false);
123 + bpf_program__set_autoload(obj->progs.netdata_close_fd_fexit, false);
124 + }
125 +}
126 +
127 +/**
128 + * Set trampoline target
129 + *
130 + * Set the targets we will monitor.
131 + *
132 + * @param obj is the main structure for bpf objects.
133 + */
134 +static void ebpf_set_trampoline_target(struct fd_bpf *obj)
135 +{
136 + bpf_program__set_attach_target(obj->progs.netdata_sys_open_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
137 + bpf_program__set_attach_target(obj->progs.netdata_sys_open_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
138 + bpf_program__set_attach_target(obj->progs.netdata_release_task_fd_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
139 +
140 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
141 + bpf_program__set_attach_target(
142 + obj->progs.netdata_close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
143 + bpf_program__set_attach_target(obj->progs.netdata_close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
144 + } else {
145 + bpf_program__set_attach_target(
146 + obj->progs.netdata___close_fd_fentry, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
147 + bpf_program__set_attach_target(
148 + obj->progs.netdata___close_fd_fexit, 0, fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
149 + }
150 +}
151 +
152 +/**
153 + * Mount Attach Probe
154 + *
155 + * Attach probes to target
156 + *
157 + * @param obj is the main structure for bpf objects.
158 + *
159 + * @return It returns 0 on success and -1 otherwise.
160 + */
161 +static int ebpf_fd_attach_probe(struct fd_bpf *obj)
162 +{
163 + obj->links.netdata_sys_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kprobe, false,
164 + fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
165 + int ret = libbpf_get_error(obj->links.netdata_sys_open_kprobe);
166 + if (ret)
167 + return -1;
168 +
169 + obj->links.netdata_sys_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_sys_open_kretprobe, true,
170 + fd_targets[NETDATA_FD_SYSCALL_OPEN].name);
171 + ret = libbpf_get_error(obj->links.netdata_sys_open_kretprobe);
172 + if (ret)
173 + return -1;
174 +
175 + obj->links.netdata_release_task_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_fd_kprobe,
176 + false,
177 + EBPF_COMMON_FNCT_CLEAN_UP);
178 + ret = libbpf_get_error(obj->links.netdata_release_task_fd_kprobe);
179 + if (ret)
180 + return -1;
181 +
182 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
183 + obj->links.netdata_close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kretprobe, true,
184 + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
185 + ret = libbpf_get_error(obj->links.netdata_close_fd_kretprobe);
186 + if (ret)
187 + return -1;
188 +
189 + obj->links.netdata_close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_close_fd_kprobe, false,
190 + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
191 + ret = libbpf_get_error(obj->links.netdata_close_fd_kprobe);
192 + if (ret)
193 + return -1;
194 + } else {
195 + obj->links.netdata___close_fd_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kretprobe,
196 + true,
197 + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
198 + ret = libbpf_get_error(obj->links.netdata___close_fd_kretprobe);
199 + if (ret)
200 + return -1;
201 +
202 + obj->links.netdata___close_fd_kprobe = bpf_program__attach_kprobe(obj->progs.netdata___close_fd_kprobe,
203 + false,
204 + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name);
205 + ret = libbpf_get_error(obj->links.netdata___close_fd_kprobe);
206 + if (ret)
207 + return -1;
208 + }
209 +
210 + return 0;
211 +}
212 +
213 +/**
214 + * Set target values
215 + *
216 + * Set pointers used to laod data.
217 + */
218 +static void ebpf_fd_set_target_values()
219 +{
220 + static char *close_targets[] = {"close_fd", "__close_fd"};
221 + static char *open_targets[] = {"do_sys_openat2", "do_sys_open"};
222 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_11) {
223 + fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[0];
224 + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[0];
225 + } else {
226 + fd_targets[NETDATA_FD_SYSCALL_OPEN].name = open_targets[1];
227 + fd_targets[NETDATA_FD_SYSCALL_CLOSE].name = close_targets[1];
228 + }
229 +}
230 +
231 +/**
232 + * Set hash tables
233 + *
234 + * Set the values for maps according the value given by kernel.
235 + *
236 + * @param obj is the main structure for bpf objects.
237 + */
238 +static void ebpf_fd_set_hash_tables(struct fd_bpf *obj)
239 +{
240 + fd_maps[NETDATA_FD_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_global);
241 + fd_maps[NETDATA_FD_PID_STATS].map_fd = bpf_map__fd(obj->maps.tbl_fd_pid);
242 + fd_maps[NETDATA_FD_CONTROLLER].map_fd = bpf_map__fd(obj->maps.fd_ctrl);
243 +}
244 +
245 +/**
246 + * Adjust Map Size
247 + *
248 + * Resize maps according input from users.
249 + *
250 + * @param obj is the main structure for bpf objects.
251 + * @param em structure with configuration
252 + */
253 +static void ebpf_fd_adjust_map_size(struct fd_bpf *obj, ebpf_module_t *em)
254 +{
255 + ebpf_update_map_size(obj->maps.tbl_fd_pid, &fd_maps[NETDATA_FD_PID_STATS],
256 + em, bpf_map__name(obj->maps.tbl_fd_pid));
257 +}
258 +
259 +/**
260 + * Disable Release Task
261 + *
262 + * Disable release task when apps is not enabled.
263 + *
264 + * @param obj is the main structure for bpf objects.
265 + */
266 +static void ebpf_fd_disable_release_task(struct fd_bpf *obj)
267 +{
268 + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_kprobe, false);
269 + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
270 +}
271 +
272 +/**
273 + * Load and attach
274 + *
275 + * Load and attach the eBPF code in kernel.
276 + *
277 + * @param obj is the main structure for bpf objects.
278 + * @param em structure with configuration
279 + *
280 + * @return it returns 0 on succes and -1 otherwise
281 + */
282 +static inline int ebpf_fd_load_and_attach(struct fd_bpf *obj, ebpf_module_t *em)
283 +{
284 + netdata_ebpf_targets_t *mt = em->targets;
285 + netdata_ebpf_program_loaded_t test = mt[NETDATA_FD_SYSCALL_OPEN].mode;
286 +
287 + ebpf_fd_set_target_values();
288 + if (test == EBPF_LOAD_TRAMPOLINE) {
289 + ebpf_fd_disable_probes(obj);
290 + ebpf_disable_specific_trampoline(obj);
291 +
292 + ebpf_set_trampoline_target(obj);
293 + // TODO: Remove this in next PR, because this specific trampoline has an error.
294 + bpf_program__set_autoload(obj->progs.netdata_release_task_fd_fentry, false);
295 + } else {
296 + ebpf_disable_trampoline(obj);
297 + ebpf_disable_specific_probes(obj);
298 + }
299 +
300 + ebpf_fd_adjust_map_size(obj, em);
301 +
302 + if (!em->apps_charts && !em->cgroup_charts)
303 + ebpf_fd_disable_release_task(obj);
304 +
305 + int ret = fd_bpf__load(obj);
306 + if (ret) {
307 + return ret;
308 + }
309 +
310 + ret = (test == EBPF_LOAD_TRAMPOLINE) ? fd_bpf__attach(obj) : ebpf_fd_attach_probe(obj);
311 + if (!ret) {
312 + ebpf_fd_set_hash_tables(obj);
313 +
314 + ebpf_update_controller(fd_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
315 + }
316 +
317 + return ret;
318 +}
319 +#endif
320 +
321 /*****************************************************************
322 *
323 * FUNCTIONS TO CLOSE THE THREAD
@@ -78,6 +358,11 @@ static void ebpf_fd_cleanup(void *ptr)
358 freez(fd_values);
359 freez(fd_vector);
360
361 +#ifdef LIBBPF_MAJOR_VERSION
362 + if (bpf_obj)
363 + fd_bpf__destroy(bpf_obj);
364 +#endif
365 +
366 fd_thread.enabled = NETDATA_MAIN_THREAD_EXITED;
367 em->enabled = NETDATA_MAIN_THREAD_EXITED;
368 }
@@ -810,6 +1095,40 @@ static void ebpf_fd_allocate_global_vectors(int apps)
1095 fd_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
1096 }
1097
1098 +/*
1099 + * Load BPF
1100 + *
1101 + * Load BPF files.
1102 + *
1103 + * @param em the structure with configuration
1104 + */
1105 +static int ebpf_fd_load_bpf(ebpf_module_t *em)
1106 +{
1107 + int ret = 0;
1108 + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_FD_SYSCALL_OPEN].mode);
1109 + if (em->load & EBPF_LOAD_LEGACY) {
1110 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1111 + if (!em->probe_links) {
1112 + em->enabled = CONFIG_BOOLEAN_NO;
1113 + ret = -1;
1114 + }
1115 + }
1116 +#ifdef LIBBPF_MAJOR_VERSION
1117 + else {
1118 + bpf_obj = fd_bpf__open();
1119 + if (!bpf_obj)
1120 + ret = -1;
1121 + else
1122 + ret = ebpf_fd_load_and_attach(bpf_obj, em);
1123 + }
1124 +#endif
1125 +
1126 + if (ret)
1127 + error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
1128 +
1129 + return ret;
1130 +}
1131 +
1132 /**
1133 * Directory Cache thread
1134 *
@@ -829,13 +1148,13 @@ void *ebpf_fd_thread(void *ptr)
1148 if (!em->enabled)
1149 goto endfd;
1150
832 - ebpf_fd_allocate_global_vectors(em->apps_charts);
833 -
834 - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
835 - if (!em->probe_links) {
836 - em->enabled = CONFIG_BOOLEAN_NO;
1151 +#ifdef LIBBPF_MAJOR_VERSION
1152 + ebpf_adjust_thread_load(em, default_btf);
1153 +#endif
1154 + if (ebpf_fd_load_bpf(em))
1155 goto endfd;
838 - }
1156 +
1157 + ebpf_fd_allocate_global_vectors(em->apps_charts);
1158
1159 int algorithms[NETDATA_FD_SYSCALL_END] = {
1160 NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX
collectors/ebpf.plugin/ebpf_fd.h
+1
@@ -79,6 +79,7 @@ extern void *ebpf_fd_thread(void *ptr);
79 extern void ebpf_fd_create_apps_charts(struct ebpf_module *em, void *ptr);
80 extern struct config fd_config;
81 extern netdata_fd_stat_t **fd_pid;
82 +extern netdata_ebpf_targets_t fd_targets[];
83
84 #endif /* NETDATA_EBPF_FD_H */
85
collectors/ebpf.plugin/ebpf_mount.c
+1 -1
@@ -435,7 +435,7 @@ static void ebpf_create_mount_charts(int update_every)
435 static int ebpf_mount_load_bpf(ebpf_module_t *em)
436 {
437 int ret = 0;
438 - if (em->load == EBPF_LOAD_LEGACY) {
438 + if (em->load & EBPF_LOAD_LEGACY) {
439 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
440 if (!em->probe_links) {
441 em->enabled = CONFIG_BOOLEAN_NO;
collectors/ebpf.plugin/ebpf_shm.c
+46 -1
@@ -83,6 +83,7 @@ static void ebpf_disable_probe(struct shm_bpf *obj)
83 bpf_program__set_autoload(obj->progs.netdata_shmat_probe, false);
84 bpf_program__set_autoload(obj->progs.netdata_shmdt_probe, false);
85 bpf_program__set_autoload(obj->progs.netdata_shmctl_probe, false);
86 + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false);
87 }
88
89 /*
@@ -98,6 +99,7 @@ static void ebpf_disable_trampoline(struct shm_bpf *obj)
99 bpf_program__set_autoload(obj->progs.netdata_shmat_fentry, false);
100 bpf_program__set_autoload(obj->progs.netdata_shmdt_fentry, false);
101 bpf_program__set_autoload(obj->progs.netdata_shmctl_fentry, false);
102 + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false);
103 }
104
105 /**
@@ -130,6 +132,9 @@ static void ebpf_set_trampoline_target(struct shm_bpf *obj)
132 shm_targets[NETDATA_KEY_SHMCTL_CALL].name, running_on_kernel);
133 bpf_program__set_attach_target(obj->progs.netdata_shmctl_fentry, 0,
134 syscall);
135 +
136 + bpf_program__set_attach_target(obj->progs.netdata_shm_release_task_fentry, 0,
137 + EBPF_COMMON_FNCT_CLEAN_UP);
138 }
139
140 /**
@@ -177,6 +182,13 @@ static int ebpf_shm_attach_probe(struct shm_bpf *obj)
182 if (ret)
183 return -1;
184
185 + obj->links.netdata_shm_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_shm_release_task_probe,
186 + false, EBPF_COMMON_FNCT_CLEAN_UP);
187 + ret = (int)libbpf_get_error(obj->links.netdata_shm_release_task_probe);
188 + if (ret)
189 + return -1;
190 +
191 +
192 return 0;
193 }
194
@@ -192,6 +204,33 @@ static void ebpf_shm_set_hash_tables(struct shm_bpf *obj)
204 shm_maps[NETDATA_SHM_GLOBAL_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_shm);
205 }
206
207 +/**
208 + * Disable Release Task
209 + *
210 + * Disable release task when apps is not enabled.
211 + *
212 + * @param obj is the main structure for bpf objects.
213 + */
214 +static void ebpf_shm_disable_release_task(struct shm_bpf *obj)
215 +{
216 + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_probe, false);
217 + bpf_program__set_autoload(obj->progs.netdata_shm_release_task_fentry, false);
218 +}
219 +
220 +/**
221 + * Adjust Map Size
222 + *
223 + * Resize maps according input from users.
224 + *
225 + * @param obj is the main structure for bpf objects.
226 + * @param em structure with configuration
227 + */
228 +static void ebpf_shm_adjust_map_size(struct shm_bpf *obj, ebpf_module_t *em)
229 +{
230 + ebpf_update_map_size(obj->maps.tbl_pid_shm, &shm_maps[NETDATA_PID_SHM_TABLE],
231 + em, bpf_map__name(obj->maps.tbl_pid_shm));
232 +}
233 +
234 /**
235 * Load and attach
236 *
@@ -221,6 +260,10 @@ static inline int ebpf_shm_load_and_attach(struct shm_bpf *obj, ebpf_module_t *e
260 ebpf_disable_trampoline(obj);
261 }
262
263 + ebpf_shm_adjust_map_size(obj, em);
264 + if (!em->apps_charts && !em->cgroup_charts)
265 + ebpf_shm_disable_release_task(obj);
266 +
267 int ret = shm_bpf__load(obj);
268 if (!ret) {
269 if (test != EBPF_LOAD_PROBE && test != EBPF_LOAD_RETPROBE)
@@ -1008,7 +1051,9 @@ static void ebpf_create_shm_charts(int update_every)
1051 static int ebpf_shm_load_bpf(ebpf_module_t *em)
1052 {
1053 int ret = 0;
1011 - if (em->load == EBPF_LOAD_LEGACY) {
1054 +
1055 + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SHMGET_CALL].mode);
1056 + if (em->load & EBPF_LOAD_LEGACY) {
1057 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1058 if (!em->probe_links) {
1059 em->enabled = CONFIG_BOOLEAN_NO;
collectors/ebpf.plugin/ebpf_socket.c
+1 -1
@@ -3875,7 +3875,7 @@ static int ebpf_socket_load_bpf(ebpf_module_t *em)
3875 {
3876 int ret = 0;
3877
3878 - if (em->load == EBPF_LOAD_LEGACY) {
3878 + if (em->load & EBPF_LOAD_LEGACY) {
3879 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
3880 if (!em->probe_links) {
3881 ret = -1;
collectors/ebpf.plugin/ebpf_swap.c
+31 -3
@@ -71,6 +71,7 @@ static void ebpf_swap_disable_trampoline(struct swap_bpf *obj)
71 {
72 bpf_program__set_autoload(obj->progs.netdata_swap_readpage_fentry, false);
73 bpf_program__set_autoload(obj->progs.netdata_swap_writepage_fentry, false);
74 + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
75 }
76
77 /**
@@ -87,6 +88,9 @@ static void ebpf_swap_set_trampoline_target(struct swap_bpf *obj)
88
89 bpf_program__set_attach_target(obj->progs.netdata_swap_writepage_fentry, 0,
90 swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
91 +
92 + bpf_program__set_attach_target(obj->progs.netdata_release_task_fentry, 0,
93 + EBPF_COMMON_FNCT_CLEAN_UP);
94 }
95
96 /**
@@ -114,6 +118,13 @@ static int ebpf_swap_attach_kprobe(struct swap_bpf *obj)
118 if (ret)
119 return -1;
120
121 + obj->links.netdata_release_task_probe = bpf_program__attach_kprobe(obj->progs.netdata_release_task_probe,
122 + false,
123 + EBPF_COMMON_FNCT_CLEAN_UP);
124 + ret = libbpf_get_error(obj->links.netdata_swap_writepage_probe);
125 + if (ret)
126 + return -1;
127 +
128 return 0;
129 }
130
@@ -145,6 +156,19 @@ static void ebpf_swap_adjust_map_size(struct swap_bpf *obj, ebpf_module_t *em)
156 em, bpf_map__name(obj->maps.tbl_pid_swap));
157 }
158
159 +/**
160 + * Disable Release Task
161 + *
162 + * Disable release task when apps is not enabled.
163 + *
164 + * @param obj is the main structure for bpf objects.
165 + */
166 +static void ebpf_swap_disable_release_task(struct swap_bpf *obj)
167 +{
168 + bpf_program__set_autoload(obj->progs.netdata_release_task_fentry, false);
169 + bpf_program__set_autoload(obj->progs.netdata_release_task_probe, false);
170 +}
171 +
172 /**
173 * Load and attach
174 *
@@ -168,13 +192,16 @@ static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t
192 ebpf_swap_disable_trampoline(obj);
193 }
194
195 + ebpf_swap_adjust_map_size(obj, em);
196 +
197 + if (!em->apps_charts && !em->cgroup_charts)
198 + ebpf_swap_disable_release_task(obj);
199 +
200 int ret = swap_bpf__load(obj);
201 if (ret) {
202 return ret;
203 }
204
176 - ebpf_swap_adjust_map_size(obj, em);
177 -
205 ret = (test == EBPF_LOAD_TRAMPOLINE) ? swap_bpf__attach(obj) : ebpf_swap_attach_kprobe(obj);
206 if (!ret) {
207 ebpf_swap_set_hash_tables(obj);
@@ -812,7 +839,8 @@ static void ebpf_create_swap_charts(int update_every)
839 static int ebpf_swap_load_bpf(ebpf_module_t *em)
840 {
841 int ret = 0;
815 - if (em->load == EBPF_LOAD_LEGACY) {
842 + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_KEY_SWAP_READPAGE_CALL].mode);
843 + if (em->load & EBPF_LOAD_LEGACY) {
844 em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
845 if (!em->probe_links) {
846 ret = -1;
collectors/ebpf.plugin/ebpf_sync.c
+1 -1
@@ -291,7 +291,7 @@ static int ebpf_sync_initialize_syscall(ebpf_module_t *em)
291 for (i = 0; local_syscalls[i].syscall; i++) {
292 ebpf_sync_syscalls_t *w = &local_syscalls[i];
293 if (w->enabled) {
294 - if (em->load == EBPF_LOAD_LEGACY) {
294 + if (em->load & EBPF_LOAD_LEGACY) {
295 if (ebpf_sync_load_legacy(w, em))
296 errors++;
297
collectors/ebpf.plugin/ebpf_vfs.c
+387 -2
@@ -39,6 +39,354 @@ struct netdata_static_thread vfs_threads = {"VFS KERNEL",
39 NULL, NULL};
40 static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING;
41
42 +netdata_ebpf_targets_t vfs_targets[] = { {.name = "vfs_write", .mode = EBPF_LOAD_TRAMPOLINE},
43 + {.name = "vfs_writev", .mode = EBPF_LOAD_TRAMPOLINE},
44 + {.name = "vfs_read", .mode = EBPF_LOAD_TRAMPOLINE},
45 + {.name = "vfs_readv", .mode = EBPF_LOAD_TRAMPOLINE},
46 + {.name = "vfs_unlink", .mode = EBPF_LOAD_TRAMPOLINE},
47 + {.name = "vfs_fsync", .mode = EBPF_LOAD_TRAMPOLINE},
48 + {.name = "vfs_open", .mode = EBPF_LOAD_TRAMPOLINE},
49 + {.name = "vfs_create", .mode = EBPF_LOAD_TRAMPOLINE},
50 + {.name = "release_task", .mode = EBPF_LOAD_TRAMPOLINE},
51 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
52 +
53 +#ifdef LIBBPF_MAJOR_VERSION
54 +#include "includes/vfs.skel.h" // BTF code
55 +
56 +static struct vfs_bpf *bpf_obj = NULL;
57 +
58 +/**
59 + * Disable probe
60 + *
61 + * Disable all probes to use exclusively another method.
62 + *
63 + * @param obj is the main structure for bpf objects
64 + */
65 +static void ebpf_vfs_disable_probes(struct vfs_bpf *obj)
66 +{
67 + bpf_program__set_autoload(obj->progs.netdata_vfs_write_kprobe, false);
68 + bpf_program__set_autoload(obj->progs.netdata_vfs_write_kretprobe, false);
69 + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kprobe, false);
70 + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_kretprobe, false);
71 + bpf_program__set_autoload(obj->progs.netdata_vfs_read_kprobe, false);
72 + bpf_program__set_autoload(obj->progs.netdata_vfs_read_kretprobe, false);
73 + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kprobe, false);
74 + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_kretprobe, false);
75 + bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kprobe, false);
76 + bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_kretprobe, false);
77 + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kprobe, false);
78 + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_kretprobe, false);
79 + bpf_program__set_autoload(obj->progs.netdata_vfs_open_kprobe, false);
80 + bpf_program__set_autoload(obj->progs.netdata_vfs_open_kretprobe, false);
81 + bpf_program__set_autoload(obj->progs.netdata_vfs_create_kprobe, false);
82 + bpf_program__set_autoload(obj->progs.netdata_vfs_create_kretprobe, false);
83 + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_kprobe, false);
84 +}
85 +
86 +/*
87 + * Disable trampoline
88 + *
89 + * Disable all trampoline to use exclusively another method.
90 + *
91 + * @param obj is the main structure for bpf objects.
92 + */
93 +static void ebpf_vfs_disable_trampoline(struct vfs_bpf *obj)
94 +{
95 + bpf_program__set_autoload(obj->progs.netdata_vfs_write_fentry, false);
96 + bpf_program__set_autoload(obj->progs.netdata_vfs_write_fexit, false);
97 + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fentry, false);
98 + bpf_program__set_autoload(obj->progs.netdata_vfs_writev_fexit, false);
99 + bpf_program__set_autoload(obj->progs.netdata_vfs_read_fentry, false);
100 + bpf_program__set_autoload(obj->progs.netdata_vfs_read_fexit, false);
101 + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fentry, false);
102 + bpf_program__set_autoload(obj->progs.netdata_vfs_readv_fexit, false);
103 + bpf_program__set_autoload(obj->progs.netdata_vfs_unlink_fentry, false);
104 + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fentry, false);
105 + bpf_program__set_autoload(obj->progs.netdata_vfs_fsync_fexit, false);
106 + bpf_program__set_autoload(obj->progs.netdata_vfs_open_fentry, false);
107 + bpf_program__set_autoload(obj->progs.netdata_vfs_open_fexit, false);
108 + bpf_program__set_autoload(obj->progs.netdata_vfs_create_fentry, false);
109 + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_fentry, false);
110 +}
111 +
112 +/**
113 + * Set trampoline target
114 + *
115 + * Set the targets we will monitor.
116 + *
117 + * @param obj is the main structure for bpf objects.
118 + */
119 +static void ebpf_vfs_set_trampoline_target(struct vfs_bpf *obj)
120 +{
121 + bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
122 +
123 + bpf_program__set_attach_target(obj->progs.netdata_vfs_write_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
124 +
125 + bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
126 +
127 + bpf_program__set_attach_target(obj->progs.netdata_vfs_writev_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
128 +
129 + bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name);
130 +
131 + bpf_program__set_attach_target(obj->progs.netdata_vfs_read_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READ].name);
132 +
133 + bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name);
134 +
135 + bpf_program__set_attach_target(obj->progs.netdata_vfs_readv_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_READV].name);
136 +
137 + bpf_program__set_attach_target(obj->progs.netdata_vfs_unlink_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
138 +
139 + bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
140 +
141 + bpf_program__set_attach_target(obj->progs.netdata_vfs_fsync_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
142 +
143 + bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
144 +
145 + bpf_program__set_attach_target(obj->progs.netdata_vfs_open_fexit, 0, vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
146 +
147 + bpf_program__set_attach_target(obj->progs.netdata_vfs_create_fentry, 0, vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
148 +
149 + bpf_program__set_attach_target(obj->progs.netdata_vfs_release_task_fentry, 0, EBPF_COMMON_FNCT_CLEAN_UP);
150 +}
151 +
152 +/**
153 + * Attach Probe
154 + *
155 + * Attach probes to target
156 + *
157 + * @param obj is the main structure for bpf objects.
158 + *
159 + * @return It returns 0 on success and -1 otherwise.
160 + */
161 +static int ebpf_vfs_attach_probe(struct vfs_bpf *obj)
162 +{
163 + obj->links.netdata_vfs_write_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_write_kprobe, false,
164 + vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
165 + int ret = libbpf_get_error(obj->links.netdata_vfs_write_kprobe);
166 + if (ret)
167 + return -1;
168 +
169 + obj->links.netdata_vfs_write_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_write_kretprobe, true,
170 + vfs_targets[NETDATA_EBPF_VFS_WRITE].name);
171 + ret = libbpf_get_error(obj->links.netdata_vfs_write_kretprobe);
172 + if (ret)
173 + return -1;
174 +
175 + obj->links.netdata_vfs_writev_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_writev_kprobe, false,
176 + vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
177 + ret = libbpf_get_error(obj->links.netdata_vfs_writev_kprobe);
178 + if (ret)
179 + return -1;
180 +
181 + obj->links.netdata_vfs_writev_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_writev_kretprobe, true,
182 + vfs_targets[NETDATA_EBPF_VFS_WRITEV].name);
183 + ret = libbpf_get_error(obj->links.netdata_vfs_writev_kretprobe);
184 + if (ret)
185 + return -1;
186 +
187 + obj->links.netdata_vfs_read_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kprobe, false,
188 + vfs_targets[NETDATA_EBPF_VFS_READ].name);
189 + ret = libbpf_get_error(obj->links.netdata_vfs_read_kprobe);
190 + if (ret)
191 + return -1;
192 +
193 + obj->links.netdata_vfs_read_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_read_kretprobe, true,
194 + vfs_targets[NETDATA_EBPF_VFS_READ].name);
195 + ret = libbpf_get_error(obj->links.netdata_vfs_read_kretprobe);
196 + if (ret)
197 + return -1;
198 +
199 + obj->links.netdata_vfs_readv_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_readv_kprobe, false,
200 + vfs_targets[NETDATA_EBPF_VFS_READV].name);
201 + ret = libbpf_get_error(obj->links.netdata_vfs_readv_kprobe);
202 + if (ret)
203 + return -1;
204 +
205 + obj->links.netdata_vfs_readv_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_readv_kretprobe, true,
206 + vfs_targets[NETDATA_EBPF_VFS_READV].name);
207 + ret = libbpf_get_error(obj->links.netdata_vfs_readv_kretprobe);
208 + if (ret)
209 + return -1;
210 +
211 + obj->links.netdata_vfs_unlink_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_unlink_kprobe, false,
212 + vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
213 + ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kprobe);
214 + if (ret)
215 + return -1;
216 +
217 + obj->links.netdata_vfs_unlink_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_unlink_kretprobe, true,
218 + vfs_targets[NETDATA_EBPF_VFS_UNLINK].name);
219 + ret = libbpf_get_error(obj->links.netdata_vfs_unlink_kretprobe);
220 + if (ret)
221 + return -1;
222 +
223 + obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kprobe, false,
224 + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
225 + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe);
226 + if (ret)
227 + return -1;
228 +
229 + obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kretprobe, true,
230 + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
231 + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe);
232 + if (ret)
233 + return -1;
234 +
235 + obj->links.netdata_vfs_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false,
236 + vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
237 + ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe);
238 + if (ret)
239 + return -1;
240 +
241 + obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kretprobe, true,
242 + vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
243 + ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe);
244 + if (ret)
245 + return -1;
246 +
247 + obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kprobe, false,
248 + vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
249 + ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe);
250 + if (ret)
251 + return -1;
252 +
253 + obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kretprobe, true,
254 + vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
255 + ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe);
256 + if (ret)
257 + return -1;
258 +
259 + obj->links.netdata_vfs_fsync_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kprobe, false,
260 + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
261 + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kprobe);
262 + if (ret)
263 + return -1;
264 +
265 + obj->links.netdata_vfs_fsync_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_fsync_kretprobe, true,
266 + vfs_targets[NETDATA_EBPF_VFS_FSYNC].name);
267 + ret = libbpf_get_error(obj->links.netdata_vfs_fsync_kretprobe);
268 + if (ret)
269 + return -1;
270 +
271 + obj->links.netdata_vfs_open_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kprobe, false,
272 + vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
273 + ret = libbpf_get_error(obj->links.netdata_vfs_open_kprobe);
274 + if (ret)
275 + return -1;
276 +
277 + obj->links.netdata_vfs_open_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_open_kretprobe, true,
278 + vfs_targets[NETDATA_EBPF_VFS_OPEN].name);
279 + ret = libbpf_get_error(obj->links.netdata_vfs_open_kretprobe);
280 + if (ret)
281 + return -1;
282 +
283 + obj->links.netdata_vfs_create_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kprobe, false,
284 + vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
285 + ret = libbpf_get_error(obj->links.netdata_vfs_create_kprobe);
286 + if (ret)
287 + return -1;
288 +
289 + obj->links.netdata_vfs_create_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_create_kretprobe, true,
290 + vfs_targets[NETDATA_EBPF_VFS_CREATE].name);
291 + ret = libbpf_get_error(obj->links.netdata_vfs_create_kretprobe);
292 + if (ret)
293 + return -1;
294 +
295 + obj->links.netdata_vfs_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_vfs_release_task_fentry,
296 + true,
297 + EBPF_COMMON_FNCT_CLEAN_UP);
298 + ret = libbpf_get_error(obj->links.netdata_vfs_release_task_kprobe);
299 + if (ret)
300 + return -1;
301 +
302 + return 0;
303 +}
304 +
305 +/**
306 + * Adjust Map Size
307 + *
308 + * Resize maps according input from users.
309 + *
310 + * @param obj is the main structure for bpf objects.
311 + * @param em structure with configuration
312 + */
313 +static void ebpf_vfs_adjust_map_size(struct vfs_bpf *obj, ebpf_module_t *em)
314 +{
315 + ebpf_update_map_size(obj->maps.tbl_vfs_pid, &vfs_maps[NETDATA_VFS_PID],
316 + em, bpf_map__name(obj->maps.tbl_vfs_pid));
317 +}
318 +
319 +/**
320 + * Set hash tables
321 + *
322 + * Set the values for maps according the value given by kernel.
323 + *
324 + * @param obj is the main structure for bpf objects.
325 + */
326 +static void ebpf_vfs_set_hash_tables(struct vfs_bpf *obj)
327 +{
328 + vfs_maps[NETDATA_VFS_ALL].map_fd = bpf_map__fd(obj->maps.tbl_vfs_stats);
329 + vfs_maps[NETDATA_VFS_PID].map_fd = bpf_map__fd(obj->maps.tbl_vfs_pid);
330 + vfs_maps[NETDATA_VFS_CTRL].map_fd = bpf_map__fd(obj->maps.vfs_ctrl);
331 +}
332 +
333 +/**
334 + * Disable Release Task
335 + *
336 + * Disable release task when apps is not enabled.
337 + *
338 + * @param obj is the main structure for bpf objects.
339 + */
340 +static void ebpf_vfs_disable_release_task(struct vfs_bpf *obj)
341 +{
342 + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_fentry, false);
343 + bpf_program__set_autoload(obj->progs.netdata_vfs_release_task_kprobe, false);
344 +}
345 +
346 +/**
347 + * Load and attach
348 + *
349 + * Load and attach the eBPF code in kernel.
350 + *
351 + * @param obj is the main structure for bpf objects.
352 + * @param em structure with configuration
353 + *
354 + * @return it returns 0 on succes and -1 otherwise
355 + */
356 +static inline int ebpf_vfs_load_and_attach(struct vfs_bpf *obj, ebpf_module_t *em)
357 +{
358 + netdata_ebpf_targets_t *mt = em->targets;
359 + netdata_ebpf_program_loaded_t test = mt[NETDATA_EBPF_VFS_WRITE].mode;
360 +
361 + if (test == EBPF_LOAD_TRAMPOLINE) {
362 + ebpf_vfs_disable_probes(obj);
363 +
364 + ebpf_vfs_set_trampoline_target(obj);
365 + } else {
366 + ebpf_vfs_disable_trampoline(obj);
367 + }
368 +
369 + ebpf_vfs_adjust_map_size(obj, em);
370 +
371 + if (!em->apps_charts && !em->cgroup_charts)
372 + ebpf_vfs_disable_release_task(obj);
373 +
374 + int ret = vfs_bpf__load(obj);
375 + if (ret) {
376 + return ret;
377 + }
378 +
379 + ret = (test == EBPF_LOAD_TRAMPOLINE) ? vfs_bpf__attach(obj) : ebpf_vfs_attach_probe(obj);
380 + if (!ret) {
381 + ebpf_vfs_set_hash_tables(obj);
382 +
383 + ebpf_update_controller(vfs_maps[NETDATA_VFS_CTRL].map_fd, em);
384 + }
385 +
386 + return ret;
387 +}
388 +#endif
389 +
390 /*****************************************************************
391 *
392 * FUNCTIONS TO CLOSE THE THREAD
@@ -77,6 +425,11 @@ static void ebpf_vfs_cleanup(void *ptr)
425 freez(vfs_vector);
426 freez(vfs_threads.thread);
427
428 +#ifdef LIBBPF_MAJOR_VERSION
429 + if (bpf_obj)
430 + vfs_bpf__destroy(bpf_obj);
431 +#endif
432 +
433 vfs_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
434 em->enabled = NETDATA_MAIN_THREAD_EXITED;
435 }
@@ -1543,6 +1896,36 @@ static void ebpf_vfs_allocate_global_vectors(int apps)
1896 *
1897 *****************************************************************/
1898
1899 +/*
1900 + * Load BPF
1901 + *
1902 + * Load BPF files.
1903 + *
1904 + * @param em the structure with configuration
1905 + */
1906 +static int ebpf_vfs_load_bpf(ebpf_module_t *em)
1907 +{
1908 + int ret = 0;
1909 + ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_EBPF_VFS_WRITE].mode);
1910 + if (em->load & EBPF_LOAD_LEGACY) {
1911 + em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1912 + if (!em->probe_links) {
1913 + ret = -1;
1914 + }
1915 + }
1916 +#ifdef LIBBPF_MAJOR_VERSION
1917 + else {
1918 + bpf_obj = vfs_bpf__open();
1919 + if (!bpf_obj)
1920 + ret = -1;
1921 + else
1922 + ret = ebpf_vfs_load_and_attach(bpf_obj, em);
1923 + }
1924 +#endif
1925 +
1926 + return ret;
1927 +}
1928 +
1929 /**
1930 * Process thread
1931 *
@@ -1566,8 +1949,10 @@ void *ebpf_vfs_thread(void *ptr)
1949 if (!em->enabled)
1950 goto endvfs;
1951
1569 - em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
1570 - if (!em->probe_links) {
1952 +#ifdef LIBBPF_MAJOR_VERSION
1953 + ebpf_adjust_thread_load(em, default_btf);
1954 +#endif
1955 + if (ebpf_vfs_load_bpf(em)) {
1956 em->enabled = CONFIG_BOOLEAN_NO;
1957 goto endvfs;
1958 }
collectors/ebpf.plugin/ebpf_vfs.h
+16 -1
@@ -149,13 +149,28 @@ enum vfs_counters {
149
150 enum netdata_vfs_tables {
151 NETDATA_VFS_PID,
152 - NETDATA_VFS_ALL
152 + NETDATA_VFS_ALL,
153 + NETDATA_VFS_CTRL
154 +};
155 +
156 +enum netdata_vfs_calls_name {
157 + NETDATA_EBPF_VFS_WRITE,
158 + NETDATA_EBPF_VFS_WRITEV,
159 + NETDATA_EBPF_VFS_READ,
160 + NETDATA_EBPF_VFS_READV,
161 + NETDATA_EBPF_VFS_UNLINK,
162 + NETDATA_EBPF_VFS_FSYNC,
163 + NETDATA_EBPF_VFS_OPEN,
164 + NETDATA_EBPF_VFS_CREATE,
165 +
166 + NETDATA_VFS_END_LIST
167 };
168
169 extern netdata_publish_vfs_t **vfs_pid;
170
171 extern void *ebpf_vfs_thread(void *ptr);
172 extern void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr);
173 +extern netdata_ebpf_targets_t vfs_targets[];
174
175 extern struct config vfs_config;
176
libnetdata/ebpf/ebpf.c
+68 -13
@@ -444,9 +444,9 @@ void ebpf_update_stats(ebpf_plugin_stats_t *report, ebpf_module_t *em)
444
445 // In theory the `else if` is useless, because when this function is called, the module should not stay in
446 // EBPF_LOAD_PLAY_DICE. We have this additional condition to detect errors from developers.
447 - if (em->load == EBPF_LOAD_LEGACY)
447 + if (em->load & EBPF_LOAD_LEGACY)
448 report->legacy++;
449 - else if (em->load == EBPF_LOAD_CORE)
449 + else if (em->load & EBPF_LOAD_CORE)
450 report->core++;
451
452 ebpf_stats_targets(report, em->targets);
@@ -826,9 +826,9 @@ netdata_ebpf_load_mode_t epbf_convert_string_to_load_mode(char *str)
826 */
827 static char *ebpf_convert_load_mode_to_string(netdata_ebpf_load_mode_t mode)
828 {
829 - if (mode == EBPF_LOAD_CORE)
829 + if (mode & EBPF_LOAD_CORE)
830 return EBPF_CFG_CORE_PROGRAM;
831 - else if (mode == EBPF_LOAD_LEGACY)
831 + else if (mode & EBPF_LOAD_LEGACY)
832 return EBPF_CFG_LEGACY_PROGRAM;
833
834 return EBPF_CFG_DEFAULT_PROGRAM;
@@ -850,7 +850,7 @@ static char *ebpf_convert_collect_pid_to_string(netdata_apps_level_t level)
850 else if (level == NETDATA_APPS_LEVEL_ALL)
851 return EBPF_CFG_PID_ALL;
852
853 - return EBPF_CFG_PID_ALL;
853 + return EBPF_CFG_PID_INTERNAL_USAGE;
854 }
855
856 /**
@@ -903,9 +903,11 @@ netdata_ebpf_program_loaded_t ebpf_convert_core_type(char *str, netdata_run_mode
903 void ebpf_adjust_thread_load(ebpf_module_t *mod, struct btf *file)
904 {
905 if (!file) {
906 - mod->load = EBPF_LOAD_LEGACY;
906 + mod->load &= ~EBPF_LOAD_CORE;
907 + mod->load |= EBPF_LOAD_LEGACY;
908 } else if (mod->load == EBPF_LOAD_PLAY_DICE && file) {
908 - mod->load = EBPF_LOAD_CORE;
909 + mod->load &= ~EBPF_LOAD_LEGACY;
910 + mod->load |= EBPF_LOAD_CORE;
911 }
912 }
913
@@ -1018,14 +1020,39 @@ static void ebpf_update_target_with_conf(ebpf_module_t *em, netdata_ebpf_program
1020 }
1021 }
1022
1023 +/**
1024 + * Select Load Mode
1025 + *
1026 + * Select the load mode according the given inputs.
1027 + *
1028 + * @param btf_file a pointer to the loaded btf file.
1029 + * @parma load current value.
1030 + *
1031 + * @return it returns the new load mode.
1032 + */
1033 +static netdata_ebpf_load_mode_t ebpf_select_load_mode(struct btf *btf_file, netdata_ebpf_load_mode_t load)
1034 +{
1035 +#ifdef LIBBPF_MAJOR_VERSION
1036 + if ((load & EBPF_LOAD_CORE) || (load & EBPF_LOAD_PLAY_DICE)) {
1037 + load = (!btf_file) ? EBPF_LOAD_LEGACY : EBPF_LOAD_CORE;
1038 + }
1039 +#else
1040 + load = EBPF_LOAD_LEGACY;
1041 +#endif
1042 +
1043 + return load;
1044 +}
1045 +
1046 /**
1047 * Update Module using config
1048 *
1049 * Update configuration for a specific thread.
1050 *
1051 * @param modules structure that will be updated
1052 + * @oaram origin specify the configuration file loaded
1053 + * @param btf_file a pointer to the loaded btf file.
1054 */
1028 -void ebpf_update_module_using_config(ebpf_module_t *modules)
1055 +void ebpf_update_module_using_config(ebpf_module_t *modules, netdata_ebpf_load_mode_t origin, struct btf *btf_file)
1056 {
1057 char default_value[EBPF_MAX_MODE_LENGTH + 1];
1058 ebpf_select_mode_string(default_value, EBPF_MAX_MODE_LENGTH, modules->mode);
@@ -1044,9 +1071,11 @@ void ebpf_update_module_using_config(ebpf_module_t *modules)
1071 modules->pid_map_size = (uint32_t)appconfig_get_number(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_PID_SIZE,
1072 modules->pid_map_size);
1073
1047 - value = ebpf_convert_load_mode_to_string(modules->load);
1074 + value = ebpf_convert_load_mode_to_string(modules->load & NETDATA_EBPF_LOAD_METHODS);
1075 value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_TYPE_FORMAT, value);
1049 - modules->load = epbf_convert_string_to_load_mode(value);
1076 + netdata_ebpf_load_mode_t load = epbf_convert_string_to_load_mode(value);
1077 + load = ebpf_select_load_mode(btf_file, load);
1078 + modules->load = origin | load;
1079
1080 value = appconfig_get(modules->cfg, EBPF_GLOBAL_SECTION, EBPF_CFG_CORE_ATTACH, EBPF_CFG_ATTACH_TRAMPOLINE);
1081 netdata_ebpf_program_loaded_t fill_lm = ebpf_convert_core_type(value, modules->mode);
@@ -1066,10 +1095,13 @@ void ebpf_update_module_using_config(ebpf_module_t *modules)
1095 * update the variables.
1096 *
1097 * @param em the module structure
1098 + * @param btf_file a pointer to the loaded btf file.
1099 */
1070 -void ebpf_update_module(ebpf_module_t *em)
1100 +void ebpf_update_module(ebpf_module_t *em, struct btf *btf_file)
1101 {
1102 char filename[FILENAME_MAX+1];
1103 + netdata_ebpf_load_mode_t origin;
1104 +
1105 ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_user_config_dir, em->config_file);
1106 if (!ebpf_load_config(em->cfg, filename)) {
1107 ebpf_mount_config_name(filename, FILENAME_MAX, ebpf_stock_config_dir, em->config_file);
@@ -1077,9 +1109,32 @@ void ebpf_update_module(ebpf_module_t *em)
1109 error("Cannot load the ebpf configuration file %s", em->config_file);
1110 return;
1111 }
1080 - }
1112 + // If user defined data globaly, we will have here EBPF_LOADED_FROM_USER, we need to consider this, to avoid
1113 + // forcing users to configure thread by thread.
1114 + origin = (!(em->load & NETDATA_EBPF_LOAD_SOURCE)) ? EBPF_LOADED_FROM_STOCK : em->load & NETDATA_EBPF_LOAD_SOURCE;
1115 + } else
1116 + origin = EBPF_LOADED_FROM_USER;
1117
1082 - ebpf_update_module_using_config(em);
1118 + ebpf_update_module_using_config(em, origin, btf_file);
1119 +}
1120 +
1121 +/**
1122 + * Adjust Apps Cgroup
1123 + *
1124 + * Apps and cgroup has internal cleanup that needs attaching tracers to release_task, to avoid overload the function
1125 + * we will enable this integration by default, if and only if, we are running with trampolines.
1126 + *
1127 + * @param em a poiter to the main thread structure.
1128 + * @param mode is the mode used with different
1129 + */
1130 +void ebpf_adjust_apps_cgroup(ebpf_module_t *em, netdata_ebpf_program_loaded_t mode)
1131 +{
1132 + if ((em->load & EBPF_LOADED_FROM_STOCK) &&
1133 + (em->apps_charts || em->cgroup_charts) &&
1134 + mode != EBPF_LOAD_TRAMPOLINE) {
1135 + em->apps_charts = NETDATA_EBPF_APPS_FLAG_NO;
1136 + em->cgroup_charts = 0;
1137 + }
1138 }
1139
1140 //----------------------------------------------------------------------------------------------------------------------
libnetdata/ebpf/ebpf.h
+10 -5
@@ -30,6 +30,7 @@
30 #define EBPF_CFG_PID_REAL_PARENT "real parent"
31 #define EBPF_CFG_PID_PARENT "parent"
32 #define EBPF_CFG_PID_ALL "all"
33 +#define EBPF_CFG_PID_INTERNAL_USAGE "not used"
34
35 #define EBPF_CFG_CORE_ATTACH "ebpf co-re tracing"
36 #define EBPF_CFG_ATTACH_TRAMPOLINE "trampoline"
@@ -201,11 +202,14 @@ typedef struct ebpf_specify_name {
202 } ebpf_specify_name_t;
203
204 typedef enum netdata_ebpf_load_mode {
204 - EBPF_LOAD_LEGACY, // Select legacy mode, this means we will load binaries
205 - EBPF_LOAD_CORE, // When CO-RE is used, it is necessary to use the souce code
206 -
207 - EBPF_LOAD_PLAY_DICE // Take a look on environment and choose the best option
205 + EBPF_LOAD_LEGACY = 1<<0, // Select legacy mode, this means we will load binaries
206 + EBPF_LOAD_CORE = 1<<1, // When CO-RE is used, it is necessary to use the souce code
207 + EBPF_LOAD_PLAY_DICE = 1<<2, // Take a look on environment and choose the best option
208 + EBPF_LOADED_FROM_STOCK = 1<<3, // Configuration loaded from Stock file
209 + EBPF_LOADED_FROM_USER = 1<<4 // Configuration loaded from user
210 } netdata_ebpf_load_mode_t;
211 +#define NETDATA_EBPF_LOAD_METHODS (EBPF_LOAD_LEGACY|EBPF_LOAD_CORE|EBPF_LOAD_PLAY_DICE)
212 +#define NETDATA_EBPF_LOAD_SOURCE (EBPF_LOADED_FROM_STOCK|EBPF_LOADED_FROM_USER)
213
214 typedef enum netdata_ebpf_program_loaded {
215 EBPF_LOAD_PROBE, // Attach probes on targets
@@ -274,8 +278,9 @@ extern struct bpf_link **ebpf_load_program(char *plugins_dir, ebpf_module_t *em,
278
279 extern void ebpf_mount_config_name(char *filename, size_t length, char *path, const char *config);
280 extern int ebpf_load_config(struct config *config, char *filename);
277 -extern void ebpf_update_module(ebpf_module_t *em);
281 +extern void ebpf_update_module(ebpf_module_t *em, struct btf *btf_file);
282 extern void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em);
283 +extern void ebpf_adjust_apps_cgroup(ebpf_module_t *em, netdata_ebpf_program_loaded_t mode);
284 extern char *ebpf_find_symbol(char *search);
285 extern void ebpf_load_addresses(ebpf_addresses_t *fa, int fd);
286 extern void ebpf_fill_algorithms(int *algorithms, size_t length, int algorithm);
packaging/ebpf-co-re.checksums
+1 -1
@@ -1 +1 @@
1 -26e6244242bb744adf2ff8640e267d54931d28fdd8150a967f9acedbd569a47b netdata-ebpf-co-re-glibc-v0.9.4.1.tar.xz
1 +ab36f617b045d4740536769f84b7a527714431c02e80e15aa7fa2fe84c64d0cc netdata-ebpf-co-re-glibc-v0.9.5.tar.xz
packaging/ebpf-co-re.version
+1 -1
@@ -1 +1 @@
1 -v0.9.4.1
1 +v0.9.5
packaging/ebpf.checksums
+3 -3
@@ -1,3 +1,3 @@
1 -49a4ab9eae3c519e6869ea414e63ea765d40ea41fb4c2cc8802a96a94a47ff74 ./netdata-kernel-collector-glibc-v0.9.4.tar.xz
2 -2284eb53ff61de823800585f993f13707d24ccd4d335b8bb39bbbd43b47cde75 ./netdata-kernel-collector-musl-v0.9.4.tar.xz
3 -46663fab8e5a279e8f2d4b76400f0e27552929ef6dee92a3ed81608250a1198b ./netdata-kernel-collector-static-v0.9.4.tar.xz
1 +e7408cbfe77d570edea4c562efd631e914827a5d5ad51dab0638d7aa3e999a99 ./netdata-kernel-collector-glibc-v0.9.5.tar.xz
2 +8a0f5117d71d3b1975ad31fe51c1e2a887d66e676aa53cd5939d22192cb581a6 ./netdata-kernel-collector-musl-v0.9.5.tar.xz
3 +472e2b6cb473cea69efd1645a35589904db4eddc162a372833bde156b53ec44b ./netdata-kernel-collector-static-v0.9.5.tar.xz
packaging/ebpf.version
+1 -1
@@ -1 +1 @@
1 -v0.9.4
1 +v0.9.5