@cryptotaxi247 / netdata-1 / commits / 2244973a9

Memory CO-RE (#12684)

thiagoftsm committed Apr 26, 2022 at 11:40 UTC 2244973a9b587c499b5f8b5f241ba08a39b5327b
12 files changed +765 -27
collectors/ebpf.plugin/ebpf.c
+3 -3
@@ -60,7 +60,7 @@ ebpf_module_t ebpf_modules[] = {
60 .config_file = NETDATA_CACHESTAT_CONFIG_FILE,
61 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18|
62 NETDATA_V5_4 | NETDATA_V5_15 | NETDATA_V5_16,
63 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
63 + .load = EBPF_LOAD_LEGACY, .targets = cachestat_targets},
64 { .thread_name = "sync", .config_name = "sync", .enabled = 0, .start_routine = ebpf_sync_thread,
65 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
66 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0, .apps_routine = NULL, .maps = NULL,
@@ -76,7 +76,7 @@ ebpf_module_t ebpf_modules[] = {
76 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &dcstat_config,
77 .config_file = NETDATA_DIRECTORY_DCSTAT_CONFIG_FILE,
78 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
79 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
79 + .load = EBPF_LOAD_LEGACY, .targets = dc_targets},
80 { .thread_name = "swap", .config_name = "swap", .enabled = 0, .start_routine = ebpf_swap_thread,
81 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
82 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
@@ -84,7 +84,7 @@ ebpf_module_t ebpf_modules[] = {
84 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &swap_config,
85 .config_file = NETDATA_DIRECTORY_SWAP_CONFIG_FILE,
86 .kernels = NETDATA_V3_10 | NETDATA_V4_14 | NETDATA_V4_16 | NETDATA_V4_18 | NETDATA_V5_4,
87 - .load = EBPF_LOAD_LEGACY, .targets = NULL},
87 + .load = EBPF_LOAD_LEGACY, .targets = swap_targets},
88 { .thread_name = "vfs", .config_name = "vfs", .enabled = 0, .start_routine = ebpf_vfs_thread,
89 .update_every = EBPF_DEFAULT_UPDATE_EVERY, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO,
90 .cgroup_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY, .optional = 0,
collectors/ebpf.plugin/ebpf.d/cachestat.conf
+12 -1
@@ -10,10 +10,21 @@
10 #
11 # The `pid table size` defines the maximum number of PIDs stored inside the application hash table.
12 #
13 +# The `ebpf type format` option accepts the following values :
14 +# `auto` : The eBPF collector will investigate hardware and select between the two next options.
15 +# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload.
16 +# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms.
17 +#
18 +# The `ebpf co-re tracing` option accepts the following values:
19 +# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
20 +# `probe` : This is the same as legacy code.
21 +#
22 # Uncomment lines to define specific options for thread.
14 -#[global]
23 +[global]
24 # ebpf load mode = entry
25 # apps = yes
26 # cgroups = no
27 # update every = 10
28 # pid table size = 32768
29 + ebpf type format = auto
30 + ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.d/dcstat.conf
+12 -1
@@ -8,10 +8,21 @@
8 # If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 # the setting `apps` and `cgroups` to 'no'.
10 #
11 +# The `ebpf type format` option accepts the following values :
12 +# `auto` : The eBPF collector will investigate hardware and select between the two next options.
13 +# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload.
14 +# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms.
15 +#
16 +# The `ebpf co-re tracing` option accepts the following values:
17 +# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
18 +# `probe` : This is the same as legacy code.
19 +#
20 # Uncomment lines to define specific options for thread.
12 -#[global]
21 +[global]
22 # ebpf load mode = entry
23 # apps = yes
24 # cgroups = no
25 # update every = 10
26 # pid table size = 32768
27 + ebpf type format = auto
28 + ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf.d/swap.conf
+12 -1
@@ -8,10 +8,21 @@
8 # If you want to disable the integration with `apps.plugin` or `cgroups.plugin` along with the above charts, change
9 # the setting `apps` and `cgroups` to 'no'.
10 #
11 +# The `ebpf type format` option accepts the following values :
12 +# `auto` : The eBPF collector will investigate hardware and select between the two next options.
13 +# `legacy`: The eBPF collector will load the legacy code. Note: This has a bigger overload.
14 +# `co-re` : The eBPF collector will use latest tracing method. Note: This is not available on all platforms.
15 +#
16 +# The `ebpf co-re tracing` option accepts the following values:
17 +# `trampoline`: This is the default mode used by the eBPF collector, due the small overhead added to host.
18 +# `probe` : This is the same as legacy code.
19 +#
20 # Uncomment lines to define specific options for thread.
12 -#[global]
21 +[global]
22 # ebpf load mode = entry
23 # apps = yes
24 # cgroups = no
25 # update every = 10
26 # pid table size = 32768
27 + ebpf type format = auto
28 + ebpf co-re tracing = trampoline
collectors/ebpf.plugin/ebpf_cachestat.c
+302 -7
@@ -45,6 +45,248 @@ struct config cachestat_config = { .first_section = NULL,
45 .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
46 .rwlock = AVL_LOCK_INITIALIZER } };
47
48 +netdata_ebpf_targets_t cachestat_targets[] = { {.name = "add_to_page_cache_lru", .mode = EBPF_LOAD_TRAMPOLINE},
49 + {.name = "mark_page_accessed", .mode = EBPF_LOAD_TRAMPOLINE},
50 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE},
51 + {.name = "mark_buffer_dirty", .mode = EBPF_LOAD_TRAMPOLINE},
52 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
53 +
54 +#ifdef LIBBPF_MAJOR_VERSION
55 +#include "includes/cachestat.skel.h" // BTF code
56 +
57 +static struct cachestat_bpf *bpf_obj = NULL;
58 +
59 +/**
60 + * Disable probe
61 + *
62 + * Disable all probes to use exclusively another method.
63 + *
64 + * @param obj is the main structure for bpf objects
65 + */
66 +static void ebpf_cachestat_disable_probe(struct cachestat_bpf *obj)
67 +{
68 + bpf_program__set_autoload(obj->progs.netdata_add_to_page_cache_lru_kprobe, false);
69 + bpf_program__set_autoload(obj->progs.netdata_mark_page_accessed_kprobe, false);
70 + bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
71 + bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
72 + bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
73 + bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_kprobe, false);
74 +}
75 +
76 +/*
77 + * Disable specific probe
78 + *
79 + * Disable probes according the kernel version
80 + *
81 + * @param obj is the main structure for bpf objects
82 + */
83 +static void ebpf_cachestat_disable_specific_probe(struct cachestat_bpf *obj)
84 +{
85 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
86 + bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
87 + bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
88 + } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
89 + bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
90 + bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_kprobe, false);
91 + } else {
92 + bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_kprobe, false);
93 + bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_kprobe, false);
94 + }
95 +}
96 +
97 +/*
98 + * Disable trampoline
99 + *
100 + * Disable all trampoline to use exclusively another method.
101 + *
102 + * @param obj is the main structure for bpf objects.
103 + */
104 +static void ebpf_cachestat_disable_trampoline(struct cachestat_bpf *obj)
105 +{
106 + bpf_program__set_autoload(obj->progs.netdata_add_to_page_cache_lru_fentry, false);
107 + bpf_program__set_autoload(obj->progs.netdata_mark_page_accessed_fentry, false);
108 + bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
109 + bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
110 + bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
111 + bpf_program__set_autoload(obj->progs.netdata_mark_buffer_dirty_fentry, false);
112 +}
113 +
114 +/*
115 + * Disable specific trampoline
116 + *
117 + * Disable trampoline according to kernel version.
118 + *
119 + * @param obj is the main structure for bpf objects.
120 + */
121 +static void ebpf_cachestat_disable_specific_trampoline(struct cachestat_bpf *obj)
122 +{
123 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
124 + bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
125 + bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
126 + } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
127 + bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
128 + bpf_program__set_autoload(obj->progs.netdata_account_page_dirtied_fentry, false);
129 + } else {
130 + bpf_program__set_autoload(obj->progs.netdata_folio_mark_dirty_fentry, false);
131 + bpf_program__set_autoload(obj->progs.netdata_set_page_dirty_fentry, false);
132 + }
133 +}
134 +
135 +/**
136 + * Set trampoline target
137 + *
138 + * Set the targets we will monitor.
139 + *
140 + * @param obj is the main structure for bpf objects.
141 + */
142 +static inline void netdata_set_trampoline_target(struct cachestat_bpf *obj)
143 +{
144 + bpf_program__set_attach_target(obj->progs.netdata_add_to_page_cache_lru_fentry, 0,
145 + cachestat_targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].name);
146 +
147 + bpf_program__set_attach_target(obj->progs.netdata_mark_page_accessed_fentry, 0,
148 + cachestat_targets[NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED].name);
149 +
150 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
151 + bpf_program__set_attach_target(obj->progs.netdata_folio_mark_dirty_fentry, 0,
152 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
153 + } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
154 + bpf_program__set_attach_target(obj->progs.netdata_set_page_dirty_fentry, 0,
155 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
156 + } else {
157 + bpf_program__set_attach_target(obj->progs.netdata_account_page_dirtied_fentry, 0,
158 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
159 + }
160 +
161 + bpf_program__set_attach_target(obj->progs.netdata_mark_buffer_dirty_fentry, 0,
162 + cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name);
163 +}
164 +
165 +/**
166 + * Mount Attach Probe
167 + *
168 + * Attach probes to target
169 + *
170 + * @param obj is the main structure for bpf objects.
171 + *
172 + * @return It returns 0 on success and -1 otherwise.
173 + */
174 +static int ebpf_cachestat_attach_probe(struct cachestat_bpf *obj)
175 +{
176 + obj->links.netdata_add_to_page_cache_lru_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_add_to_page_cache_lru_kprobe,
177 + false,
178 + cachestat_targets[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].name);
179 + int ret = libbpf_get_error(obj->links.netdata_add_to_page_cache_lru_kprobe);
180 + if (ret)
181 + return -1;
182 +
183 + obj->links.netdata_mark_page_accessed_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_mark_page_accessed_kprobe,
184 + false,
185 + cachestat_targets[NETDATA_KEY_CALLS_MARK_PAGE_ACCESSED].name);
186 + ret = libbpf_get_error(obj->links.netdata_mark_page_accessed_kprobe);
187 + if (ret)
188 + return -1;
189 +
190 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16) {
191 + obj->links.netdata_folio_mark_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_folio_mark_dirty_kprobe,
192 + false,
193 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
194 + ret = libbpf_get_error(obj->links.netdata_folio_mark_dirty_kprobe);
195 + } else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15) {
196 + obj->links.netdata_set_page_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_set_page_dirty_kprobe,
197 + false,
198 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
199 + ret = libbpf_get_error(obj->links.netdata_set_page_dirty_kprobe);
200 + } else {
201 + obj->links.netdata_account_page_dirtied_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_account_page_dirtied_kprobe,
202 + false,
203 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name);
204 + ret = libbpf_get_error(obj->links.netdata_account_page_dirtied_kprobe);
205 + }
206 +
207 + if (ret)
208 + return -1;
209 +
210 + obj->links.netdata_mark_buffer_dirty_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_mark_buffer_dirty_kprobe,
211 + false,
212 + cachestat_targets[NETDATA_KEY_CALLS_MARK_BUFFER_DIRTY].name);
213 + ret = libbpf_get_error(obj->links.netdata_mark_buffer_dirty_kprobe);
214 + if (ret)
215 + return -1;
216 +
217 + return 0;
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_cachestat_adjust_map_size(struct cachestat_bpf *obj, ebpf_module_t *em)
229 +{
230 + ebpf_update_map_size(obj->maps.cstat_pid, &cachestat_maps[NETDATA_CACHESTAT_PID_STATS],
231 + em, bpf_map__name(obj->maps.cstat_pid));
232 +}
233 +
234 +/**
235 + * Set hash tables
236 + *
237 + * Set the values for maps according the value given by kernel.
238 + *
239 + * @param obj is the main structure for bpf objects.
240 + */
241 +static void ebpf_cachestat_set_hash_tables(struct cachestat_bpf *obj)
242 +{
243 + cachestat_maps[NETDATA_CACHESTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.cstat_global);
244 + cachestat_maps[NETDATA_CACHESTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.cstat_pid);
245 + cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd = bpf_map__fd(obj->maps.cstat_ctrl);
246 +}
247 +
248 +/**
249 + * Load and attach
250 + *
251 + * Load and attach the eBPF code in kernel.
252 + *
253 + * @param obj is the main structure for bpf objects.
254 + * @param em structure with configuration
255 + *
256 + * @return it returns 0 on succes and -1 otherwise
257 + */
258 +static inline int ebpf_cachestat_load_and_attach(struct cachestat_bpf *obj, ebpf_module_t *em)
259 +{
260 + netdata_ebpf_targets_t *mt = em->targets;
261 + netdata_ebpf_program_loaded_t test = mt[NETDATA_KEY_CALLS_ADD_TO_PAGE_CACHE_LRU].mode;
262 +
263 + if (test == EBPF_LOAD_TRAMPOLINE) {
264 + ebpf_cachestat_disable_probe(obj);
265 + ebpf_cachestat_disable_specific_trampoline(obj);
266 +
267 + netdata_set_trampoline_target(obj);
268 + } else {
269 + ebpf_cachestat_disable_trampoline(obj);
270 + ebpf_cachestat_disable_specific_probe(obj);
271 + }
272 +
273 + int ret = cachestat_bpf__load(obj);
274 + if (ret) {
275 + return ret;
276 + }
277 +
278 + ebpf_cachestat_adjust_map_size(obj, em);
279 +
280 + ret = (test == EBPF_LOAD_TRAMPOLINE) ? cachestat_bpf__attach(obj) : ebpf_cachestat_attach_probe(obj);
281 + if (!ret) {
282 + ebpf_cachestat_set_hash_tables(obj);
283 +
284 + ebpf_update_controller(cachestat_maps[NETDATA_CACHESTAT_CTRL].map_fd, em);
285 + }
286 +
287 + return ret;
288 +}
289 +#endif
290 /*****************************************************************
291 *
292 * FUNCTIONS TO CLOSE THE THREAD
@@ -98,6 +340,10 @@ static void ebpf_cachestat_cleanup(void *ptr)
340 }
341 bpf_object__close(objects);
342 }
343 +#ifdef LIBBPF_MAJOR_VERSION
344 + else if (bpf_obj)
345 + cachestat_bpf__destroy(bpf_obj);
346 +#endif
347 }
348
349 /*****************************************************************
@@ -961,6 +1207,54 @@ static void ebpf_cachestat_allocate_global_vectors(int apps)
1207 *
1208 *****************************************************************/
1209
1210 +/**
1211 + * Update Internal value
1212 + *
1213 + * Update values used during runtime.
1214 + */
1215 +static void ebpf_cachestat_set_internal_value()
1216 +{
1217 + static char *account_page[] = { "account_page_dirtied", "__set_page_dirty", "__folio_mark_dirty" };
1218 + if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_16)
1219 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_FOLIO_DIRTY];
1220 + else if (running_on_kernel >= NETDATA_EBPF_KERNEL_5_15)
1221 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_SET_PAGE_DIRTY];
1222 + else
1223 + cachestat_targets[NETDATA_KEY_CALLS_ACCOUNT_PAGE_DIRTIED].name = account_page[NETDATA_CACHESTAT_ACCOUNT_PAGE_DIRTY];
1224 +}
1225 +
1226 +/*
1227 + * Load BPF
1228 + *
1229 + * Load BPF files.
1230 + *
1231 + * @param em the structure with configuration
1232 + */
1233 +static int ebpf_cachestat_load_bpf(ebpf_module_t *em)
1234 +{
1235 + int ret = 0;
1236 + if (em->load == EBPF_LOAD_LEGACY) {
1237 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1238 + if (!probe_links) {
1239 + ret = -1;
1240 + }
1241 + }
1242 +#ifdef LIBBPF_MAJOR_VERSION
1243 + else {
1244 + bpf_obj = cachestat_bpf__open();
1245 + if (!bpf_obj)
1246 + ret = -1;
1247 + else
1248 + ret = ebpf_cachestat_load_and_attach(bpf_obj, em);
1249 + }
1250 +#endif
1251 +
1252 + if (ret)
1253 + error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
1254 +
1255 + return ret;
1256 +}
1257 +
1258 /**
1259 * Cachestat thread
1260 *
@@ -982,17 +1276,17 @@ void *ebpf_cachestat_thread(void *ptr)
1276 if (!em->enabled)
1277 goto endcachestat;
1278
985 - pthread_mutex_lock(&lock);
986 - ebpf_cachestat_allocate_global_vectors(em->apps_charts);
1279 + ebpf_cachestat_set_internal_value();
1280
988 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
989 - if (!probe_links) {
990 - pthread_mutex_unlock(&lock);
1281 +#ifdef LIBBPF_MAJOR_VERSION
1282 + ebpf_adjust_thread_load(em, default_btf);
1283 +#endif
1284 + if (ebpf_cachestat_load_bpf(em)) {
1285 em->enabled = CONFIG_BOOLEAN_NO;
1286 goto endcachestat;
1287 }
1288
995 - ebpf_update_stats(&plugin_statistics, em);
1289 + ebpf_cachestat_allocate_global_vectors(em->apps_charts);
1290
1291 int algorithms[NETDATA_CACHESTAT_END] = {
1292 NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX
@@ -1002,8 +1296,9 @@ void *ebpf_cachestat_thread(void *ptr)
1296 cachestat_counter_dimension_name, cachestat_counter_dimension_name,
1297 algorithms, NETDATA_CACHESTAT_END);
1298
1299 + pthread_mutex_lock(&lock);
1300 + ebpf_update_stats(&plugin_statistics, em);
1301 ebpf_create_memory_charts(em);
1006 -
1302 pthread_mutex_unlock(&lock);
1303
1304 cachestat_collector(em);
collectors/ebpf.plugin/ebpf_cachestat.h
+9 -1
@@ -45,6 +45,12 @@ enum cachestat_counters {
45 NETDATA_CACHESTAT_END
46 };
47
48 +enum cachestat_account_dirty_pages {
49 + NETDATA_CACHESTAT_ACCOUNT_PAGE_DIRTY,
50 + NETDATA_CACHESTAT_SET_PAGE_DIRTY,
51 + NETDATA_CACHESTAT_FOLIO_DIRTY
52 +};
53 +
54 enum cachestat_indexes {
55 NETDATA_CACHESTAT_IDX_RATIO,
56 NETDATA_CACHESTAT_IDX_DIRTY,
@@ -54,7 +60,8 @@ enum cachestat_indexes {
60
61 enum cachestat_tables {
62 NETDATA_CACHESTAT_GLOBAL_STATS,
57 - NETDATA_CACHESTAT_PID_STATS
63 + NETDATA_CACHESTAT_PID_STATS,
64 + NETDATA_CACHESTAT_CTRL
65 };
66
67 typedef struct netdata_publish_cachestat_pid {
@@ -78,5 +85,6 @@ extern void *ebpf_cachestat_thread(void *ptr);
85 extern void clean_cachestat_pid_structures();
86
87 extern struct config cachestat_config;
88 +extern netdata_ebpf_targets_t cachestat_targets[];
89
90 #endif // NETDATA_EBPF_CACHESTAT_H
collectors/ebpf.plugin/ebpf_dcstat.c
+216 -8
@@ -49,6 +49,179 @@ static ebpf_specify_name_t dc_optional_name[] = { {.program_name = "netdata_look
49 .retprobe = CONFIG_BOOLEAN_NO},
50 {.program_name = NULL}};
51
52 +netdata_ebpf_targets_t dc_targets[] = { {.name = "lookup_fast", .mode = EBPF_LOAD_TRAMPOLINE},
53 + {.name = "d_lookup", .mode = EBPF_LOAD_TRAMPOLINE},
54 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
55 +
56 +#ifdef LIBBPF_MAJOR_VERSION
57 +#include "includes/dc.skel.h" // BTF code
58 +
59 +static struct dc_bpf *bpf_obj = NULL;
60 +
61 +/**
62 + * Disable probe
63 + *
64 + * Disable all probes to use exclusively another method.
65 + *
66 + * @param obj is the main structure for bpf objects
67 + */
68 +static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
69 +{
70 + bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
71 + bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
72 +}
73 +
74 +/*
75 + * Disable trampoline
76 + *
77 + * Disable all trampoline to use exclusively another method.
78 + *
79 + * @param obj is the main structure for bpf objects.
80 + */
81 +static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
82 +{
83 + bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
84 + bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
85 +}
86 +
87 +/**
88 + * Set trampoline target
89 + *
90 + * Set the targets we will monitor.
91 + *
92 + * @param obj is the main structure for bpf objects.
93 + */
94 +static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
95 +{
96 + bpf_program__set_attach_target(obj->progs.netdata_lookup_fast_fentry, 0,
97 + dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name);
98 +
99 + bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
100 + dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
101 +}
102 +
103 +/**
104 + * Mount Attach Probe
105 + *
106 + * Attach probes to target
107 + *
108 + * @param obj is the main structure for bpf objects.
109 + *
110 + * @return It returns 0 on success and -1 otherwise.
111 + */
112 +static int ebpf_dc_attach_probes(struct dc_bpf *obj)
113 +{
114 + obj->links.netdata_d_lookup_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_d_lookup_kretprobe,
115 + true,
116 + dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
117 + int ret = libbpf_get_error(obj->links.netdata_d_lookup_kretprobe);
118 + if (ret)
119 + return -1;
120 +
121 + char *lookup_name = (dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional) ?
122 + dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional :
123 + dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name ;
124 +
125 + obj->links.netdata_lookup_fast_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_lookup_fast_kprobe,
126 + false,
127 + lookup_name);
128 + ret = libbpf_get_error(obj->links.netdata_lookup_fast_kprobe);
129 + if (ret)
130 + return -1;
131 +
132 + return 0;
133 +}
134 +
135 +/**
136 + * Adjust Map Size
137 + *
138 + * Resize maps according input from users.
139 + *
140 + * @param obj is the main structure for bpf objects.
141 + * @param em structure with configuration
142 + */
143 +static void ebpf_dc_adjust_map_size(struct dc_bpf *obj, ebpf_module_t *em)
144 +{
145 + ebpf_update_map_size(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS],
146 + em, bpf_map__name(obj->maps.dcstat_pid));
147 +}
148 +
149 +/**
150 + * Set hash tables
151 + *
152 + * Set the values for maps according the value given by kernel.
153 + *
154 + * @param obj is the main structure for bpf objects.
155 + */
156 +static void ebpf_dc_set_hash_tables(struct dc_bpf *obj)
157 +{
158 + dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_global);
159 + dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_pid);
160 + dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd = bpf_map__fd(obj->maps.dcstat_ctrl);
161 +}
162 +
163 +/**
164 + * Update Load
165 + *
166 + * For directory cache, some distributions change the function name, and we do not have condition to use
167 + * TRAMPOLINE like other functions.
168 + *
169 + * @param em structure with configuration
170 + *
171 + * @return When then symbols were not modified, it returns TRAMPOLINE, else it returns RETPROBE.
172 + */
173 +netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
174 +{
175 + if (!strcmp(dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional,
176 + dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach))
177 + return EBPF_LOAD_TRAMPOLINE;
178 +
179 + if (em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode != EBPF_LOAD_RETPROBE)
180 + info("When your kernel was compiled the symbol %s was modified, instead to use `trampoline`, the plugin will use `probes`.",
181 + dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach);
182 +
183 + return EBPF_LOAD_RETPROBE;
184 +}
185 +
186 +/**
187 + * Load and attach
188 + *
189 + * Load and attach the eBPF code in kernel.
190 + *
191 + * @param obj is the main structure for bpf objects.
192 + * @param em structure with configuration
193 + *
194 + * @return it returns 0 on succes and -1 otherwise
195 + */
196 +static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
197 +{
198 + netdata_ebpf_program_loaded_t test = ebpf_dc_update_load(em);
199 + if (test == EBPF_LOAD_TRAMPOLINE) {
200 + ebpf_dc_disable_probes(obj);
201 +
202 + ebpf_dc_set_trampoline_target(obj);
203 + } else {
204 + ebpf_dc_disable_trampoline(obj);
205 + }
206 +
207 + int ret = dc_bpf__load(obj);
208 + if (ret) {
209 + return ret;
210 + }
211 +
212 + ebpf_dc_adjust_map_size(obj, em);
213 +
214 + ret = (test == EBPF_LOAD_TRAMPOLINE) ? dc_bpf__attach(obj) : ebpf_dc_attach_probes(obj);
215 + if (!ret) {
216 + ebpf_dc_set_hash_tables(obj);
217 +
218 + ebpf_update_controller(dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd, em);
219 + }
220 +
221 + return ret;
222 +}
223 +#endif
224 +
225 /*****************************************************************
226 *
227 * COMMON FUNCTIONS
@@ -141,6 +314,10 @@ static void ebpf_dcstat_cleanup(void *ptr)
314 }
315 bpf_object__close(objects);
316 }
317 +#ifdef LIBBPF_MAJOR_VERSION
318 + else if (bpf_obj)
319 + dc_bpf__destroy(bpf_obj);
320 +#endif
321 }
322
323 /*****************************************************************
@@ -937,6 +1114,38 @@ static void ebpf_dcstat_allocate_global_vectors(int apps)
1114 *
1115 *****************************************************************/
1116
1117 +/*
1118 + * Load BPF
1119 + *
1120 + * Load BPF files.
1121 + *
1122 + * @param em the structure with configuration
1123 + */
1124 +static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
1125 +{
1126 + int ret = 0;
1127 + if (em->load == EBPF_LOAD_LEGACY) {
1128 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
1129 + if (!probe_links) {
1130 + ret = -1;
1131 + }
1132 + }
1133 +#ifdef LIBBPF_MAJOR_VERSION
1134 + else {
1135 + bpf_obj = dc_bpf__open();
1136 + if (!bpf_obj)
1137 + ret = -1;
1138 + else
1139 + ret = ebpf_dc_load_and_attach(bpf_obj, em);
1140 + }
1141 +#endif
1142 +
1143 + if (ret)
1144 + error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
1145 +
1146 + return ret;
1147 +}
1148 +
1149 /**
1150 * Directory Cache thread
1151 *
@@ -960,17 +1169,16 @@ void *ebpf_dcstat_thread(void *ptr)
1169 if (!em->enabled)
1170 goto enddcstat;
1171
963 - ebpf_dcstat_allocate_global_vectors(em->apps_charts);
964 -
965 - pthread_mutex_lock(&lock);
966 -
967 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
968 - if (!probe_links) {
969 - pthread_mutex_unlock(&lock);
1172 +#ifdef LIBBPF_MAJOR_VERSION
1173 + ebpf_adjust_thread_load(em, default_btf);
1174 +#endif
1175 + if (ebpf_dcstat_load_bpf(em)) {
1176 em->enabled = CONFIG_BOOLEAN_NO;
1177 goto enddcstat;
1178 }
1179
1180 + ebpf_dcstat_allocate_global_vectors(em->apps_charts);
1181 +
1182 int algorithms[NETDATA_DCSTAT_IDX_END] = {
1183 NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
1184 NETDATA_EBPF_ABSOLUTE_IDX
@@ -980,9 +1188,9 @@ void *ebpf_dcstat_thread(void *ptr)
1188 dcstat_counter_dimension_name, dcstat_counter_dimension_name,
1189 algorithms, NETDATA_DCSTAT_IDX_END);
1190
1191 + pthread_mutex_lock(&lock);
1192 ebpf_create_filesystem_charts(em->update_every);
1193 ebpf_update_stats(&plugin_statistics, em);
985 -
1194 pthread_mutex_unlock(&lock);
1195
1196 dcstat_collector(em);
collectors/ebpf.plugin/ebpf_dcstat.h
+8 -1
@@ -42,7 +42,8 @@ enum directory_cache_indexes {
42
43 enum directory_cache_tables {
44 NETDATA_DCSTAT_GLOBAL_STATS,
45 - NETDATA_DCSTAT_PID_STATS
45 + NETDATA_DCSTAT_PID_STATS,
46 + NETDATA_DCSTAT_CTRL
47 };
48
49 // variables
@@ -55,6 +56,11 @@ enum directory_cache_counters {
56 NETDATA_DIRECTORY_CACHE_END
57 };
58
59 +enum directory_cache_targets {
60 + NETDATA_DC_TARGET_LOOKUP_FAST,
61 + NETDATA_DC_TARGET_D_LOOKUP
62 +};
63 +
64 typedef struct netdata_publish_dcstat_pid {
65 uint64_t cache_access;
66 uint64_t file_system;
@@ -73,5 +79,6 @@ extern void *ebpf_dcstat_thread(void *ptr);
79 extern void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr);
80 extern void clean_dcstat_pid_structures();
81 extern struct config dcstat_config;
82 +extern netdata_ebpf_targets_t dc_targets[];
83
84 #endif // NETDATA_EBPF_DCSTAT_H
collectors/ebpf.plugin/ebpf_swap.c
+188 -2
@@ -41,6 +41,154 @@ static struct bpf_object *objects = NULL;
41 struct netdata_static_thread swap_threads = {"SWAP KERNEL", NULL, NULL, 1,
42 NULL, NULL, NULL};
43
44 +netdata_ebpf_targets_t swap_targets[] = { {.name = "swap_readpage", .mode = EBPF_LOAD_TRAMPOLINE},
45 + {.name = "swap_writepage", .mode = EBPF_LOAD_TRAMPOLINE},
46 + {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
47 +
48 +#ifdef LIBBPF_MAJOR_VERSION
49 +#include "includes/swap.skel.h" // BTF code
50 +
51 +static struct swap_bpf *bpf_obj = NULL;
52 +
53 +/**
54 + * Disable probe
55 + *
56 + * Disable all probes to use exclusively another method.
57 + *
58 + * @param obj is the main structure for bpf objects
59 + */
60 +static void ebpf_swap_disable_probe(struct swap_bpf *obj)
61 +{
62 + bpf_program__set_autoload(obj->progs.netdata_swap_readpage_probe, false);
63 + bpf_program__set_autoload(obj->progs.netdata_swap_writepage_probe, false);
64 +}
65 +
66 +/*
67 + * Disable trampoline
68 + *
69 + * Disable all trampoline to use exclusively another method.
70 + *
71 + * @param obj is the main structure for bpf objects.
72 + */
73 +static void ebpf_swap_disable_trampoline(struct swap_bpf *obj)
74 +{
75 + bpf_program__set_autoload(obj->progs.netdata_swap_readpage_fentry, false);
76 + bpf_program__set_autoload(obj->progs.netdata_swap_writepage_fentry, false);
77 +}
78 +
79 +/**
80 + * Set trampoline target
81 + *
82 + * Set the targets we will monitor.
83 + *
84 + * @param obj is the main structure for bpf objects.
85 + */
86 +static void ebpf_swap_set_trampoline_target(struct swap_bpf *obj)
87 +{
88 + bpf_program__set_attach_target(obj->progs.netdata_swap_readpage_fentry, 0,
89 + swap_targets[NETDATA_KEY_SWAP_READPAGE_CALL].name);
90 +
91 + bpf_program__set_attach_target(obj->progs.netdata_swap_writepage_fentry, 0,
92 + swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
93 +}
94 +
95 +/**
96 + * Mount Attach Probe
97 + *
98 + * Attach probes to target
99 + *
100 + * @param obj is the main structure for bpf objects.
101 + *
102 + * @return It returns 0 on success and -1 otherwise.
103 + */
104 +static int ebpf_swap_attach_kprobe(struct swap_bpf *obj)
105 +{
106 + obj->links.netdata_swap_readpage_probe = bpf_program__attach_kprobe(obj->progs.netdata_swap_readpage_probe,
107 + false,
108 + swap_targets[NETDATA_KEY_SWAP_READPAGE_CALL].name);
109 + int ret = libbpf_get_error(obj->links.netdata_swap_readpage_probe);
110 + if (ret)
111 + return -1;
112 +
113 + obj->links.netdata_swap_writepage_probe = bpf_program__attach_kprobe(obj->progs.netdata_swap_writepage_probe,
114 + false,
115 + swap_targets[NETDATA_KEY_SWAP_WRITEPAGE_CALL].name);
116 + ret = libbpf_get_error(obj->links.netdata_swap_writepage_probe);
117 + if (ret)
118 + return -1;
119 +
120 + return 0;
121 +}
122 +
123 +/**
124 + * Set hash tables
125 + *
126 + * Set the values for maps according the value given by kernel.
127 + *
128 + * @param obj is the main structure for bpf objects.
129 + */
130 +static void ebpf_swap_set_hash_tables(struct swap_bpf *obj)
131 +{
132 + swap_maps[NETDATA_PID_SWAP_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_pid_swap);
133 + swap_maps[NETDATA_SWAP_CONTROLLER].map_fd = bpf_map__fd(obj->maps.swap_ctrl);
134 + swap_maps[NETDATA_SWAP_GLOBAL_TABLE].map_fd = bpf_map__fd(obj->maps.tbl_swap);
135 +}
136 +
137 +/**
138 + * Adjust Map Size
139 + *
140 + * Resize maps according input from users.
141 + *
142 + * @param obj is the main structure for bpf objects.
143 + * @param em structure with configuration
144 + */
145 +static void ebpf_swap_adjust_map_size(struct swap_bpf *obj, ebpf_module_t *em)
146 +{
147 + ebpf_update_map_size(obj->maps.tbl_pid_swap, &swap_maps[NETDATA_PID_SWAP_TABLE],
148 + em, bpf_map__name(obj->maps.tbl_pid_swap));
149 +}
150 +
151 +/**
152 + * Load and attach
153 + *
154 + * Load and attach the eBPF code in kernel.
155 + *
156 + * @param obj is the main structure for bpf objects.
157 + * @param em structure with configuration
158 + *
159 + * @return it returns 0 on succes and -1 otherwise
160 + */
161 +static inline int ebpf_swap_load_and_attach(struct swap_bpf *obj, ebpf_module_t *em)
162 +{
163 + netdata_ebpf_targets_t *mt = em->targets;
164 + netdata_ebpf_program_loaded_t test = mt[NETDATA_KEY_SWAP_READPAGE_CALL].mode;
165 +
166 + if (test == EBPF_LOAD_TRAMPOLINE) {
167 + ebpf_swap_disable_probe(obj);
168 +
169 + ebpf_swap_set_trampoline_target(obj);
170 + } else {
171 + ebpf_swap_disable_trampoline(obj);
172 + }
173 +
174 + int ret = swap_bpf__load(obj);
175 + if (ret) {
176 + return ret;
177 + }
178 +
179 + ebpf_swap_adjust_map_size(obj, em);
180 +
181 + ret = (test == EBPF_LOAD_TRAMPOLINE) ? swap_bpf__attach(obj) : ebpf_swap_attach_kprobe(obj);
182 + if (!ret) {
183 + ebpf_swap_set_hash_tables(obj);
184 +
185 + ebpf_update_controller(swap_maps[NETDATA_SWAP_CONTROLLER].map_fd, em);
186 + }
187 +
188 + return ret;
189 +}
190 +#endif
191 +
192 /*****************************************************************
193 *
194 * FUNCTIONS TO CLOSE THE THREAD
@@ -92,6 +240,10 @@ static void ebpf_swap_cleanup(void *ptr)
240 }
241 bpf_object__close(objects);
242 }
243 +#ifdef LIBBPF_MAJOR_VERSION
244 + else if (bpf_obj)
245 + swap_bpf__destroy(bpf_obj);
246 +#endif
247 }
248
249 /*****************************************************************
@@ -654,6 +806,38 @@ static void ebpf_create_swap_charts(int update_every)
806 update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
807 }
808
809 +/*
810 + * Load BPF
811 + *
812 + * Load BPF files.
813 + *
814 + * @param em the structure with configuration
815 + */
816 +static int ebpf_swap_load_bpf(ebpf_module_t *em)
817 +{
818 + int ret = 0;
819 + if (em->load == EBPF_LOAD_LEGACY) {
820 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
821 + if (!probe_links) {
822 + ret = -1;
823 + }
824 + }
825 +#ifdef LIBBPF_MAJOR_VERSION
826 + else {
827 + bpf_obj = swap_bpf__open();
828 + if (!bpf_obj)
829 + ret = -1;
830 + else
831 + ret = ebpf_swap_load_and_attach(bpf_obj, em);
832 + }
833 +#endif
834 +
835 + if (ret)
836 + error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
837 +
838 + return ret;
839 +}
840 +
841 /**
842 * SWAP thread
843 *
@@ -675,8 +859,10 @@ void *ebpf_swap_thread(void *ptr)
859 if (!em->enabled)
860 goto endswap;
861
678 - probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
679 - if (!probe_links) {
862 +#ifdef LIBBPF_MAJOR_VERSION
863 + ebpf_adjust_thread_load(em, default_btf);
864 +#endif
865 + if (ebpf_swap_load_bpf(em)) {
866 em->enabled = CONFIG_BOOLEAN_NO;
867 goto endswap;
868 }
collectors/ebpf.plugin/ebpf_swap.h
+1
@@ -49,5 +49,6 @@ extern void ebpf_swap_create_apps_charts(struct ebpf_module *em, void *ptr);
49 extern void clean_swap_pid_structures();
50
51 extern struct config swap_config;
52 +extern netdata_ebpf_targets_t swap_targets[];
53
54 #endif
packaging/ebpf-co-re.checksums
+1 -1
@@ -1 +1 @@
1 -0e3a6928a9b69a1a1e7911635b6d6fda44e78b67a3e38daad9d8cc3babfcdfee netdata-ebpf-co-re-glibc-v0.9.3.2.tar.xz
1 +9181063ec4a40f1b2ce5d7ac702eb9de233d127c6e21aac8a3d3f7c185502726 netdata-ebpf-co-re-glibc-v0.9.3.3.tar.xz
packaging/ebpf-co-re.version
+1 -1
@@ -1 +1 @@
1 -v0.9.3.2
1 +v0.9.3.3