@cryptotaxi247 / netdata-1 / commits / 9f1c1bddf

eBPF ext4 (new thread for collector) (#11224)

* ebpf_ext4: Add new thread * ebpf_ext4: Add configuration files * ebpf_ext4: Add helpers to identify partitions and main threads * ebpf_ext4: Add helpers to create chart * ebpf_ext4: Add functions to read data from kernel ring * ebpf_ext4: Add functions to send data to Netdata * ebpf_ext4: Adjust dimensions * ebpf_ext4: Add information for dashboard * ebpf_ext4: Update documentation * ebpf_ext4: Update algorithm to read Array table instead hash table * ebpf_ext4: Add new eBPF version * ebpf_ext4: Add obsolete chart * ebpf_ext4: Fix coverity report * ebpf_ext4: Fix grammar in readme.md * ebpf_ext4: Update link inside dashboard_info.js * ebpf_ext4: Rename function and remove unused options inside filesystem.conf * ebpf_ext4: Rename variables and fix format * ebpf_ext4: Rename more variables * ebpf_ext4: Update algorithm to create dimensions * ebpf_ext4: Fix comment grammar * ebpf_ext4: Add messages to simplify comparison with hash table * ebpf_ext4: Update eBPF release * ebpf_ext4: Remove variables to improve the buckets * ebpf_ext4: Update algorithm to select filesystem * ebpf_ext4: Remove messages * ebpf_ext4: Add comment to filesystem

thiagoftsm committed Jun 8, 2021 at 12:30 UTC 9f1c1bddf40d175619cb73102ab880f80cd4e6bf
17 files changed +956 -24
CMakeLists.txt
+2
@@ -490,6 +490,8 @@ set(EBPF_PROCESS_PLUGIN_FILES
490 collectors/ebpf.plugin/ebpf_cachestat.h
491 collectors/ebpf.plugin/ebpf_dcstat.c
492 collectors/ebpf.plugin/ebpf_dcstat.h
493 + collectors/ebpf.plugin/ebpf_filesystem.c
494 + collectors/ebpf.plugin/ebpf_filesystem.h
495 collectors/ebpf.plugin/ebpf_process.c
496 collectors/ebpf.plugin/ebpf_process.h
497 collectors/ebpf.plugin/ebpf_socket.c
Makefile.am
+2
@@ -289,6 +289,8 @@ EBPF_PLUGIN_FILES = \
289 collectors/ebpf.plugin/ebpf_cachestat.h \
290 collectors/ebpf.plugin/ebpf_dcstat.c \
291 collectors/ebpf.plugin/ebpf_dcstat.h \
292 + collectors/ebpf.plugin/ebpf_filesystem.c \
293 + collectors/ebpf.plugin/ebpf_filesystem.h \
294 collectors/ebpf.plugin/ebpf_process.c \
295 collectors/ebpf.plugin/ebpf_process.h \
296 collectors/ebpf.plugin/ebpf_socket.c \
collectors/all.h
+2
@@ -150,6 +150,8 @@
150 #define NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_CREATE 2158
151 #define NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_ECREATE 2159
152
153 +#define NETDATA_CHART_PRIO_EBPF_FILESYSTEM_CHARTS 2160
154 +
155 // NFS (server)
156
157 #define NETDATA_CHART_PRIO_NFSD_READCACHE 2200
collectors/ebpf.plugin/Makefile.am
+1
@@ -34,6 +34,7 @@ dist_ebpfconfig_DATA = \
34 ebpf.d/ebpf_kernel_reject_list.txt \
35 ebpf.d/cachestat.conf \
36 ebpf.d/dcstat.conf \
37 + ebpf.d/filesystem.conf \
38 ebpf.d/network.conf \
39 ebpf.d/process.conf \
40 ebpf.d/sync.conf \
collectors/ebpf.plugin/README.md
+12
@@ -216,6 +216,7 @@ The eBPF collector enables and runs the following eBPF programs by default:
216 - `dcstat` : This eBPF program creates charts that show information about file access using directory cache. It appends
217 `kprobes` for `lookup_fast()` and `d_lookup()` to identify if files are inside directory cache, outside and
218 files are not found.
219 +- `filesystem`: This eBPF program creates charts that show latency information for selected filesystem.
220 - `process`: This eBPF program creates charts that show information about process creation, calls to open files.
221 When in `return` mode, it also creates charts showing errors when these operations are executed.
222 - `network viewer`: This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
@@ -239,6 +240,7 @@ The following configuration files are available:
240
241 - `cachestat.conf`: Configuration for the `cachestat` thread.
242 - `dcstat.conf`: Configuration for the `dcstat` thread.
243 +- `filesystem.conf`: Configuration for the `filesystem` thread.
244 - `process.conf`: Configuration for the `process` thread.
245 - `network.conf`: Configuration for the `network viewer` thread. This config file overwrites the global options and
246 also lets you specify which network the eBPF collector monitors.
@@ -315,6 +317,16 @@ monitored.
317 sync_file_range = yes
318 ```
319
320 +### Filesystem configuration
321 +
322 +The filesystem configuration has specific options to disable monitoring for filesystems, by default all
323 +filesystems are monitored.
324 +
325 +```conf
326 +[filesystem]
327 + ext4dist = yes
328 +```
329 +
330 ## Troubleshooting
331
332 If the eBPF collector does not work, you can troubleshoot it by running the `ebpf.plugin` command and investigating its
collectors/ebpf.plugin/ebpf.c
+64 -12
@@ -109,6 +109,11 @@ ebpf_module_t ebpf_modules[] = {
109 .optional = 0, .apps_routine = ebpf_vfs_create_apps_charts, .maps = NULL,
110 .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &vfs_config,
111 .config_file = NETDATA_DIRECTORY_VFS_CONFIG_FILE },
112 + { .thread_name = "filesystem", .config_name = "filesystem", .enabled = 0, .start_routine = ebpf_filesystem_thread,
113 + .update_time = 1, .global_charts = 1, .apps_charts = 1, .mode = MODE_ENTRY,
114 + .optional = 0, .apps_routine = NULL, .maps = NULL,
115 + .pid_map_size = ND_EBPF_DEFAULT_PID_SIZE, .names = NULL, .cfg = &fs_config,
116 + .config_file = NETDATA_SYNC_CONFIG_FILE},
117 { .thread_name = NULL, .enabled = 0, .start_routine = NULL, .update_time = 1,
118 .global_charts = 0, .apps_charts = 1, .mode = MODE_ENTRY,
119 .optional = 0, .apps_routine = NULL, .maps = NULL, .pid_map_size = 0, .names = NULL,
@@ -389,6 +394,33 @@ void ebpf_write_chart_cmd(char *type, char *id, char *title, char *units, char *
394 update_every);
395 }
396
397 +/**
398 + * Write chart cmd on standard output
399 + *
400 + * @param type chart type
401 + * @param id chart id
402 + * @param title chart title
403 + * @param units units label
404 + * @param family group name used to attach the chart on dashboard
405 + * @param charttype chart type
406 + * @param context chart context
407 + * @param order chart order
408 + */
409 +void ebpf_write_chart_obsolete(char *type, char *id, char *title, char *units, char *family,
410 + char *charttype, char *context, int order)
411 +{
412 + printf("CHART %s.%s '' '%s' '%s' '%s' '%s' '%s' %d %d 'obsolete'\n",
413 + type,
414 + id,
415 + title,
416 + units,
417 + (family)?family:"",
418 + (context)?context:"",
419 + (charttype)?charttype:"",
420 + order,
421 + update_every);
422 +}
423 +
424 /**
425 * Write the dimension command on standard output
426 *
@@ -625,6 +657,8 @@ void ebpf_print_help()
657 "\n"
658 " --dcstat or -d Enable charts related to directory cache.\n"
659 "\n"
660 + " --filesystem or -i Enable chart related to filesystem run time.\n"
661 + "\n"
662 " --net or -n Enable network viewer charts.\n"
663 "\n"
664 " --process or -p Enable charts related to process run time.\n"
@@ -940,6 +974,13 @@ static void read_collector_values(int *disable_apps)
974 started++;
975 }
976
977 + enabled = appconfig_get_boolean(&collector_config, EBPF_PROGRAMS_SECTION, "filesystem",
978 + CONFIG_BOOLEAN_NO);
979 + if (enabled) {
980 + ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, *disable_apps);
981 + started++;
982 + }
983 +
984 if (!started){
985 ebpf_enable_all_charts(*disable_apps);
986 // Read network viewer section
@@ -1018,18 +1059,19 @@ static void parse_args(int argc, char **argv)
1059 int freq = 0;
1060 int option_index = 0;
1061 static struct option long_options[] = {
1021 - {"help", no_argument, 0, 'h' },
1022 - {"version", no_argument, 0, 'v' },
1023 - {"global", no_argument, 0, 'g' },
1024 - {"all", no_argument, 0, 'a' },
1025 - {"cachestat", no_argument, 0, 'c' },
1026 - {"dcstat", no_argument, 0, 'd' },
1027 - {"net", no_argument, 0, 'n' },
1028 - {"process", no_argument, 0, 'p' },
1029 - {"return", no_argument, 0, 'r' },
1030 - {"sync", no_argument, 0, 's' },
1031 - {"swap", no_argument, 0, 'w' },
1032 - {"vfs", no_argument, 0, 'f' },
1062 + {"help", no_argument, 0, 'h' },
1063 + {"version", no_argument, 0, 'v' },
1064 + {"global", no_argument, 0, 'g' },
1065 + {"all", no_argument, 0, 'a' },
1066 + {"cachestat", no_argument, 0, 'c' },
1067 + {"dcstat", no_argument, 0, 'd' },
1068 + {"filesystem", no_argument, 0, 'i' },
1069 + {"net", no_argument, 0, 'n' },
1070 + {"process", no_argument, 0, 'p' },
1071 + {"return", no_argument, 0, 'r' },
1072 + {"sync", no_argument, 0, 's' },
1073 + {"swap", no_argument, 0, 'w' },
1074 + {"vfs", no_argument, 0, 'f' },
1075 {0, 0, 0, 0}
1076 };
1077
@@ -1088,6 +1130,14 @@ static void parse_args(int argc, char **argv)
1130 #ifdef NETDATA_INTERNAL_CHECKS
1131 info(
1132 "EBPF enabling \"DCSTAT\" charts, because it was started with the option \"--dcstat\" or \"-d\".");
1133 +#endif
1134 + break;
1135 + }
1136 + case 'i': {
1137 + enabled = 1;
1138 + ebpf_enable_chart(EBPF_MODULE_FILESYSTEM_IDX, disable_apps);
1139 +#ifdef NETDATA_INTERNAL_CHECKS
1140 + info("EBPF enabling \"filesystem\" chart, because it was started with the option \"--filesystem\" or \"-i\".");
1141 #endif
1142 break;
1143 }
@@ -1285,6 +1335,8 @@ int main(int argc, char **argv)
1335 NULL, NULL, ebpf_modules[EBPF_MODULE_SWAP_IDX].start_routine},
1336 {"EBPF VFS" , NULL, NULL, 1,
1337 NULL, NULL, ebpf_modules[EBPF_MODULE_VFS_IDX].start_routine},
1338 + {"EBPF FILESYSTEM" , NULL, NULL, 1,
1339 + NULL, NULL, ebpf_modules[EBPF_MODULE_FILESYSTEM_IDX].start_routine},
1340 {NULL , NULL, NULL, 0,
1341 NULL, NULL, NULL}
1342 };
collectors/ebpf.plugin/ebpf.d.conf
+9 -7
@@ -25,17 +25,19 @@
25 #
26 # The eBPF collector enables and runs the following eBPF programs by default:
27 #
28 -# `cachestat`: Make charts for kernel functions related to page cache.
29 -# `process` : This eBPF program creates charts that show information about process creation, and file manipulation.
30 -# `socket` : This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
31 -# bandwidth consumed by each.
32 -# `sync` : Montitor calls for syscall sync(2).
33 -# `swap` : Monitor calls for internal swap functions.
34 -# `vfs` : This eBPF program creates charts that show information about process VFS IO, VFS file manipulation and
28 +# `cachestat` : Make charts for kernel functions related to page cache.
29 +# `filesystem`: Monitor calls for functions used to manipulate specific filesystems
30 +# `process` : This eBPF program creates charts that show information about process creation, and file manipulation.
31 +# `socket` : This eBPF program creates charts with information about `TCP` and `UDP` functions, including the
32 +# bandwidth consumed by each.
33 +# `sync` : Montitor calls for syscall sync(2).
34 +# `swap` : Monitor calls for internal swap functions.
35 +# `vfs` : This eBPF program creates charts that show information about process VFS IO, VFS file manipulation and
36 # files removed.
37 [ebpf programs]
38 cachestat = no
39 dcstat = no
40 + filesystem = no
41 process = yes
42 socket = yes
43 sync = yes
collectors/ebpf.plugin/ebpf.d/filesystem.conf new
+16
@@ -0,0 +1,16 @@
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 +# The eBPF collector also creates charts for each running application through an integration with the `apps plugin`.
7 +# If you want to disable the integration with `apps.plugin` along with the above charts, change the setting `apps` to
8 +# 'no'.
9 +#
10 +[global]
11 + ebpf load mode = entry
12 + update every = 2
13 +
14 +# All filesystems are named as 'NAMEdist' where NAME is the filesystem name while 'dist' is a reference for distribution.
15 +[filesystem]
16 + ext4dist = yes
collectors/ebpf.plugin/ebpf.h
+4 -1
@@ -80,7 +80,8 @@ enum ebpf_module_indexes {
80 EBPF_MODULE_SYNC_IDX,
81 EBPF_MODULE_DCSTAT_IDX,
82 EBPF_MODULE_SWAP_IDX,
83 - EBPF_MODULE_VFS_IDX
83 + EBPF_MODULE_VFS_IDX,
84 + EBPF_MODULE_FILESYSTEM_IDX
85 };
86
87 // Copied from musl header
@@ -223,6 +224,8 @@ extern void ebpf_cachestat_create_apps_charts(struct ebpf_module *em, void *root
224 extern void ebpf_one_dimension_write_charts(char *family, char *chart, char *dim, long long v1);
225 extern collected_number get_value_from_structure(char *basis, size_t offset);
226 extern void ebpf_update_pid_table(ebpf_local_maps_t *pid, ebpf_module_t *em);
227 +extern void ebpf_write_chart_obsolete(char *type, char *id, char *title, char *units, char *family,
228 + char *charttype, char *context, int order);
229
230 #define EBPF_MAX_SYNCHRONIZATION_TIME 300
231
collectors/ebpf.plugin/ebpf_apps.h
+1
@@ -20,6 +20,7 @@
20
21 #include "ebpf_process.h"
22 #include "ebpf_dcstat.h"
23 +#include "ebpf_filesystem.h"
24 #include "ebpf_cachestat.h"
25 #include "ebpf_sync.h"
26 #include "ebpf_swap.h"
collectors/ebpf.plugin/ebpf_filesystem.c new
+620
@@ -0,0 +1,620 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "ebpf_filesystem.h"
4 +
5 +struct config fs_config = { .first_section = NULL,
6 + .last_section = NULL,
7 + .mutex = NETDATA_MUTEX_INITIALIZER,
8 + .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
9 + .rwlock = AVL_LOCK_INITIALIZER } };
10 +
11 +ebpf_filesystem_partitions_t localfs[] =
12 + {{.filesystem = "ext4",
13 + .family = "EXT4",
14 + .objects = NULL,
15 + .probe_links = NULL,
16 + .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
17 + .enabled = CONFIG_BOOLEAN_YES,
18 + .addresses = {.function = NULL, .addr = 0}},
19 + {.filesystem = NULL,
20 + .family = NULL,
21 + .objects = NULL,
22 + .probe_links = NULL,
23 + .flags = NETDATA_FILESYSTEM_FLAG_NO_PARTITION,
24 + .enabled = CONFIG_BOOLEAN_YES,
25 + .addresses = {.function = NULL, .addr = 0}}};
26 +
27 +struct netdata_static_thread filesystem_threads = {"EBPF FS READ",
28 + NULL, NULL, 1, NULL,
29 + NULL, NULL };
30 +
31 +static int read_thread_closed = 1;
32 +static netdata_syscall_stat_t filesystem_aggregated_data[NETDATA_FILESYSTEM_MAX_BINS];
33 +static netdata_publish_syscall_t filesystem_publish_aggregated[NETDATA_FILESYSTEM_MAX_BINS];
34 +
35 +char **dimensions = NULL;
36 +static netdata_idx_t *filesystem_hash_values = NULL;
37 +
38 +/*****************************************************************
39 + *
40 + * COMMON FUNCTIONS
41 + *
42 + *****************************************************************/
43 +
44 +/**
45 + * Create Filesystem chart
46 + *
47 + * Create latency charts
48 + */
49 +static void ebpf_obsolete_fs_charts()
50 +{
51 + int i;
52 + uint32_t test = NETDATA_FILESYSTEM_FLAG_CHART_CREATED | NETDATA_FILESYSTEM_REMOVE_CHARTS;
53 + for (i = 0; localfs[i].filesystem; i++) {
54 + ebpf_filesystem_partitions_t *efp = &localfs[i];
55 + uint32_t flags = efp->flags;
56 + if ((flags & test) == test) {
57 + flags &= ~NETDATA_FILESYSTEM_FLAG_CHART_CREATED;
58 +
59 + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
60 + efp->hread.title,
61 + EBPF_COMMON_DIMENSION_CALL, efp->family_name,
62 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hread.order);
63 +
64 + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
65 + efp->hwrite.title,
66 + EBPF_COMMON_DIMENSION_CALL, efp->family_name,
67 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hwrite.order);
68 +
69 + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name,
70 + efp->hopen.title,
71 + EBPF_COMMON_DIMENSION_CALL, efp->family_name,
72 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hopen.order);
73 +
74 + ebpf_write_chart_obsolete(NETDATA_FILESYSTEM_FAMILY, efp->hsync.name,
75 + efp->hsync.title,
76 + EBPF_COMMON_DIMENSION_CALL, efp->family_name,
77 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, efp->hsync.order);
78 + }
79 + efp->flags = flags;
80 + }
81 +}
82 +
83 +/**
84 + * Create Filesystem chart
85 + *
86 + * Create latency charts
87 + */
88 +static void ebpf_create_fs_charts()
89 +{
90 + static int order = NETDATA_CHART_PRIO_EBPF_FILESYSTEM_CHARTS;
91 + char chart_name[64], title[256], family[64];
92 + int i;
93 + uint32_t test = NETDATA_FILESYSTEM_FLAG_CHART_CREATED|NETDATA_FILESYSTEM_REMOVE_CHARTS;
94 + for (i = 0; localfs[i].filesystem; i++) {
95 + ebpf_filesystem_partitions_t *efp = &localfs[i];
96 + uint32_t flags = efp->flags;
97 + if (flags & NETDATA_FILESYSTEM_FLAG_HAS_PARTITION && !(flags & test)) {
98 + snprintfz(title, 255, "%s latency for each read request.", efp->filesystem);
99 + snprintfz(family, 63, "%s latency (eBPF)", efp->family);
100 + snprintfz(chart_name, 63, "%s_read_latency", efp->filesystem);
101 + efp->hread.name = strdupz(chart_name);
102 + efp->hread.title = strdupz(title);
103 + efp->hread.order = order;
104 + efp->family_name = strdupz(family);
105 +
106 + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
107 + title,
108 + EBPF_COMMON_DIMENSION_CALL, family,
109 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
110 + filesystem_publish_aggregated, NETDATA_FILESYSTEM_MAX_BINS);
111 + order++;
112 +
113 + snprintfz(title, 255, "%s latency for each write request.", efp->filesystem);
114 + snprintfz(chart_name, 63, "%s_write_latency", efp->filesystem);
115 + efp->hwrite.name = strdupz(chart_name);
116 + efp->hwrite.title = strdupz(title);
117 + efp->hwrite.order = order;
118 + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
119 + title,
120 + EBPF_COMMON_DIMENSION_CALL, family,
121 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
122 + filesystem_publish_aggregated, NETDATA_FILESYSTEM_MAX_BINS);
123 + order++;
124 +
125 + snprintfz(title, 255, "%s latency for each open request.", efp->filesystem);
126 + snprintfz(chart_name, 63, "%s_open_latency", efp->filesystem);
127 + efp->hopen.name = strdupz(chart_name);
128 + efp->hopen.title = strdupz(title);
129 + efp->hopen.order = order;
130 + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name,
131 + title,
132 + EBPF_COMMON_DIMENSION_CALL, family,
133 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
134 + filesystem_publish_aggregated, NETDATA_FILESYSTEM_MAX_BINS);
135 + order++;
136 +
137 + snprintfz(title, 255, "%s latency for each sync request.", efp->filesystem);
138 + snprintfz(chart_name, 63, "%s_sync_latency", efp->filesystem);
139 + efp->hsync.name = strdupz(chart_name);
140 + efp->hsync.title = strdupz(title);
141 + efp->hsync.order = order;
142 + ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, efp->hsync.name,
143 + title,
144 + EBPF_COMMON_DIMENSION_CALL, family,
145 + NULL, NETDATA_EBPF_CHART_TYPE_STACKED, order, ebpf_create_global_dimension,
146 + filesystem_publish_aggregated, NETDATA_FILESYSTEM_MAX_BINS);
147 + order++;
148 + efp->flags |= NETDATA_FILESYSTEM_FLAG_CHART_CREATED;
149 + }
150 + }
151 +}
152 +
153 +/**
154 + * Initialize eBPF data
155 + *
156 + * @param em main thread structure.
157 + *
158 + * @return it returns 0 on success and -1 otherwise.
159 + */
160 +int ebpf_filesystem_initialize_ebpf_data(ebpf_module_t *em)
161 +{
162 + int i;
163 + const char *saved_name = em->thread_name;
164 + for (i = 0; localfs[i].filesystem; i++) {
165 + ebpf_filesystem_partitions_t *efp = &localfs[i];
166 + if (!efp->probe_links && efp->flags & NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM) {
167 + ebpf_data_t *ed = &efp->kernel_info;
168 + fill_ebpf_data(ed);
169 +
170 + if (ebpf_update_kernel(ed)) {
171 + em->thread_name = saved_name;
172 + return -1;
173 + }
174 +
175 + em->thread_name = efp->filesystem;
176 + efp->probe_links = ebpf_load_program(ebpf_plugin_dir, em, kernel_string,
177 + &efp->objects, ed->map_fd);
178 + if (!efp->probe_links) {
179 + em->thread_name = saved_name;
180 + return -1;
181 + }
182 + efp->flags |= NETDATA_FILESYSTEM_FLAG_HAS_PARTITION;
183 +
184 + // Nedeed for filesystems like btrfs
185 + if ((efp->flags & NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE) && (efp->addresses.function))
186 + ebpf_load_addresses(&efp->addresses, efp->kernel_info.map_fd[NETDATA_ADDR_FS_TABLE]);
187 + }
188 + efp->flags &= ~NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM;
189 + }
190 + em->thread_name = saved_name;
191 +
192 + if (!dimensions) {
193 + dimensions = ebpf_fill_histogram_dimension(NETDATA_FILESYSTEM_MAX_BINS);
194 +
195 + memset(filesystem_aggregated_data, 0 , NETDATA_FILESYSTEM_MAX_BINS * sizeof(netdata_syscall_stat_t));
196 + memset(filesystem_publish_aggregated, 0 , NETDATA_FILESYSTEM_MAX_BINS * sizeof(netdata_publish_syscall_t));
197 +
198 + filesystem_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
199 + }
200 +
201 + return 0;
202 +}
203 +
204 +/**
205 + * Read Local partitions
206 + *
207 + * @return the total of partitions that will be monitored
208 + */
209 +static int ebpf_read_local_partitions()
210 +{
211 + char filename[FILENAME_MAX + 1];
212 + snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
213 + procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
214 + if(unlikely(!ff)) {
215 + snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix);
216 + ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
217 + if(unlikely(!ff)) return 0;
218 + }
219 +
220 + ff = procfile_readall(ff);
221 + if(unlikely(!ff))
222 + return 0;
223 +
224 + int count = 0;
225 + unsigned long l, i, lines = procfile_lines(ff);
226 + for (i = 0; localfs[i].filesystem; i++) {
227 + localfs[i].flags |= NETDATA_FILESYSTEM_REMOVE_CHARTS;
228 + }
229 +
230 + for(l = 0; l < lines ; l++) {
231 + // In "normal" situation the expected value is at column 7
232 + // When `shared` options is added to mount information, the filesystem is at column 8
233 + // Finally when we have systemd starting netdata, it will be at column 9
234 + unsigned long index = procfile_linewords(ff, l) - 3;
235 +
236 + char *fs = procfile_lineword(ff, l, index);
237 +
238 + for (i = 0; localfs[i].filesystem; i++) {
239 + ebpf_filesystem_partitions_t *w = &localfs[i];
240 + if (w->enabled && !strcmp(fs, w->filesystem)) {
241 + localfs[i].flags |= NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM;
242 + localfs[i].flags &= ~NETDATA_FILESYSTEM_REMOVE_CHARTS;
243 + count++;
244 + break;
245 + }
246 + }
247 + }
248 + procfile_close(ff);
249 +
250 + return count;
251 +}
252 +
253 +/**
254 + * Update partition
255 + *
256 + * Update the partition structures before to plot
257 + *
258 + * @param em main thread structure
259 + *
260 + * @return 0 on success and -1 otherwise.
261 + */
262 +static int ebpf_update_partitions(ebpf_module_t *em)
263 +{
264 + static time_t update_time = 0;
265 + time_t curr = now_realtime_sec();
266 + if (curr < update_time)
267 + return 0;
268 +
269 + update_time = curr + 5 * em->update_time;
270 + if (!ebpf_read_local_partitions()) {
271 + em->optional = -1;
272 + return -1;
273 + }
274 +
275 + if (ebpf_filesystem_initialize_ebpf_data(em)) {
276 + return -1;
277 + }
278 +
279 + return 0;
280 +}
281 +
282 +/*****************************************************************
283 + *
284 + * CLEANUP FUNCTIONS
285 + *
286 + *****************************************************************/
287 +
288 +/*
289 + * Cleanup eBPF data
290 + */
291 +void ebpf_filesystem_cleanup_ebpf_data()
292 +{
293 + int i;
294 + for (i = 0; localfs[i].filesystem; i++) {
295 + ebpf_filesystem_partitions_t *efp = &localfs[i];
296 + if (efp->probe_links) {
297 + freez(efp->kernel_info.map_fd);
298 + freez(efp->family_name);
299 +
300 + freez(efp->hread.name);
301 + freez(efp->hread.title);
302 +
303 + freez(efp->hwrite.name);
304 + freez(efp->hwrite.title);
305 +
306 + freez(efp->hopen.name);
307 + freez(efp->hopen.title);
308 +
309 + freez(efp->hsync.name);
310 + freez(efp->hsync.title);
311 +
312 + struct bpf_link **probe_links = efp->probe_links;
313 + size_t j = 0 ;
314 + struct bpf_program *prog;
315 + bpf_object__for_each_program(prog, efp->objects) {
316 + bpf_link__destroy(probe_links[j]);
317 + j++;
318 + }
319 + bpf_object__close(efp->objects);
320 +
321 + ebpf_histogram_dimension_cleanup(dimensions, NETDATA_FILESYSTEM_MAX_BINS);
322 + freez(filesystem_hash_values);
323 + }
324 + }
325 +}
326 +
327 +/**
328 + * Clean up the main thread.
329 + *
330 + * @param ptr thread data.
331 + */
332 +static void ebpf_filesystem_cleanup(void *ptr)
333 +{
334 + ebpf_module_t *em = (ebpf_module_t *)ptr;
335 + if (!em->enabled)
336 + return;
337 +
338 + heartbeat_t hb;
339 + heartbeat_init(&hb);
340 + uint32_t tick = 2*USEC_PER_MS;
341 + while (!read_thread_closed) {
342 + usec_t dt = heartbeat_next(&hb, tick);
343 + UNUSED(dt);
344 + }
345 +
346 + freez(filesystem_threads.thread);
347 + ebpf_cleanup_publish_syscall(filesystem_publish_aggregated);
348 +
349 + ebpf_filesystem_cleanup_ebpf_data();
350 +}
351 +
352 +/*****************************************************************
353 + *
354 + * MAIN THREAD
355 + *
356 + *****************************************************************/
357 +
358 +/**
359 + * Select hist
360 + *
361 + * Select a histogram to store data.
362 + *
363 + * @param efp pointer for the structure with pointers.
364 + * @param id histogram selector
365 + *
366 + * @return It returns a pointer for the histogram
367 + */
368 +static inline netdata_ebpf_histogram_t *select_hist(ebpf_filesystem_partitions_t *efp, uint32_t *idx, uint32_t id)
369 +{
370 + if (id < NETDATA_KEY_CALLS_READ) {
371 + *idx = id;
372 + return &efp->hread;
373 + } else if (id < NETDATA_KEY_CALLS_WRITE) {
374 + *idx = id - NETDATA_KEY_CALLS_READ;
375 + return &efp->hwrite;
376 + } else if (id < NETDATA_KEY_CALLS_OPEN) {
377 + *idx = id - NETDATA_KEY_CALLS_WRITE;
378 + return &efp->hopen;
379 + } else if (id < NETDATA_KEY_CALLS_SYNC ){
380 + *idx = id - NETDATA_KEY_CALLS_OPEN;
381 + return &efp->hsync;
382 + }
383 +
384 + return NULL;
385 +}
386 +
387 +/**
388 + * Read hard disk table
389 + *
390 + * @param table index for the hash table
391 + *
392 + * Read the table with number of calls for all functions
393 + */
394 +static void read_filesystem_table(ebpf_filesystem_partitions_t *efp)
395 +{
396 + netdata_idx_t *values = filesystem_hash_values;
397 + uint32_t key;
398 + uint32_t idx;
399 + int fd = efp->kernel_info.map_fd[NETDATA_MAIN_FS_TABLE];
400 + for (key = 0; key < NETDATA_KEY_CALLS_SYNC; key++) {
401 + netdata_ebpf_histogram_t *w = select_hist(efp, &idx, key);
402 + if (!w) {
403 + continue;
404 + }
405 +
406 + int test = bpf_map_lookup_elem(fd, &key, values);
407 + if (test < 0) {
408 + continue;
409 + }
410 +
411 + uint64_t total = 0;
412 + int i;
413 + int end = ebpf_nprocs;
414 + for (i = 0; i < end; i++) {
415 + total += values[i];
416 + }
417 +
418 + w->histogram[idx] = total;
419 + }
420 +}
421 +
422 +/**
423 + * Read hard disk table
424 + *
425 + * @param table index for the hash table
426 + *
427 + * Read the table with number of calls for all functions
428 + */
429 +static void read_filesystem_tables()
430 +{
431 + int i;
432 + for (i = 0; localfs[i].filesystem; i++) {
433 + ebpf_filesystem_partitions_t *efp = &localfs[i];
434 + if (efp->flags & NETDATA_FILESYSTEM_FLAG_HAS_PARTITION) {
435 + read_filesystem_table(efp);
436 + }
437 + }
438 +}
439 +
440 +/**
441 + * Socket read hash
442 + *
443 + * This is the thread callback.
444 + * This thread is necessary, because we cannot freeze the whole plugin to read the data on very busy socket.
445 + *
446 + * @param ptr It is a NULL value for this thread.
447 + *
448 + * @return It always returns NULL.
449 + */
450 +void *ebpf_filesystem_read_hash(void *ptr)
451 +{
452 + ebpf_module_t *em = (ebpf_module_t *)ptr;
453 + read_thread_closed = 0;
454 +
455 + heartbeat_t hb;
456 + heartbeat_init(&hb);
457 + usec_t step = NETDATA_FILESYSTEM_READ_SLEEP_MS * em->update_time;
458 + while (!close_ebpf_plugin) {
459 + usec_t dt = heartbeat_next(&hb, step);
460 + (void)dt;
461 +
462 + (void) ebpf_update_partitions(em);
463 + ebpf_obsolete_fs_charts();
464 +
465 + // No more partitions, it is not necessary to read tables
466 + if (em->optional)
467 + continue;
468 +
469 + read_filesystem_tables();
470 + }
471 +
472 + read_thread_closed = 1;
473 + return NULL;
474 +}
475 +
476 +/**
477 + * Call the necessary functions to create a name.
478 + *
479 + * @param family family name
480 + * @param name chart name
481 + * @param hist0 histogram values
482 + * @param end number of bins that will be sent to Netdata.
483 + *
484 + * @return It returns a variable tha maps the charts that did not have zero values.
485 + */
486 +static void write_histogram_chart(char *family, char *name, const netdata_idx_t *hist, uint32_t end)
487 +{
488 + write_begin_chart(family, name);
489 +
490 + uint32_t i;
491 + for (i = 0; i < end; i++) {
492 + write_chart_dimension(dimensions[i], (long long) hist[i]);
493 + }
494 +
495 + write_end_chart();
496 +
497 + fflush(stdout);
498 +}
499 +
500 +/**
501 + * Send Hard disk data
502 + *
503 + * Send hard disk information to Netdata.
504 + */
505 +static void ebpf_histogram_send_data()
506 +{
507 + uint32_t i;
508 + for (i = 0; localfs[i].filesystem; i++) {
509 + ebpf_filesystem_partitions_t *efp = &localfs[i];
510 + if (efp->flags & NETDATA_FILESYSTEM_FLAG_HAS_PARTITION) {
511 + write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hread.name,
512 + efp->hread.histogram, NETDATA_FILESYSTEM_MAX_BINS);
513 +
514 + write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hwrite.name,
515 + efp->hwrite.histogram, NETDATA_FILESYSTEM_MAX_BINS);
516 +
517 + write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hopen.name,
518 + efp->hopen.histogram, NETDATA_FILESYSTEM_MAX_BINS);
519 +
520 + write_histogram_chart(NETDATA_FILESYSTEM_FAMILY, efp->hsync.name,
521 + efp->hsync.histogram, NETDATA_FILESYSTEM_MAX_BINS);
522 + }
523 + }
524 +}
525 +
526 +/**
527 + * Main loop for this collector.
528 + *
529 + * @param em main structure for this thread
530 + */
531 +static void filesystem_collector(ebpf_module_t *em)
532 +{
533 + filesystem_threads.thread = mallocz(sizeof(netdata_thread_t));
534 + filesystem_threads.start_routine = ebpf_filesystem_read_hash;
535 +
536 + netdata_thread_create(filesystem_threads.thread, filesystem_threads.name,
537 + NETDATA_THREAD_OPTION_JOINABLE, ebpf_filesystem_read_hash, em);
538 +
539 + while (!close_ebpf_plugin || em->optional) {
540 + pthread_mutex_lock(&collect_data_mutex);
541 + pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
542 +
543 + pthread_mutex_lock(&lock);
544 +
545 + ebpf_create_fs_charts();
546 + ebpf_histogram_send_data();
547 +
548 + pthread_mutex_unlock(&collect_data_mutex);
549 + pthread_mutex_unlock(&lock);
550 + }
551 +}
552 +
553 +/*****************************************************************
554 + *
555 + * ENTRY THREAD
556 + *
557 + *****************************************************************/
558 +
559 +/**
560 + * Update Filesystem
561 + *
562 + * Update file system structure using values read from configuration file.
563 + */
564 +static void ebpf_update_filesystem()
565 +{
566 + char dist[NETDATA_FS_MAX_DIST_NAME + 1];
567 + int i;
568 + for (i = 0; localfs[i].filesystem; i++) {
569 + snprintfz(dist, NETDATA_FS_MAX_DIST_NAME, "%sdist", localfs[i].filesystem);
570 +
571 + localfs[i].enabled = appconfig_get_boolean(&fs_config, NETDATA_FILESYSTEM_CONFIG_NAME, dist,
572 + CONFIG_BOOLEAN_YES);
573 + }
574 +}
575 +
576 +/**
577 + * Filesystem thread
578 + *
579 + * Thread used to generate socket charts.
580 + *
581 + * @param ptr a pointer to `struct ebpf_module`
582 + *
583 + * @return It always return NULL
584 + */
585 +void *ebpf_filesystem_thread(void *ptr)
586 +{
587 + netdata_thread_cleanup_push(ebpf_filesystem_cleanup, ptr);
588 +
589 + ebpf_module_t *em = (ebpf_module_t *)ptr;
590 + ebpf_update_filesystem();
591 +
592 + if (!em->enabled)
593 + goto endfilesystem;
594 +
595 + // Initialize optional as zero, to identify when there are not partitions to monitor
596 + em->optional = 0;
597 +
598 + if (ebpf_update_partitions(em)) {
599 + if (em->optional)
600 + info("Netdata cannot monitor the filesystems used on this host.");
601 +
602 + em->enabled = 0;
603 + goto endfilesystem;
604 + }
605 +
606 + int algorithms[NETDATA_FILESYSTEM_MAX_BINS];
607 + ebpf_fill_algorithms(algorithms, NETDATA_FILESYSTEM_MAX_BINS, NETDATA_EBPF_INCREMENTAL_IDX);
608 + ebpf_global_labels(filesystem_aggregated_data, filesystem_publish_aggregated, dimensions, dimensions,
609 + algorithms, NETDATA_FILESYSTEM_MAX_BINS);
610 +
611 + pthread_mutex_lock(&lock);
612 + ebpf_create_fs_charts();
613 + pthread_mutex_unlock(&lock);
614 +
615 + filesystem_collector(em);
616 +
617 +endfilesystem:
618 + netdata_thread_cleanup_pop(1);
619 + return NULL;
620 +}
collectors/ebpf.plugin/ebpf_filesystem.h new
+70
@@ -0,0 +1,70 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_EBPF_FILESYSTEM_H
4 +#define NETDATA_EBPF_FILESYSTEM_H 1
5 +
6 +#include "ebpf.h"
7 +
8 +#define NETDATA_FILESYSTEM_MAX_BINS 24UL
9 +#define NETDATA_FS_MAX_DIST_NAME 64UL
10 +
11 +#define NETDATA_FILESYSTEM_CONFIG_NAME "filesystem"
12 +#define NETDATA_FILESYSTEM_READ_SLEEP_MS 600000ULL
13 +
14 +typedef struct netdata_fs_hist {
15 + uint32_t hist_id;
16 + uint32_t bin;
17 +} netdata_fs_hist_t;
18 +
19 +enum filesystem_limit {
20 + NETDATA_KEY_CALLS_READ = 24,
21 + NETDATA_KEY_CALLS_WRITE = 48,
22 + NETDATA_KEY_CALLS_OPEN = 72,
23 + NETDATA_KEY_CALLS_SYNC = 96
24 +};
25 +
26 +enum netdata_filesystem_flags {
27 + NETDATA_FILESYSTEM_FLAG_NO_PARTITION = 0,
28 + NETDATA_FILESYSTEM_LOAD_EBPF_PROGRAM = 1,
29 + NETDATA_FILESYSTEM_FLAG_HAS_PARTITION = 2,
30 + NETDATA_FILESYSTEM_FLAG_CHART_CREATED = 4,
31 + NETDATA_FILESYSTEM_FILL_ADDRESS_TABLE = 8,
32 + NETDATA_FILESYSTEM_REMOVE_CHARTS = 16
33 +};
34 +
35 +typedef struct netdata_ebpf_histogram {
36 + char *name;
37 + char *title;
38 + int order;
39 + uint64_t histogram[NETDATA_FILESYSTEM_MAX_BINS];
40 +} netdata_ebpf_histogram_t;
41 +
42 +
43 +enum netdata_filesystem_table {
44 + NETDATA_MAIN_FS_TABLE,
45 + NETDATA_ADDR_FS_TABLE
46 +};
47 +
48 +typedef struct ebpf_filesystem_partitions {
49 + char *filesystem;
50 + char *family;
51 + char *family_name;
52 + struct bpf_object *objects;
53 + struct bpf_link **probe_links;
54 +
55 + netdata_ebpf_histogram_t hread;
56 + netdata_ebpf_histogram_t hwrite;
57 + netdata_ebpf_histogram_t hopen;
58 + netdata_ebpf_histogram_t hsync;
59 +
60 + uint32_t flags;
61 + uint32_t enabled;
62 +
63 + ebpf_data_t kernel_info;
64 + ebpf_addresses_t addresses;
65 +} ebpf_filesystem_partitions_t;
66 +
67 +extern void *ebpf_filesystem_thread(void *ptr);
68 +extern struct config fs_config;
69 +
70 +#endif /* NETDATA_EBPF_FILESYSTEM_H */
libnetdata/ebpf/ebpf.c
+120
@@ -522,3 +522,123 @@ void ebpf_update_module(ebpf_module_t *em)
522
523 ebpf_update_module_using_config(em);
524 }
525 +
526 +//----------------------------------------------------------------------------------------------------------------------
527 +
528 +/**
529 + * Load Address
530 + *
531 + * Helper used to get address from /proc/kallsym
532 + *
533 + * @param fa address structure
534 + * @param fd file descriptor loaded inside kernel.
535 + */
536 +void ebpf_load_addresses(ebpf_addresses_t *fa, int fd)
537 +{
538 + if (fa->addr)
539 + return ;
540 +
541 + procfile *ff = procfile_open("/proc/kallsyms", " \t:", PROCFILE_FLAG_DEFAULT);
542 + if (!ff)
543 + return;
544 +
545 + ff = procfile_readall(ff);
546 + if (!ff)
547 + return;
548 +
549 + fa->hash = simple_hash(fa->function);
550 +
551 + size_t lines = procfile_lines(ff), l;
552 + for(l = 0; l < lines ;l++) {
553 + char *fcnt = procfile_lineword(ff, l, 2);
554 + uint32_t hash = simple_hash(fcnt);
555 + if (fa->hash == hash && !strcmp(fcnt, fa->function)) {
556 + char addr[128];
557 + snprintf(addr, 127, "0x%s", procfile_lineword(ff, l, 0));
558 + fa->addr = (unsigned long) strtoul(addr, NULL, 16);
559 + uint32_t key = 0;
560 + bpf_map_update_elem(fd, &key, &fa->addr, BPF_ANY);
561 + }
562 + }
563 +
564 + procfile_close(ff);
565 +}
566 +
567 +//----------------------------------------------------------------------------------------------------------------------
568 +
569 +/**
570 + * Fill Algorithms
571 + *
572 + * Set one unique dimension for all vector position.
573 + *
574 + * @param algorithms the output vector
575 + * @param length number of elements of algorithms vector
576 + * @param algortihm algorithm used on charts.
577 +*/
578 +void ebpf_fill_algorithms(int *algorithms, size_t length, int algorithm)
579 +{
580 + size_t i;
581 + for (i = 0; i < length; i++) {
582 + algorithms[i] = algorithm;
583 + }
584 +}
585 +
586 +/**
587 + * Fill Histogram dimension
588 + *
589 + * Fill the histogram dimension with the specified ranges
590 + */
591 +char **ebpf_fill_histogram_dimension(size_t maximum)
592 +{
593 + char *dimensions[] = { "us", "ms", "s"};
594 + int previous_dim = 0, current_dim = 0;
595 + uint32_t previous_level = 1000, current_level = 1000;
596 + uint32_t previous_divisor = 1, current_divisor = 1;
597 + uint32_t current = 1, previous = 0;
598 + uint32_t selector;
599 + char **out = callocz(maximum, sizeof(char *));
600 + char range[128];
601 + size_t end = maximum - 1;
602 + for (selector = 0; selector < end; selector++) {
603 + snprintf(range, 127, "%u%s->%u%s", previous/previous_divisor, dimensions[previous_dim],
604 + current/current_divisor, dimensions[current_dim]);
605 + out[selector] = strdupz(range);
606 + previous = current;
607 + current <<= 1;
608 +
609 + if (previous_dim != 2 && previous > previous_level) {
610 + previous_dim++;
611 +
612 + previous_divisor *= 1000;
613 + previous_level *= 1000;
614 + }
615 +
616 + if (current_dim != 2 && current > current_level) {
617 + current_dim++;
618 +
619 + current_divisor *= 1000;
620 + current_level *= 1000;
621 + }
622 + }
623 + snprintf(range, 127, "%u%s->+Inf", previous/previous_divisor, dimensions[previous_dim]);
624 + out[selector] = strdupz(range);
625 +
626 + return out;
627 +}
628 +
629 +/**
630 + * Histogram dimension cleanup
631 + *
632 + * Cleanup dimensions allocated with function ebpf_fill_histogram_dimension
633 + *
634 + * @param ptr
635 + * @param length
636 + */
637 +void ebpf_histogram_dimension_cleanup(char **ptr, size_t length)
638 +{
639 + size_t i;
640 + for (i = 0; i < length; i++) {
641 + freez(ptr[i]);
642 + }
643 + freez(ptr);
644 +}
libnetdata/ebpf/ebpf.h
+13
@@ -5,6 +5,7 @@
5
6 #include <bpf/bpf.h>
7 #include <bpf/libbpf.h>
8 +#include <stdlib.h> // Necessary for stdtoul
9
10 #define NETDATA_DEBUGFS "/sys/kernel/debug/tracing/"
11 #define NETDATA_KALLSYMS "/proc/kallsyms"
@@ -87,6 +88,14 @@
88 #define VERSION_STRING_LEN 256
89 #define EBPF_KERNEL_REJECT_LIST_FILE "ebpf_kernel_reject_list.txt"
90
91 +
92 +typedef struct ebpf_addresses {
93 + char *function;
94 + uint32_t hash;
95 + // We use long as address, because it matches system length
96 + unsigned long addr;
97 +} ebpf_addresses_t;
98 +
99 extern char *ebpf_user_config_dir;
100 extern char *ebpf_stock_config_dir;
101
@@ -154,5 +163,9 @@ extern int ebpf_load_config(struct config *config, char *filename);
163 extern void ebpf_update_module_using_config(ebpf_module_t *modules);
164 extern void ebpf_update_module(ebpf_module_t *em);
165 extern void ebpf_update_names(ebpf_specify_name_t *opt, ebpf_module_t *em);
166 +extern void ebpf_load_addresses(ebpf_addresses_t *fa, int fd);
167 +extern void ebpf_fill_algorithms(int *algorithms, size_t length, int algorithm);
168 +extern char **ebpf_fill_histogram_dimension(size_t maximum);
169 +extern void ebpf_histogram_dimension_cleanup(char **ptr, size_t length);
170
171 #endif /* NETDATA_EBPF_H */
packaging/ebpf.checksums
+3 -3
@@ -1,3 +1,3 @@
1 -49c50bdca3389a7a5df3c2753d9ed790983fae1350e1ee95bdaa5bc36e8ed398 netdata-kernel-collector-glibc-v0.6.6.tar.xz
2 -3cfe2ab7ebec5e508a4e769d79e97a8bdfe03e1d0f2147320643dcae2a3b525a netdata-kernel-collector-musl-v0.6.6.tar.xz
3 -66c04aa186540dc27317265bad5ee9ce4eec962c176d3cb04f4d56032171e566 netdata-kernel-collector-static-v0.6.6.tar.xz
1 +f712ebedd6f052d1bfd4bf26ef50903d34db0fdb83dd48abf54eb7b00f29587c netdata-kernel-collector-glibc-v0.6.8.tar.xz
2 +0e34392c5928cc5a8c66348b6131186e2e9d35237d9ac303bae7cbf684b888fe netdata-kernel-collector-musl-v0.6.8.tar.xz
3 +29f5d13f0b894a6933142dc0677cf269b9114e7f03e8ff4192e560c6c7313631 netdata-kernel-collector-static-v0.6.8.tar.xz
packaging/ebpf.version
+1 -1
@@ -1 +1 @@
1 -v0.6.6
1 +v0.6.8
web/gui/dashboard_info.js
+16
@@ -3460,6 +3460,22 @@ netdataDashboard.context = {
3460 info: 'Failed calls to functions <code>vfs_create</code>.'
3461 },
3462
3463 + 'filesystem.ext4_read_latency': {
3464 + info: 'Latency is the time it takes for an event to be completed. Netdata is attaching a kprobe for when the function <code>ext4_file_read_iter</code> is called and another for when it finishes the execution. We calculate the difference between the calling and return times, we get the logarithmic for the final result and we sum one value to the respective bin. Based on the eBPF <a href="http://www.brendangregg.com/blog/2016-10-06/linux-bcc-ext4dist-ext4slower.html" target="_blank">ext4dist</a> from BCC tools.'
3465 + },
3466 +
3467 + 'filesystem.ext4_write_latency': {
3468 + info: 'Latency is the time it takes for an event to be completed. Netdata is attaching a kprobe for when the function <code>ext4_file_write_iter</code> is called and another for when it finishes the execution. We calculate the difference between the calling and return times, we get the logarithmic for the final result and we sum one value to the respective bin. Based on the eBPF <a href="http://www.brendangregg.com/blog/2016-10-06/linux-bcc-ext4dist-ext4slower.html" target="_blank">ext4dist</a> from BCC tools.'
3469 + },
3470 +
3471 + 'filesystem.ext4_open_latency': {
3472 + info: 'Latency is the time it takes for an event to be completed. Netdata is attaching a kprobe for when the function <code>ext4_file_open</code> is called and another for when it finishes the execution. We calculate the difference between the calling and return times, we get the logarithmic for the final result and we sum one value to the respective bin. Based on the eBPF <a href="http://www.brendangregg.com/blog/2016-10-06/linux-bcc-ext4dist-ext4slower.html" target="_blank">ext4dist</a> from BCC tools.'
3473 + },
3474 +
3475 + 'filesystem.ext4_sync_latency': {
3476 + info: 'Latency is the time it takes for an event to be completed. Netdata is attaching a kprobe for when the function <code>ext4_sync_file</code> is called and another for when it finishes the execution. We calculate the difference between the calling and return times, we get the logarithmic for the final result and we sum one value to the respective bin. Based on the eBPF <a href="http://www.brendangregg.com/blog/2016-10-06/linux-bcc-ext4dist-ext4slower.html" target="_blank">ext4dist</a> from BCC tools.'
3477 + },
3478 +
3479 // ------------------------------------------------------------------------
3480 // eBPF
3481