@cryptotaxi247 / netdata-1 / commits / 561557c5a

eBPF mount (#11358)

thiagoftsm committed Jul 29, 2021 at 18:26 UTC 561557c5ae2f427033fb3809e52e8db7cbecf7f7
15 files changed +358 -5
CMakeLists.txt
+2
@@ -492,6 +492,8 @@ set(EBPF_PROCESS_PLUGIN_FILES
492 collectors/ebpf.plugin/ebpf_dcstat.h
493 collectors/ebpf.plugin/ebpf_disk.c
494 collectors/ebpf.plugin/ebpf_disk.h
495 + collectors/ebpf.plugin/ebpf_mount.c
496 + collectors/ebpf.plugin/ebpf_mount.h
497 collectors/ebpf.plugin/ebpf_filesystem.c
498 collectors/ebpf.plugin/ebpf_filesystem.h
499 collectors/ebpf.plugin/ebpf_process.c
Makefile.am
+2
@@ -297,6 +297,8 @@ EBPF_PLUGIN_FILES = \
297 collectors/ebpf.plugin/ebpf_disk.h \
298 collectors/ebpf.plugin/ebpf_filesystem.c \
299 collectors/ebpf.plugin/ebpf_filesystem.h \
300 + collectors/ebpf.plugin/ebpf_mount.c \
301 + collectors/ebpf.plugin/ebpf_mount.h \
302 collectors/ebpf.plugin/ebpf_process.c \
303 collectors/ebpf.plugin/ebpf_process.h \
304 collectors/ebpf.plugin/ebpf_socket.c \
collectors/all.h
+3
@@ -153,6 +153,9 @@
153
154 #define NETDATA_CHART_PRIO_EBPF_FILESYSTEM_CHARTS 2160
155
156 +// Mount Points
157 +#define NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS 2195
158 +
159 // NFS (server)
160
161 #define NETDATA_CHART_PRIO_NFSD_READCACHE 2200
collectors/ebpf.plugin/Makefile.am
+1
@@ -36,6 +36,7 @@ dist_ebpfconfig_DATA = \
36 ebpf.d/dcstat.conf \
37 ebpf.d/disk.conf \
38 ebpf.d/filesystem.conf \
39 + ebpf.d/mount.conf \
40 ebpf.d/network.conf \
41 ebpf.d/process.conf \
42 ebpf.d/sync.conf \
collectors/ebpf.plugin/ebpf.c
+25
@@ -120,6 +120,11 @@ ebpf_module_t ebpf_modules[] = {
120 .optional = 0, .apps_routine = NULL, .maps = NULL,
121 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &disk_config,
122 .config_file = NETDATA_SYNC_CONFIG_FILE},
123 + { .thread_name = "mount", .config_name = "mount", .enabled = 0, .start_routine = ebpf_mount_thread,
124 + .update_time = 1, .global_charts = 1, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
125 + .optional = 0, .apps_routine = NULL, .maps = NULL,
126 + .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &mount_config,
127 + .config_file = NETDATA_SYNC_CONFIG_FILE},
128 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1,
129 .global_charts = 0, .apps_charts = CONFIG_BOOLEAN_NO, .mode = MODE_ENTRY,
130 .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
@@ -692,6 +697,8 @@ void ebpf_print_help()
697 "\n"
698 " --filesystem or -i Enable chart related to filesystem run time.\n"
699 "\n"
700 + " --mount or -m Enable charts related to mount monitoring.\n"
701 + "\n"
702 " --net or -n Enable network viewer charts.\n"
703 "\n"
704 " --process or -p Enable charts related to process run time.\n"
@@ -1021,6 +1028,13 @@ static void read_collector_values(int *disable_apps)
1028 started++;
1029 }
1030
1031 + enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "mount",
1032 + CONFIG_BOOLEAN_YES);
1033 + if (enabled) {
1034 + ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, *disable_apps);
1035 + started++;
1036 + }
1037 +
1038 if (!started){
1039 ebpf_enable_all_charts(*disable_apps);
1040 // Read network viewer section
@@ -1107,6 +1121,7 @@ static void parse_args(int argc, char **argv)
1121 {"dcstat", no_argument, 0, 'd' },
1122 {"disk", no_argument, 0, 'k' },
1123 {"filesystem", no_argument, 0, 'i' },
1124 + {"mount", no_argument, 0, 'm' },
1125 {"net", no_argument, 0, 'n' },
1126 {"process", no_argument, 0, 'p' },
1127 {"return", no_argument, 0, 'r' },
@@ -1187,6 +1202,14 @@ static void parse_args(int argc, char **argv)
1202 ebpf_enable_chart(EBPF_MODULE_DISK_IDX, disable_apps);
1203 #ifdef NETDATA_INTERNAL_CHECKS
1204 info("EBPF enabling \"disk\" chart, because it was started with the option \"--disk\" or \"-k\".");
1205 +#endif
1206 + break;
1207 + }
1208 + case 'm': {
1209 + enabled = 1;
1210 + ebpf_enable_chart(EBPF_MODULE_MOUNT_IDX, disable_apps);
1211 +#ifdef NETDATA_INTERNAL_CHECKS
1212 + info("EBPF enabling \"mount\" chart, because it was started with the option \"--mount\" or \"-m\".");
1213 #endif
1214 break;
1215 }
@@ -1514,6 +1537,8 @@ int main(int argc, char **argv)
1537 NULL, NULL, ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].start_routine},
1538 {"EBPF DISK" , NULL, NULL, 1,
1539 NULL, NULL, ebpf_modules[EBPF_MODULE_DISK_IDX].start_routine},
1540 + {"EBPF MOUNT" , NULL, NULL, 1,
1541 + NULL, NULL, ebpf_modules[EBPF_MODULE_MOUNT_IDX].start_routine},
1542 {NULL , NULL, NULL, 0,
1543 NULL, NULL, NULL}
1544 };
collectors/ebpf.plugin/ebpf.d.conf
+2
@@ -28,6 +28,7 @@
28 # `cachestat` : Make charts for kernel functions related to page cache.
29 # `dcstat` : Make charts for kernel functions related to directory cache.
30 # `disk` : Monitor I/O latencies for disks
31 +# `mount` : Monitor calls for syscalls mount and umount
32 # `filesystem`: Monitor calls for functions used to manipulate specific filesystems
33 # `process` : This eBPF program creates charts that show information about process creation, and file manipulation.
34 # `socket` : This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
@@ -41,6 +42,7 @@
42 dcstat = no
43 disk = no
44 filesystem = no
45 + mount = yes
46 process = yes
47 socket = yes
48 sync = yes
collectors/ebpf.plugin/ebpf.d/mount.conf new
+8
@@ -0,0 +1,8 @@
1 +# The `ebpf load mode` option accepts the following values :
2 +# `entry` : The eBPF collector only monitors calls for the functions, and does not show charts related to errors.
3 +# `return : In the `return` mode, the eBPF collector monitors the same kernel functions as `entry`, but also creates
4 +# new charts for the return of these functions, such as errors.
5 +#
6 +[global]
7 + ebpf load mode = entry
8 + update every = 2
collectors/ebpf.plugin/ebpf.h
+3 -1
@@ -82,7 +82,8 @@ enum ebpf_module_indexes {
82 EBPF_MODULE_SWAP_IDX,
83 EBPF_MODULE_VFS_IDX,
84 EBPF_MODULE_FILESYSTEM_IDX,
85 - EBPF_MODULE_DISK_IDX
85 + EBPF_MODULE_DISK_IDX,
86 + EBPF_MODULE_MOUNT_IDX
87 };
88
89 // Copied from musl header
@@ -97,6 +98,7 @@ enum ebpf_module_indexes {
98 // Chart definitions
99 #define NETDATA_EBPF_FAMILY "ebpf"
100 #define NETDATA_FILESYSTEM_FAMILY "filesystem"
101 +#define NETDATA_EBPF_MOUNT_GLOBAL_FAMILY "mount_points"
102 #define NETDATA_EBPF_CHART_TYPE_LINE "line"
103 #define NETDATA_EBPF_CHART_TYPE_STACKED "stacked"
104 #define NETDATA_EBPF_MEMORY_GROUP "mem"
collectors/ebpf.plugin/ebpf_apps.h
+1
@@ -23,6 +23,7 @@
23 #include "ebpf_disk.h"
24 #include "ebpf_filesystem.h"
25 #include "ebpf_cachestat.h"
26 +#include "ebpf_mount.h"
27 #include "ebpf_sync.h"
28 #include "ebpf_swap.h"
29 #include "ebpf_vfs.h"
collectors/ebpf.plugin/ebpf_mount.c new
+255
@@ -0,0 +1,255 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "ebpf.h"
4 +#include "ebpf_mount.h"
5 +
6 +static ebpf_local_maps_t mount_maps[] = {{.name = "tbl_mount", .internal_input = NETDATA_MOUNT_END,
7 + .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
8 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
9 + {.name = NULL, .internal_input = 0, .user_input = 0,
10 + .type = NETDATA_EBPF_MAP_CONTROLLER,
11 + .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
12 +
13 +static ebpf_data_t mount_data;
14 +static char *mount_dimension_name[NETDATA_EBPF_MOUNT_SYSCALL] = { "mount", "umount" };
15 +static netdata_syscall_stat_t mount_aggregated_data[NETDATA_EBPF_MOUNT_SYSCALL];
16 +static netdata_publish_syscall_t mount_publish_aggregated[NETDATA_EBPF_MOUNT_SYSCALL];
17 +
18 +struct config mount_config = { .first_section = NULL, .last_section = NULL, .mutex = NETDATA_MUTEX_INITIALIZER,
19 + .index = {.avl_tree = { .root = NULL, .compar = appconfig_section_compare },
20 + .rwlock = AVL_LOCK_INITIALIZER } };
21 +
22 +static int read_thread_closed = 1;
23 +static netdata_idx_t *mount_values = NULL;
24 +
25 +static struct bpf_link **probe_links = NULL;
26 +static struct bpf_object *objects = NULL;
27 +
28 +static netdata_idx_t mount_hash_values[NETDATA_MOUNT_END];
29 +
30 +struct netdata_static_thread mount_thread = {"MOUNT KERNEL",
31 + NULL, NULL, 1, NULL,
32 + NULL, NULL};
33 +
34 +/*****************************************************************
35 + *
36 + * FUNCTIONS TO CLOSE THE THREAD
37 + *
38 + *****************************************************************/
39 +
40 +/**
41 + * Clean up the main thread.
42 + *
43 + * @param ptr thread data.
44 + */
45 +static void ebpf_mount_cleanup(void *ptr)
46 +{
47 + ebpf_module_t *em = (ebpf_module_t *)ptr;
48 + if (!em->enabled)
49 + return;
50 +
51 + freez(mount_thread.thread);
52 + freez(mount_values);
53 +
54 + if (probe_links) {
55 + struct bpf_program *prog;
56 + size_t i = 0 ;
57 + bpf_object__for_each_program(prog, objects) {
58 + bpf_link__destroy(probe_links[i]);
59 + i++;
60 + }
61 + bpf_object__close(objects);
62 + }
63 +}
64 +
65 +/*****************************************************************
66 + *
67 + * MAIN LOOP
68 + *
69 + *****************************************************************/
70 +
71 +/**
72 + * Read global table
73 + *
74 + * Read the table with number of calls for all functions
75 + */
76 +static void read_global_table()
77 +{
78 + uint32_t idx;
79 + netdata_idx_t *val = mount_hash_values;
80 + netdata_idx_t *stored = mount_values;
81 + int fd = mount_maps[NETDATA_KEY_MOUNT_TABLE].map_fd;
82 +
83 + for (idx = NETDATA_KEY_MOUNT_CALL; idx < NETDATA_MOUNT_END; idx++) {
84 + if (!bpf_map_lookup_elem(fd, &idx, stored)) {
85 + int i;
86 + int end = ebpf_nprocs;
87 + netdata_idx_t total = 0;
88 + for (i = 0; i < end; i++)
89 + total += stored[i];
90 +
91 + val[idx] = total;
92 + }
93 + }
94 +}
95 +
96 +/**
97 + * Mount read hash
98 + *
99 + * This is the thread callback.
100 + * This thread is necessary, because we cannot freeze the whole plugin to read the data.
101 + *
102 + * @param ptr It is a NULL value for this thread.
103 + *
104 + * @return It always returns NULL.
105 + */
106 +void *ebpf_mount_read_hash(void *ptr)
107 +{
108 + read_thread_closed = 0;
109 +
110 + heartbeat_t hb;
111 + heartbeat_init(&hb);
112 +
113 + ebpf_module_t *em = (ebpf_module_t *)ptr;
114 +
115 + usec_t step = NETDATA_LATENCY_MOUNT_SLEEP_MS * em->update_time;
116 + while (!close_ebpf_plugin) {
117 + usec_t dt = heartbeat_next(&hb, step);
118 + (void)dt;
119 +
120 + read_global_table();
121 + }
122 + read_thread_closed = 1;
123 +
124 + return NULL;
125 +}
126 +
127 +/**
128 + * Send data to Netdata calling auxiliar functions.
129 +*/
130 +static void ebpf_mount_send_data()
131 +{
132 + int i, j;
133 + int end = NETDATA_EBPF_MOUNT_SYSCALL;
134 + for (i = NETDATA_KEY_MOUNT_CALL, j = NETDATA_KEY_MOUNT_ERROR; i < end; i++, j++) {
135 + mount_publish_aggregated[i].ncall = mount_hash_values[i];
136 + mount_publish_aggregated[i].nerr = mount_hash_values[j];
137 + }
138 +
139 + write_count_chart(NETDATA_EBPF_MOUNT_CALLS, NETDATA_EBPF_MOUNT_GLOBAL_FAMILY,
140 + mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
141 +
142 + write_err_chart(NETDATA_EBPF_MOUNT_ERRORS, NETDATA_EBPF_MOUNT_GLOBAL_FAMILY,
143 + mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
144 +}
145 +
146 +/**
147 +* Main loop for this collector.
148 +*/
149 +static void mount_collector(ebpf_module_t *em)
150 +{
151 + mount_thread.thread = mallocz(sizeof(netdata_thread_t));
152 + mount_thread.start_routine = ebpf_mount_read_hash;
153 + memset(mount_hash_values, 0, sizeof(mount_hash_values));
154 +
155 + mount_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
156 +
157 + netdata_thread_create(mount_thread.thread, mount_thread.name, NETDATA_THREAD_OPTION_JOINABLE,
158 + ebpf_mount_read_hash, em);
159 +
160 + while (!close_ebpf_plugin) {
161 + pthread_mutex_lock(&collect_data_mutex);
162 + pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
163 +
164 + pthread_mutex_lock(&lock);
165 +
166 + ebpf_mount_send_data();
167 +
168 + pthread_mutex_unlock(&lock);
169 + pthread_mutex_unlock(&collect_data_mutex);
170 + }
171 +}
172 +
173 +/*****************************************************************
174 + *
175 + * INITIALIZE THREAD
176 + *
177 + *****************************************************************/
178 +
179 +/**
180 + * Create mount charts
181 + *
182 + * Call ebpf_create_chart to create the charts for the collector.
183 + */
184 +static void ebpf_create_mount_charts()
185 +{
186 + ebpf_create_chart(NETDATA_EBPF_MOUNT_GLOBAL_FAMILY, NETDATA_EBPF_MOUNT_CALLS,
187 + "Calls to mount and umount syscalls.",
188 + EBPF_COMMON_DIMENSION_CALL, NETDATA_EBPF_MOUNT_FAMILY,
189 + NULL,
190 + NETDATA_EBPF_CHART_TYPE_LINE,
191 + NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS,
192 + ebpf_create_global_dimension,
193 + mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
194 +
195 + ebpf_create_chart(NETDATA_EBPF_MOUNT_GLOBAL_FAMILY, NETDATA_EBPF_MOUNT_ERRORS,
196 + "Errors to mount and umount syscalls.",
197 + EBPF_COMMON_DIMENSION_CALL, NETDATA_EBPF_MOUNT_FAMILY,
198 + NULL,
199 + NETDATA_EBPF_CHART_TYPE_LINE,
200 + NETDATA_CHART_PRIO_EBPF_MOUNT_CHARTS + 1,
201 + ebpf_create_global_dimension,
202 + mount_publish_aggregated, NETDATA_EBPF_MOUNT_SYSCALL);
203 +
204 + fflush(stdout);
205 +}
206 +
207 +/*****************************************************************
208 + *
209 + * MAIN THREAD
210 + *
211 + *****************************************************************/
212 +
213 +/**
214 + * Mount thread
215 + *
216 + * Thread used to make mount thread
217 + *
218 + * @param ptr a pointer to `struct ebpf_module`
219 + *
220 + * @return It always returns NULL
221 + */
222 +void *ebpf_mount_thread(void *ptr)
223 +{
224 + netdata_thread_cleanup_push(ebpf_mount_cleanup, ptr);
225 +
226 + ebpf_module_t *em = (ebpf_module_t *)ptr;
227 + em->maps = mount_maps;
228 + fill_ebpf_data(&mount_data);
229 +
230 + if (!em->enabled)
231 + goto endmount;
232 +
233 + if (ebpf_update_kernel(&mount_data))
234 + goto endmount;
235 +
236 + probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string, &objects, mount_data.map_fd);
237 + if (!probe_links) {
238 + goto endmount;
239 + }
240 +
241 + int algorithms[NETDATA_EBPF_MOUNT_SYSCALL] = { NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX };
242 +
243 + ebpf_global_labels(mount_aggregated_data, mount_publish_aggregated, mount_dimension_name, mount_dimension_name,
244 + algorithms, NETDATA_EBPF_MOUNT_SYSCALL);
245 +
246 + pthread_mutex_lock(&lock);
247 + ebpf_create_mount_charts();
248 + pthread_mutex_unlock(&lock);
249 +
250 + mount_collector(em);
251 +
252 +endmount:
253 + netdata_thread_cleanup_pop(1);
254 + return NULL;
255 +}
collectors/ebpf.plugin/ebpf_mount.h new
+30
@@ -0,0 +1,30 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_EBPF_MOUNT_H
4 +#define NETDATA_EBPF_MOUNT_H 1
5 +
6 +#define NETDATA_EBPF_MOUNT_SYSCALL 2
7 +
8 +#define NETDATA_LATENCY_MOUNT_SLEEP_MS 700000ULL
9 +
10 +#define NETDATA_EBPF_MOUNT_CALLS "call"
11 +#define NETDATA_EBPF_MOUNT_ERRORS "error"
12 +#define NETDATA_EBPF_MOUNT_FAMILY "mount (eBPF)"
13 +
14 +enum mount_counters {
15 + NETDATA_KEY_MOUNT_CALL,
16 + NETDATA_KEY_UMOUNT_CALL,
17 + NETDATA_KEY_MOUNT_ERROR,
18 + NETDATA_KEY_UMOUNT_ERROR,
19 +
20 + NETDATA_MOUNT_END
21 +};
22 +
23 +enum mount_tables {
24 + NETDATA_KEY_MOUNT_TABLE
25 +};
26 +
27 +extern struct config mount_config;
28 +extern void *ebpf_mount_thread(void *ptr);
29 +
30 +#endif /* NETDATA_EBPF_MOUNT_H */
packaging/ebpf.checksums
+3 -3
@@ -1,3 +1,3 @@
1 -9144ec509b1d8dc43bfb5275935cfb9329d0da7a90bfefa5f1c2796d60991dd1 netdata-kernel-collector-glibc-v0.7.5.tar.xz
2 -a2c901e7f67472108c015a66b0c2dedf0cc3a791bbd8f75145c9c066aa7e0567 netdata-kernel-collector-musl-v0.7.5.tar.xz
3 -04231b6a5997c6f3330eeffa1897a4b331e70a21cb46278e4346c006824d7cb1 netdata-kernel-collector-static-v0.7.5.tar.xz
1 +0e5d9bbbffeef735534edaf5efa73e2f44b705699268bcc3028e48434e7fe8d0 netdata-kernel-collector-glibc-v0.7.6.tar.xz
2 +ee189fd82dae3c9e68756f88364bfdb97a29adb134ea7d95ae22f6059db4a632 netdata-kernel-collector-musl-v0.7.6.tar.xz
3 +98a31a53b9f7ca7b95c44ec12126357dc7d4c4d4a547142c8573a886ac6de430 netdata-kernel-collector-static-v0.7.6.tar.xz
packaging/ebpf.version
+1 -1
@@ -1 +1 @@
1 -v0.7.5
1 +v0.7.6
web/gui/dashboard_info.js
+14
@@ -127,6 +127,12 @@ netdataDashboard.menu = {
127 info: 'Charts with performance information for all the system disks. Special care has been given to present disk performance metrics in a way compatible with <code>iostat -x</code>. netdata by default prevents rendering performance charts for individual partitions and unmounted virtual disks. Disabled charts can still be enabled by configuring the relative settings in the netdata configuration file.'
128 },
129
130 + 'mount': {
131 + title: 'Mount Points',
132 + icon: '<i class="fas fa-hdd"></i>',
133 + info: ''
134 + },
135 +
136 'mdstat': {
137 title: 'MD arrays',
138 icon: '<i class="fas fa-hdd"></i>'
@@ -3588,6 +3594,14 @@ netdataDashboard.context = {
3594 info: 'Netdata is attaching <code>kprobes</code> for when the function <code>btrfs_sync_file</code>.'
3595 },
3596
3597 + 'mount_points.call': {
3598 + info: 'Monitor calls to syscalls <code>mount(2)</code> and <code>umount(2)</code> that are responsible for attaching or removing filesystems.'
3599 + },
3600 +
3601 + 'mount_points.error': {
3602 + info: 'Monitor errors in calls to syscalls <code>mount(2)</code> and <code>umount(2)</code>.'
3603 + },
3604 +
3605 // ------------------------------------------------------------------------
3606 // eBPF
3607
web/gui/main.js
+8
@@ -1410,6 +1410,14 @@ function enrichChartData(chart) {
1410 }
1411 break;
1412
1413 + case 'mount':
1414 + if (parts.length > 2) {
1415 + chart.menu = tmp + '_' + parts[1];
1416 + } else {
1417 + chart.menu = tmp;
1418 + }
1419 + break;
1420 +
1421 case 'isc':
1422 chart.menu = chart.type;
1423 if (parts.length > 2 && parts[1] === 'dhcpd') {