ebpf_vfs.c 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include <sys/resource.h>
  3. #include "ebpf.h"
  4. #include "ebpf_vfs.h"
  5. static char *vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_END] = { "delete", "read", "write",
  6. "fsync", "open", "create" };
  7. static char *vfs_id_names[NETDATA_KEY_PUBLISH_VFS_END] = { "vfs_unlink", "vfs_read", "vfs_write",
  8. "vfs_fsync", "vfs_open", "vfs_create"};
  9. static netdata_idx_t *vfs_hash_values = NULL;
  10. static netdata_syscall_stat_t vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_END];
  11. static netdata_publish_syscall_t vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_END];
  12. netdata_publish_vfs_t **vfs_pid = NULL;
  13. netdata_publish_vfs_t *vfs_vector = NULL;
  14. static ebpf_local_maps_t vfs_maps[] = {{.name = "tbl_vfs_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  15. .user_input = 0, .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  16. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  17. {.name = "tbl_vfs_stats", .internal_input = NETDATA_VFS_COUNTER,
  18. .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
  19. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  20. {.name = "vfs_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  21. .user_input = 0,
  22. .type = NETDATA_EBPF_MAP_CONTROLLER,
  23. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  24. {.name = NULL, .internal_input = 0, .user_input = 0}};
  25. struct config vfs_config = { .first_section = NULL,
  26. .last_section = NULL,
  27. .mutex = NETDATA_MUTEX_INITIALIZER,
  28. .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  29. .rwlock = AVL_LOCK_INITIALIZER } };
  30. static struct bpf_object *objects = NULL;
  31. static struct bpf_link **probe_links = NULL;
  32. struct netdata_static_thread vfs_threads = {"VFS KERNEL",
  33. NULL, NULL, 1, NULL,
  34. NULL, NULL};
  35. static int read_thread_closed = 1;
  36. /*****************************************************************
  37. *
  38. * FUNCTIONS TO CLOSE THE THREAD
  39. *
  40. *****************************************************************/
  41. /**
  42. * Clean up the main thread.
  43. *
  44. * @param ptr thread data.
  45. **/
  46. static void ebpf_vfs_cleanup(void *ptr)
  47. {
  48. ebpf_module_t *em = (ebpf_module_t *)ptr;
  49. if (!em->enabled)
  50. return;
  51. heartbeat_t hb;
  52. heartbeat_init(&hb);
  53. uint32_t tick = 50 * USEC_PER_MS;
  54. while (!read_thread_closed) {
  55. usec_t dt = heartbeat_next(&hb, tick);
  56. UNUSED(dt);
  57. }
  58. freez(vfs_hash_values);
  59. freez(vfs_vector);
  60. if (probe_links) {
  61. struct bpf_program *prog;
  62. size_t i = 0 ;
  63. bpf_object__for_each_program(prog, objects) {
  64. bpf_link__destroy(probe_links[i]);
  65. i++;
  66. }
  67. if (objects)
  68. bpf_object__close(objects);
  69. }
  70. }
  71. /*****************************************************************
  72. *
  73. * FUNCTIONS WITH THE MAIN LOOP
  74. *
  75. *****************************************************************/
  76. /**
  77. * Send data to Netdata calling auxiliary functions.
  78. *
  79. * @param em the structure with thread information
  80. */
  81. static void ebpf_vfs_send_data(ebpf_module_t *em)
  82. {
  83. netdata_publish_vfs_common_t pvc;
  84. pvc.write = (long)vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_WRITE].bytes;
  85. pvc.read = (long)vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_READ].bytes;
  86. write_count_chart(NETDATA_VFS_FILE_CLEAN_COUNT, NETDATA_FILESYSTEM_FAMILY,
  87. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK], 1);
  88. write_count_chart(NETDATA_VFS_FILE_IO_COUNT, NETDATA_FILESYSTEM_FAMILY,
  89. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ], 2);
  90. if (em->mode < MODE_ENTRY) {
  91. write_err_chart(NETDATA_VFS_FILE_ERR_COUNT, NETDATA_FILESYSTEM_FAMILY,
  92. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ], 2);
  93. }
  94. write_io_chart(NETDATA_VFS_IO_FILE_BYTES, NETDATA_FILESYSTEM_FAMILY, vfs_id_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
  95. (long long)pvc.write, vfs_id_names[NETDATA_KEY_PUBLISH_VFS_READ], (long long)pvc.read);
  96. write_count_chart(NETDATA_VFS_FSYNC, NETDATA_FILESYSTEM_FAMILY,
  97. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC], 1);
  98. if (em->mode < MODE_ENTRY) {
  99. write_err_chart(NETDATA_VFS_FSYNC_ERR, NETDATA_FILESYSTEM_FAMILY,
  100. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC], 1);
  101. }
  102. write_count_chart(NETDATA_VFS_OPEN, NETDATA_FILESYSTEM_FAMILY,
  103. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN], 1);
  104. if (em->mode < MODE_ENTRY) {
  105. write_err_chart(NETDATA_VFS_OPEN_ERR, NETDATA_FILESYSTEM_FAMILY,
  106. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN], 1);
  107. }
  108. write_count_chart(NETDATA_VFS_CREATE, NETDATA_FILESYSTEM_FAMILY,
  109. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE], 1);
  110. if (em->mode < MODE_ENTRY) {
  111. write_err_chart(
  112. NETDATA_VFS_CREATE_ERR,
  113. NETDATA_FILESYSTEM_FAMILY,
  114. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  115. 1);
  116. }
  117. }
  118. /**
  119. * Read the hash table and store data to allocated vectors.
  120. */
  121. static void read_global_table()
  122. {
  123. uint64_t idx;
  124. netdata_idx_t res[NETDATA_VFS_COUNTER];
  125. netdata_idx_t *val = vfs_hash_values;
  126. int fd = vfs_maps[NETDATA_VFS_ALL].map_fd;
  127. for (idx = 0; idx < NETDATA_VFS_COUNTER; idx++) {
  128. uint64_t total = 0;
  129. if (!bpf_map_lookup_elem(fd, &idx, val)) {
  130. int i;
  131. int end = ebpf_nprocs;
  132. for (i = 0; i < end; i++)
  133. total += val[i];
  134. }
  135. res[idx] = total;
  136. }
  137. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].ncall = res[NETDATA_KEY_CALLS_VFS_UNLINK];
  138. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].ncall = res[NETDATA_KEY_CALLS_VFS_READ] +
  139. res[NETDATA_KEY_CALLS_VFS_READV];
  140. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].ncall = res[NETDATA_KEY_CALLS_VFS_WRITE] +
  141. res[NETDATA_KEY_CALLS_VFS_WRITEV];
  142. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].ncall = res[NETDATA_KEY_CALLS_VFS_FSYNC];
  143. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].ncall = res[NETDATA_KEY_CALLS_VFS_OPEN];
  144. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].ncall = res[NETDATA_KEY_CALLS_VFS_CREATE];
  145. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].nerr = res[NETDATA_KEY_ERROR_VFS_UNLINK];
  146. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].nerr = res[NETDATA_KEY_ERROR_VFS_READ] +
  147. res[NETDATA_KEY_ERROR_VFS_READV];
  148. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].nerr = res[NETDATA_KEY_ERROR_VFS_WRITE] +
  149. res[NETDATA_KEY_ERROR_VFS_WRITEV];
  150. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].nerr = res[NETDATA_KEY_ERROR_VFS_FSYNC];
  151. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].nerr = res[NETDATA_KEY_ERROR_VFS_OPEN];
  152. vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].nerr = res[NETDATA_KEY_ERROR_VFS_CREATE];
  153. vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_WRITE].bytes = (uint64_t)res[NETDATA_KEY_BYTES_VFS_WRITE] +
  154. (uint64_t)res[NETDATA_KEY_BYTES_VFS_WRITEV];
  155. vfs_aggregated_data[NETDATA_KEY_PUBLISH_VFS_READ].bytes = (uint64_t)res[NETDATA_KEY_BYTES_VFS_READ] +
  156. (uint64_t)res[NETDATA_KEY_BYTES_VFS_READV];
  157. }
  158. /**
  159. * Sum PIDs
  160. *
  161. * Sum values for all targets.
  162. *
  163. * @param swap output structure
  164. * @param root link list with structure to be used
  165. */
  166. static void ebpf_vfs_sum_pids(netdata_publish_vfs_t *vfs, struct pid_on_target *root)
  167. {
  168. netdata_publish_vfs_t accumulator;
  169. memset(&accumulator, 0, sizeof(accumulator));
  170. while (root) {
  171. int32_t pid = root->pid;
  172. netdata_publish_vfs_t *w = vfs_pid[pid];
  173. if (w) {
  174. accumulator.write_call += w->write_call;
  175. accumulator.writev_call += w->writev_call;
  176. accumulator.read_call += w->read_call;
  177. accumulator.readv_call += w->readv_call;
  178. accumulator.unlink_call += w->unlink_call;
  179. accumulator.fsync_call += w->fsync_call;
  180. accumulator.open_call += w->open_call;
  181. accumulator.create_call += w->create_call;
  182. accumulator.write_bytes += w->write_bytes;
  183. accumulator.writev_bytes += w->writev_bytes;
  184. accumulator.read_bytes += w->read_bytes;
  185. accumulator.readv_bytes += w->readv_bytes;
  186. accumulator.write_err += w->write_err;
  187. accumulator.writev_err += w->writev_err;
  188. accumulator.read_err += w->read_err;
  189. accumulator.readv_err += w->readv_err;
  190. accumulator.unlink_err += w->unlink_err;
  191. accumulator.fsync_err += w->fsync_err;
  192. accumulator.open_err += w->open_err;
  193. accumulator.create_err += w->create_err;
  194. }
  195. root = root->next;
  196. }
  197. // These conditions were added, because we are using incremental algorithm
  198. vfs->write_call = (accumulator.write_call >= vfs->write_call) ? accumulator.write_call : vfs->write_call;
  199. vfs->writev_call = (accumulator.writev_call >= vfs->writev_call) ? accumulator.writev_call : vfs->writev_call;
  200. vfs->read_call = (accumulator.read_call >= vfs->read_call) ? accumulator.read_call : vfs->read_call;
  201. vfs->readv_call = (accumulator.readv_call >= vfs->readv_call) ? accumulator.readv_call : vfs->readv_call;
  202. vfs->unlink_call = (accumulator.unlink_call >= vfs->unlink_call) ? accumulator.unlink_call : vfs->unlink_call;
  203. vfs->fsync_call = (accumulator.fsync_call >= vfs->fsync_call) ? accumulator.fsync_call : vfs->fsync_call;
  204. vfs->open_call = (accumulator.open_call >= vfs->open_call) ? accumulator.open_call : vfs->open_call;
  205. vfs->create_call = (accumulator.create_call >= vfs->create_call) ? accumulator.create_call : vfs->create_call;
  206. vfs->write_bytes = (accumulator.write_bytes >= vfs->write_bytes) ? accumulator.write_bytes : vfs->write_bytes;
  207. vfs->writev_bytes = (accumulator.writev_bytes >= vfs->writev_bytes) ? accumulator.writev_bytes : vfs->writev_bytes;
  208. vfs->read_bytes = (accumulator.read_bytes >= vfs->read_bytes) ? accumulator.read_bytes : vfs->read_bytes;
  209. vfs->readv_bytes = (accumulator.readv_bytes >= vfs->readv_bytes) ? accumulator.readv_bytes : vfs->readv_bytes;
  210. vfs->write_err = (accumulator.write_err >= vfs->write_err) ? accumulator.write_err : vfs->write_err;
  211. vfs->writev_err = (accumulator.writev_err >= vfs->writev_err) ? accumulator.writev_err : vfs->writev_err;
  212. vfs->read_err = (accumulator.read_err >= vfs->read_err) ? accumulator.read_err : vfs->read_err;
  213. vfs->readv_err = (accumulator.readv_err >= vfs->readv_err) ? accumulator.readv_err : vfs->readv_err;
  214. vfs->unlink_err = (accumulator.unlink_err >= vfs->unlink_err) ? accumulator.unlink_err : vfs->unlink_err;
  215. vfs->fsync_err = (accumulator.fsync_err >= vfs->fsync_err) ? accumulator.fsync_err : vfs->fsync_err;
  216. vfs->open_err = (accumulator.open_err >= vfs->open_err) ? accumulator.open_err : vfs->open_err;
  217. vfs->create_err = (accumulator.create_err >= vfs->create_err) ? accumulator.create_err : vfs->create_err;
  218. }
  219. /**
  220. * Send data to Netdata calling auxiliary functions.
  221. *
  222. * @param em the structure with thread information
  223. * @param root the target list.
  224. */
  225. void ebpf_vfs_send_apps_data(ebpf_module_t *em, struct target *root)
  226. {
  227. struct target *w;
  228. for (w = root; w; w = w->next) {
  229. if (unlikely(w->exposed && w->processes)) {
  230. ebpf_vfs_sum_pids(&w->vfs, w->root_pid);
  231. }
  232. }
  233. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_FILE_DELETED);
  234. for (w = root; w; w = w->next) {
  235. if (unlikely(w->exposed && w->processes)) {
  236. write_chart_dimension(w->name, w->vfs.unlink_call);
  237. }
  238. }
  239. write_end_chart();
  240. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
  241. for (w = root; w; w = w->next) {
  242. if (unlikely(w->exposed && w->processes)) {
  243. write_chart_dimension(w->name, w->vfs.write_call + w->vfs.writev_call);
  244. }
  245. }
  246. write_end_chart();
  247. if (em->mode < MODE_ENTRY) {
  248. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
  249. for (w = root; w; w = w->next) {
  250. if (unlikely(w->exposed && w->processes)) {
  251. write_chart_dimension(w->name, w->vfs.write_err + w->vfs.writev_err);
  252. }
  253. }
  254. write_end_chart();
  255. }
  256. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
  257. for (w = root; w; w = w->next) {
  258. if (unlikely(w->exposed && w->processes)) {
  259. write_chart_dimension(w->name, w->vfs.read_call + w->vfs.readv_call);
  260. }
  261. }
  262. write_end_chart();
  263. if (em->mode < MODE_ENTRY) {
  264. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
  265. for (w = root; w; w = w->next) {
  266. if (unlikely(w->exposed && w->processes)) {
  267. write_chart_dimension(w->name, w->vfs.read_err + w->vfs.readv_err);
  268. }
  269. }
  270. write_end_chart();
  271. }
  272. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
  273. for (w = root; w; w = w->next) {
  274. if (unlikely(w->exposed && w->processes)) {
  275. write_chart_dimension(w->name, w->vfs.write_bytes + w->vfs.writev_bytes);
  276. }
  277. }
  278. write_end_chart();
  279. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
  280. for (w = root; w; w = w->next) {
  281. if (unlikely(w->exposed && w->processes)) {
  282. write_chart_dimension(w->name, w->vfs.read_bytes + w->vfs.readv_bytes);
  283. }
  284. }
  285. write_end_chart();
  286. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC);
  287. for (w = root; w; w = w->next) {
  288. if (unlikely(w->exposed && w->processes)) {
  289. write_chart_dimension(w->name, w->vfs.fsync_call);
  290. }
  291. }
  292. write_end_chart();
  293. if (em->mode < MODE_ENTRY) {
  294. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
  295. for (w = root; w; w = w->next) {
  296. if (unlikely(w->exposed && w->processes)) {
  297. write_chart_dimension(w->name, w->vfs.fsync_err);
  298. }
  299. }
  300. write_end_chart();
  301. }
  302. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN);
  303. for (w = root; w; w = w->next) {
  304. if (unlikely(w->exposed && w->processes)) {
  305. write_chart_dimension(w->name, w->vfs.open_call);
  306. }
  307. }
  308. write_end_chart();
  309. if (em->mode < MODE_ENTRY) {
  310. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
  311. for (w = root; w; w = w->next) {
  312. if (unlikely(w->exposed && w->processes)) {
  313. write_chart_dimension(w->name, w->vfs.open_err);
  314. }
  315. }
  316. write_end_chart();
  317. }
  318. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE);
  319. for (w = root; w; w = w->next) {
  320. if (unlikely(w->exposed && w->processes)) {
  321. write_chart_dimension(w->name, w->vfs.create_call);
  322. }
  323. }
  324. write_end_chart();
  325. if (em->mode < MODE_ENTRY) {
  326. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
  327. for (w = root; w; w = w->next) {
  328. if (unlikely(w->exposed && w->processes)) {
  329. write_chart_dimension(w->name, w->vfs.create_err);
  330. }
  331. }
  332. write_end_chart();
  333. }
  334. }
  335. /**
  336. * Apps Accumulator
  337. *
  338. * Sum all values read from kernel and store in the first address.
  339. *
  340. * @param out the vector with read values.
  341. */
  342. static void vfs_apps_accumulator(netdata_publish_vfs_t *out)
  343. {
  344. int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
  345. netdata_publish_vfs_t *total = &out[0];
  346. for (i = 1; i < end; i++) {
  347. netdata_publish_vfs_t *w = &out[i];
  348. total->write_call += w->write_call;
  349. total->writev_call += w->writev_call;
  350. total->read_call += w->read_call;
  351. total->readv_call += w->readv_call;
  352. total->unlink_call += w->unlink_call;
  353. total->write_bytes += w->write_bytes;
  354. total->writev_bytes += w->writev_bytes;
  355. total->read_bytes += w->read_bytes;
  356. total->readv_bytes += w->readv_bytes;
  357. total->write_err += w->write_err;
  358. total->writev_err += w->writev_err;
  359. total->read_err += w->read_err;
  360. total->readv_err += w->readv_err;
  361. total->unlink_err += w->unlink_err;
  362. }
  363. }
  364. /**
  365. * Fill PID
  366. *
  367. * Fill PID structures
  368. *
  369. * @param current_pid pid that we are collecting data
  370. * @param out values read from hash tables;
  371. */
  372. static void vfs_fill_pid(uint32_t current_pid, netdata_publish_vfs_t *publish)
  373. {
  374. netdata_publish_vfs_t *curr = vfs_pid[current_pid];
  375. if (!curr) {
  376. curr = callocz(1, sizeof(netdata_publish_vfs_t));
  377. vfs_pid[current_pid] = curr;
  378. }
  379. memcpy(curr, &publish[0], sizeof(netdata_publish_vfs_t));
  380. }
  381. /**
  382. * Read the hash table and store data to allocated vectors.
  383. */
  384. static void ebpf_vfs_read_apps()
  385. {
  386. struct pid_stat *pids = root_of_pids;
  387. netdata_publish_vfs_t *vv = vfs_vector;
  388. int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
  389. size_t length = sizeof(netdata_publish_vfs_t) * ebpf_nprocs;
  390. while (pids) {
  391. uint32_t key = pids->pid;
  392. if (bpf_map_lookup_elem(fd, &key, vv)) {
  393. pids = pids->next;
  394. continue;
  395. }
  396. vfs_apps_accumulator(vv);
  397. vfs_fill_pid(key, vv);
  398. // We are cleaning to avoid passing data read from one process to other.
  399. memset(vv, 0, length);
  400. pids = pids->next;
  401. }
  402. }
  403. /**
  404. * Update cgroup
  405. *
  406. * Update cgroup data based in
  407. */
  408. static void read_update_vfs_cgroup()
  409. {
  410. ebpf_cgroup_target_t *ect ;
  411. netdata_publish_vfs_t *vv = vfs_vector;
  412. int fd = vfs_maps[NETDATA_VFS_PID].map_fd;
  413. size_t length = sizeof(netdata_publish_vfs_t) * ebpf_nprocs;
  414. pthread_mutex_lock(&mutex_cgroup_shm);
  415. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  416. struct pid_on_target2 *pids;
  417. for (pids = ect->pids; pids; pids = pids->next) {
  418. int pid = pids->pid;
  419. netdata_publish_vfs_t *out = &pids->vfs;
  420. if (likely(vfs_pid) && vfs_pid[pid]) {
  421. netdata_publish_vfs_t *in = vfs_pid[pid];
  422. memcpy(out, in, sizeof(netdata_publish_vfs_t));
  423. } else {
  424. memset(vv, 0, length);
  425. if (!bpf_map_lookup_elem(fd, &pid, vv)) {
  426. vfs_apps_accumulator(vv);
  427. memcpy(out, vv, sizeof(netdata_publish_vfs_t));
  428. }
  429. }
  430. }
  431. }
  432. pthread_mutex_unlock(&mutex_cgroup_shm);
  433. }
  434. /**
  435. * VFS read hash
  436. *
  437. * This is the thread callback.
  438. * This thread is necessary, because we cannot freeze the whole plugin to read the data.
  439. *
  440. * @param ptr It is a NULL value for this thread.
  441. *
  442. * @return It always returns NULL.
  443. */
  444. void *ebpf_vfs_read_hash(void *ptr)
  445. {
  446. read_thread_closed = 0;
  447. heartbeat_t hb;
  448. heartbeat_init(&hb);
  449. ebpf_module_t *em = (ebpf_module_t *)ptr;
  450. usec_t step = NETDATA_LATENCY_VFS_SLEEP_MS * em->update_every;
  451. while (!close_ebpf_plugin) {
  452. usec_t dt = heartbeat_next(&hb, step);
  453. (void)dt;
  454. read_global_table();
  455. }
  456. read_thread_closed = 1;
  457. return NULL;
  458. }
  459. /**
  460. * Sum PIDs
  461. *
  462. * Sum values for all targets.
  463. *
  464. * @param vfs structure used to store data
  465. * @param pids input data
  466. */
  467. static void ebpf_vfs_sum_cgroup_pids(netdata_publish_vfs_t *vfs, struct pid_on_target2 *pids)
  468. {
  469. netdata_publish_vfs_t accumulator;
  470. memset(&accumulator, 0, sizeof(accumulator));
  471. while (pids) {
  472. netdata_publish_vfs_t *w = &pids->vfs;
  473. accumulator.write_call += w->write_call;
  474. accumulator.writev_call += w->writev_call;
  475. accumulator.read_call += w->read_call;
  476. accumulator.readv_call += w->readv_call;
  477. accumulator.unlink_call += w->unlink_call;
  478. accumulator.fsync_call += w->fsync_call;
  479. accumulator.open_call += w->open_call;
  480. accumulator.create_call += w->create_call;
  481. accumulator.write_bytes += w->write_bytes;
  482. accumulator.writev_bytes += w->writev_bytes;
  483. accumulator.read_bytes += w->read_bytes;
  484. accumulator.readv_bytes += w->readv_bytes;
  485. accumulator.write_err += w->write_err;
  486. accumulator.writev_err += w->writev_err;
  487. accumulator.read_err += w->read_err;
  488. accumulator.readv_err += w->readv_err;
  489. accumulator.unlink_err += w->unlink_err;
  490. accumulator.fsync_err += w->fsync_err;
  491. accumulator.open_err += w->open_err;
  492. accumulator.create_err += w->create_err;
  493. pids = pids->next;
  494. }
  495. // These conditions were added, because we are using incremental algorithm
  496. vfs->write_call = (accumulator.write_call >= vfs->write_call) ? accumulator.write_call : vfs->write_call;
  497. vfs->writev_call = (accumulator.writev_call >= vfs->writev_call) ? accumulator.writev_call : vfs->writev_call;
  498. vfs->read_call = (accumulator.read_call >= vfs->read_call) ? accumulator.read_call : vfs->read_call;
  499. vfs->readv_call = (accumulator.readv_call >= vfs->readv_call) ? accumulator.readv_call : vfs->readv_call;
  500. vfs->unlink_call = (accumulator.unlink_call >= vfs->unlink_call) ? accumulator.unlink_call : vfs->unlink_call;
  501. vfs->fsync_call = (accumulator.fsync_call >= vfs->fsync_call) ? accumulator.fsync_call : vfs->fsync_call;
  502. vfs->open_call = (accumulator.open_call >= vfs->open_call) ? accumulator.open_call : vfs->open_call;
  503. vfs->create_call = (accumulator.create_call >= vfs->create_call) ? accumulator.create_call : vfs->create_call;
  504. vfs->write_bytes = (accumulator.write_bytes >= vfs->write_bytes) ? accumulator.write_bytes : vfs->write_bytes;
  505. vfs->writev_bytes = (accumulator.writev_bytes >= vfs->writev_bytes) ? accumulator.writev_bytes : vfs->writev_bytes;
  506. vfs->read_bytes = (accumulator.read_bytes >= vfs->read_bytes) ? accumulator.read_bytes : vfs->read_bytes;
  507. vfs->readv_bytes = (accumulator.readv_bytes >= vfs->readv_bytes) ? accumulator.readv_bytes : vfs->readv_bytes;
  508. vfs->write_err = (accumulator.write_err >= vfs->write_err) ? accumulator.write_err : vfs->write_err;
  509. vfs->writev_err = (accumulator.writev_err >= vfs->writev_err) ? accumulator.writev_err : vfs->writev_err;
  510. vfs->read_err = (accumulator.read_err >= vfs->read_err) ? accumulator.read_err : vfs->read_err;
  511. vfs->readv_err = (accumulator.readv_err >= vfs->readv_err) ? accumulator.readv_err : vfs->readv_err;
  512. vfs->unlink_err = (accumulator.unlink_err >= vfs->unlink_err) ? accumulator.unlink_err : vfs->unlink_err;
  513. vfs->fsync_err = (accumulator.fsync_err >= vfs->fsync_err) ? accumulator.fsync_err : vfs->fsync_err;
  514. vfs->open_err = (accumulator.open_err >= vfs->open_err) ? accumulator.open_err : vfs->open_err;
  515. vfs->create_err = (accumulator.create_err >= vfs->create_err) ? accumulator.create_err : vfs->create_err;
  516. }
  517. /**
  518. * Create specific VFS charts
  519. *
  520. * Create charts for cgroup/application.
  521. *
  522. * @param type the chart type.
  523. * @param em the main thread structure.
  524. */
  525. static void ebpf_create_specific_vfs_charts(char *type, ebpf_module_t *em)
  526. {
  527. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED,"Files deleted",
  528. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
  529. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500,
  530. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
  531. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  532. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
  533. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_CONTEXT,
  534. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501,
  535. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
  536. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  537. if (em->mode < MODE_ENTRY) {
  538. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
  539. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
  540. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502,
  541. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
  542. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  543. }
  544. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
  545. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_CONTEXT,
  546. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503,
  547. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  548. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  549. if (em->mode < MODE_ENTRY) {
  550. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
  551. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
  552. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504,
  553. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  554. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  555. }
  556. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
  557. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
  558. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505,
  559. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
  560. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  561. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
  562. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
  563. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506,
  564. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  565. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  566. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls for <code>vfs_fsync</code>",
  567. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_FSYNC_CONTEXT,
  568. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507,
  569. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  570. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  571. if (em->mode < MODE_ENTRY) {
  572. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
  573. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_FSYNC_ERROR_CONTEXT,
  574. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508,
  575. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  576. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  577. }
  578. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls for <code>vfs_open</code>",
  579. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_OPEN_CONTEXT,
  580. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509,
  581. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  582. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  583. if (em->mode < MODE_ENTRY) {
  584. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
  585. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_OPEN_ERROR_CONTEXT,
  586. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510,
  587. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  588. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  589. }
  590. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls for <code>vfs_create</code>",
  591. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_CREATE_CONTEXT,
  592. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511,
  593. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  594. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  595. if (em->mode < MODE_ENTRY) {
  596. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
  597. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_CREATE_ERROR_CONTEXT,
  598. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512,
  599. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  600. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  601. }
  602. }
  603. /**
  604. * Obsolete specific VFS charts
  605. *
  606. * Obsolete charts for cgroup/application.
  607. *
  608. * @param type the chart type.
  609. * @param em the main thread structure.
  610. */
  611. static void ebpf_obsolete_specific_vfs_charts(char *type, ebpf_module_t *em)
  612. {
  613. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_DELETED, "Files deleted",
  614. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  615. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
  616. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500, em->update_every);
  617. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
  618. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  619. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_CONTEXT,
  620. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501, em->update_every);
  621. if (em->mode < MODE_ENTRY) {
  622. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
  623. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  624. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
  625. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502, em->update_every);
  626. }
  627. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
  628. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  629. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_CONTEXT,
  630. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503, em->update_every);
  631. if (em->mode < MODE_ENTRY) {
  632. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
  633. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  634. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
  635. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504, em->update_every);
  636. }
  637. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
  638. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_GROUP,
  639. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
  640. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505, em->update_every);
  641. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
  642. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_GROUP,
  643. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
  644. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506, em->update_every);
  645. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls for <code>vfs_fsync</code>",
  646. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  647. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_FSYNC_CONTEXT,
  648. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507, em->update_every);
  649. if (em->mode < MODE_ENTRY) {
  650. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
  651. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  652. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_FSYNC_ERROR_CONTEXT,
  653. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508, em->update_every);
  654. }
  655. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls for <code>vfs_open</code>",
  656. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  657. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_OPEN_CONTEXT,
  658. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509, em->update_every);
  659. if (em->mode < MODE_ENTRY) {
  660. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
  661. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  662. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_OPEN_ERROR_CONTEXT,
  663. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510, em->update_every);
  664. }
  665. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls for <code>vfs_create</code>",
  666. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  667. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_CREATE_CONTEXT,
  668. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511, em->update_every);
  669. if (em->mode < MODE_ENTRY) {
  670. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
  671. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  672. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_CREATE_ERROR_CONTEXT,
  673. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512, em->update_every);
  674. }
  675. }
  676. /*
  677. * Send specific VFS data
  678. *
  679. * Send data for specific cgroup/apps.
  680. *
  681. * @param type chart type
  682. * @param values structure with values that will be sent to netdata
  683. */
  684. static void ebpf_send_specific_vfs_data(char *type, netdata_publish_vfs_t *values, ebpf_module_t *em)
  685. {
  686. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED);
  687. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].name, (long long)values->unlink_call);
  688. write_end_chart();
  689. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
  690. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
  691. (long long)values->write_call + (long long)values->writev_call);
  692. write_end_chart();
  693. if (em->mode < MODE_ENTRY) {
  694. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
  695. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
  696. (long long)values->write_err + (long long)values->writev_err);
  697. write_end_chart();
  698. }
  699. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
  700. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
  701. (long long)values->read_call + (long long)values->readv_call);
  702. write_end_chart();
  703. if (em->mode < MODE_ENTRY) {
  704. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
  705. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
  706. (long long)values->read_err + (long long)values->readv_err);
  707. write_end_chart();
  708. }
  709. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
  710. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
  711. (long long)values->write_bytes + (long long)values->writev_bytes);
  712. write_end_chart();
  713. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
  714. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
  715. (long long)values->read_bytes + (long long)values->readv_bytes);
  716. write_end_chart();
  717. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC);
  718. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name,
  719. (long long)values->fsync_call);
  720. write_end_chart();
  721. if (em->mode < MODE_ENTRY) {
  722. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
  723. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name,
  724. (long long)values->fsync_err);
  725. write_end_chart();
  726. }
  727. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN);
  728. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name,
  729. (long long)values->open_call);
  730. write_end_chart();
  731. if (em->mode < MODE_ENTRY) {
  732. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
  733. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name,
  734. (long long)values->open_err);
  735. write_end_chart();
  736. }
  737. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE);
  738. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name,
  739. (long long)values->create_call);
  740. write_end_chart();
  741. if (em->mode < MODE_ENTRY) {
  742. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
  743. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name,
  744. (long long)values->create_err);
  745. write_end_chart();
  746. }
  747. }
  748. /**
  749. * Create Systemd Socket Charts
  750. *
  751. * Create charts when systemd is enabled
  752. *
  753. * @param em the main collector structure
  754. **/
  755. static void ebpf_create_systemd_vfs_charts(ebpf_module_t *em)
  756. {
  757. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_DELETED, "Files deleted",
  758. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  759. NETDATA_EBPF_CHART_TYPE_STACKED, 20065,
  760. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_UNLINK_CONTEXT,
  761. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  762. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
  763. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  764. NETDATA_EBPF_CHART_TYPE_STACKED, 20066,
  765. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_WRITE_CONTEXT,
  766. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  767. if (em->mode < MODE_ENTRY) {
  768. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
  769. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  770. NETDATA_EBPF_CHART_TYPE_STACKED, 20067,
  771. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  772. NETDATA_SYSTEMD_VFS_WRITE_ERROR_CONTEXT,
  773. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  774. }
  775. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
  776. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  777. NETDATA_EBPF_CHART_TYPE_STACKED, 20068,
  778. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_READ_CONTEXT,
  779. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  780. if (em->mode < MODE_ENTRY) {
  781. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
  782. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  783. NETDATA_EBPF_CHART_TYPE_STACKED, 20069,
  784. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  785. NETDATA_SYSTEMD_VFS_READ_ERROR_CONTEXT,
  786. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  787. }
  788. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
  789. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP,
  790. NETDATA_EBPF_CHART_TYPE_STACKED, 20070,
  791. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_WRITE_BYTES_CONTEXT,
  792. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  793. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
  794. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP,
  795. NETDATA_EBPF_CHART_TYPE_STACKED, 20071,
  796. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_READ_BYTES_CONTEXT,
  797. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  798. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls to <code>vfs_fsync</code>",
  799. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  800. NETDATA_EBPF_CHART_TYPE_STACKED, 20072,
  801. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_FSYNC_CONTEXT,
  802. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  803. if (em->mode < MODE_ENTRY) {
  804. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
  805. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  806. NETDATA_EBPF_CHART_TYPE_STACKED, 20073,
  807. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_FSYNC_ERROR_CONTEXT,
  808. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  809. }
  810. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls to <code>vfs_open</code>",
  811. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  812. NETDATA_EBPF_CHART_TYPE_STACKED, 20074,
  813. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_OPEN_CONTEXT,
  814. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  815. if (em->mode < MODE_ENTRY) {
  816. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
  817. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  818. NETDATA_EBPF_CHART_TYPE_STACKED, 20075,
  819. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_OPEN_ERROR_CONTEXT,
  820. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  821. }
  822. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls to <code>vfs_create</code>",
  823. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  824. NETDATA_EBPF_CHART_TYPE_STACKED, 20076,
  825. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_CREATE_CONTEXT,
  826. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  827. if (em->mode < MODE_ENTRY) {
  828. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
  829. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  830. NETDATA_EBPF_CHART_TYPE_STACKED, 20077,
  831. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_CREATE_ERROR_CONTEXT,
  832. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  833. }
  834. }
  835. /**
  836. * Send Systemd charts
  837. *
  838. * Send collected data to Netdata.
  839. *
  840. * @param em the main collector structure
  841. *
  842. * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
  843. * otherwise function returns 1 to avoid chart recreation
  844. */
  845. static int ebpf_send_systemd_vfs_charts(ebpf_module_t *em)
  846. {
  847. int ret = 1;
  848. ebpf_cgroup_target_t *ect;
  849. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_DELETED);
  850. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  851. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  852. write_chart_dimension(ect->name, ect->publish_systemd_vfs.unlink_call);
  853. } else
  854. ret = 0;
  855. }
  856. write_end_chart();
  857. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
  858. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  859. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  860. write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_call +
  861. ect->publish_systemd_vfs.writev_call);
  862. }
  863. }
  864. write_end_chart();
  865. if (em->mode < MODE_ENTRY) {
  866. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
  867. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  868. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  869. write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_err +
  870. ect->publish_systemd_vfs.writev_err);
  871. }
  872. }
  873. write_end_chart();
  874. }
  875. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
  876. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  877. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  878. write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_call +
  879. ect->publish_systemd_vfs.readv_call);
  880. }
  881. }
  882. write_end_chart();
  883. if (em->mode < MODE_ENTRY) {
  884. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
  885. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  886. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  887. write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_err +
  888. ect->publish_systemd_vfs.readv_err);
  889. }
  890. }
  891. write_end_chart();
  892. }
  893. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
  894. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  895. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  896. write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_bytes +
  897. ect->publish_systemd_vfs.writev_bytes);
  898. }
  899. }
  900. write_end_chart();
  901. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
  902. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  903. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  904. write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_bytes +
  905. ect->publish_systemd_vfs.readv_bytes);
  906. }
  907. }
  908. write_end_chart();
  909. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC);
  910. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  911. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  912. write_chart_dimension(ect->name, ect->publish_systemd_vfs.fsync_call);
  913. }
  914. }
  915. write_end_chart();
  916. if (em->mode < MODE_ENTRY) {
  917. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
  918. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  919. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  920. write_chart_dimension(ect->name, ect->publish_systemd_vfs.fsync_err);
  921. }
  922. }
  923. write_end_chart();
  924. }
  925. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN);
  926. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  927. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  928. write_chart_dimension(ect->name, ect->publish_systemd_vfs.open_call);
  929. }
  930. }
  931. write_end_chart();
  932. if (em->mode < MODE_ENTRY) {
  933. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
  934. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  935. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  936. write_chart_dimension(ect->name, ect->publish_systemd_vfs.open_err);
  937. }
  938. }
  939. write_end_chart();
  940. }
  941. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE);
  942. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  943. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  944. write_chart_dimension(ect->name, ect->publish_systemd_vfs.create_call);
  945. }
  946. }
  947. write_end_chart();
  948. if (em->mode < MODE_ENTRY) {
  949. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
  950. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  951. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  952. write_chart_dimension(ect->name, ect->publish_systemd_vfs.create_err);
  953. }
  954. }
  955. write_end_chart();
  956. }
  957. return ret;
  958. }
  959. /**
  960. * Send data to Netdata calling auxiliary functions.
  961. *
  962. * @param em the main collector structure
  963. */
  964. static void ebpf_vfs_send_cgroup_data(ebpf_module_t *em)
  965. {
  966. if (!ebpf_cgroup_pids)
  967. return;
  968. pthread_mutex_lock(&mutex_cgroup_shm);
  969. ebpf_cgroup_target_t *ect;
  970. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  971. ebpf_vfs_sum_cgroup_pids(&ect->publish_systemd_vfs, ect->pids);
  972. }
  973. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  974. if (has_systemd) {
  975. static int systemd_charts = 0;
  976. if (!systemd_charts) {
  977. ebpf_create_systemd_vfs_charts(em);
  978. systemd_charts = 1;
  979. }
  980. systemd_charts = ebpf_send_systemd_vfs_charts(em);
  981. }
  982. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  983. if (ect->systemd)
  984. continue;
  985. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) && ect->updated) {
  986. ebpf_create_specific_vfs_charts(ect->name, em);
  987. ect->flags |= NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
  988. }
  989. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) {
  990. if (ect->updated) {
  991. ebpf_send_specific_vfs_data(ect->name, &ect->publish_systemd_vfs, em);
  992. } else {
  993. ebpf_obsolete_specific_vfs_charts(ect->name, em);
  994. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
  995. }
  996. }
  997. }
  998. pthread_mutex_unlock(&mutex_cgroup_shm);
  999. }
  1000. /**
  1001. * Main loop for this collector.
  1002. *
  1003. * @param step the number of microseconds used with heart beat
  1004. * @param em the structure with thread information
  1005. */
  1006. static void vfs_collector(ebpf_module_t *em)
  1007. {
  1008. vfs_threads.thread = mallocz(sizeof(netdata_thread_t));
  1009. vfs_threads.start_routine = ebpf_vfs_read_hash;
  1010. netdata_thread_create(vfs_threads.thread, vfs_threads.name, NETDATA_THREAD_OPTION_JOINABLE,
  1011. ebpf_vfs_read_hash, em);
  1012. int apps = em->apps_charts;
  1013. int cgroups = em->cgroup_charts;
  1014. int update_every = em->update_every;
  1015. int counter = update_every - 1;
  1016. while (!close_ebpf_plugin) {
  1017. pthread_mutex_lock(&collect_data_mutex);
  1018. pthread_cond_wait(&collect_data_cond_var, &collect_data_mutex);
  1019. if (++counter == update_every) {
  1020. counter = 0;
  1021. if (apps)
  1022. ebpf_vfs_read_apps();
  1023. if (cgroups)
  1024. read_update_vfs_cgroup();
  1025. pthread_mutex_lock(&lock);
  1026. ebpf_vfs_send_data(em);
  1027. fflush(stdout);
  1028. if (apps)
  1029. ebpf_vfs_send_apps_data(em, apps_groups_root_target);
  1030. if (cgroups)
  1031. ebpf_vfs_send_cgroup_data(em);
  1032. pthread_mutex_unlock(&lock);
  1033. }
  1034. pthread_mutex_unlock(&collect_data_mutex);
  1035. }
  1036. }
  1037. /*****************************************************************
  1038. *
  1039. * FUNCTIONS TO CREATE CHARTS
  1040. *
  1041. *****************************************************************/
  1042. /**
  1043. * Create IO chart
  1044. *
  1045. * @param family the chart family
  1046. * @param name the chart name
  1047. * @param axis the axis label
  1048. * @param web the group name used to attach the chart on dashboard
  1049. * @param order the order number of the specified chart
  1050. * @param algorithm the algorithm used to make the charts.
  1051. * @param update_every value to overwrite the update frequency set by the server.
  1052. */
  1053. static void ebpf_create_io_chart(char *family, char *name, char *axis, char *web,
  1054. int order, int algorithm, int update_every)
  1055. {
  1056. printf("CHART %s.%s '' 'Bytes written and read' '%s' '%s' '' line %d %d '' 'ebpf.plugin' 'filesystem'\n",
  1057. family,
  1058. name,
  1059. axis,
  1060. web,
  1061. order,
  1062. update_every);
  1063. printf("DIMENSION %s %s %s 1 1\n",
  1064. vfs_id_names[NETDATA_KEY_PUBLISH_VFS_READ],
  1065. vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_READ],
  1066. ebpf_algorithms[algorithm]);
  1067. printf("DIMENSION %s %s %s -1 1\n",
  1068. vfs_id_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
  1069. vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
  1070. ebpf_algorithms[algorithm]);
  1071. }
  1072. /**
  1073. * Create global charts
  1074. *
  1075. * Call ebpf_create_chart to create the charts for the collector.
  1076. *
  1077. * @param em a pointer to the structure with the default values.
  1078. */
  1079. static void ebpf_create_global_charts(ebpf_module_t *em)
  1080. {
  1081. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1082. NETDATA_VFS_FILE_CLEAN_COUNT,
  1083. "Remove files",
  1084. EBPF_COMMON_DIMENSION_CALL,
  1085. NETDATA_VFS_GROUP,
  1086. NULL,
  1087. NETDATA_EBPF_CHART_TYPE_LINE,
  1088. NETDATA_CHART_PRIO_FILESYSTEM_VFS_CLEAN,
  1089. ebpf_create_global_dimension,
  1090. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
  1091. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1092. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1093. NETDATA_VFS_FILE_IO_COUNT,
  1094. "Calls to IO",
  1095. EBPF_COMMON_DIMENSION_CALL,
  1096. NETDATA_VFS_GROUP,
  1097. NULL,
  1098. NETDATA_EBPF_CHART_TYPE_LINE,
  1099. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_COUNT,
  1100. ebpf_create_global_dimension,
  1101. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  1102. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1103. ebpf_create_io_chart(NETDATA_FILESYSTEM_FAMILY,
  1104. NETDATA_VFS_IO_FILE_BYTES, EBPF_COMMON_DIMENSION_BYTES,
  1105. NETDATA_VFS_GROUP,
  1106. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_BYTES,
  1107. NETDATA_EBPF_INCREMENTAL_IDX, em->update_every);
  1108. if (em->mode < MODE_ENTRY) {
  1109. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1110. NETDATA_VFS_FILE_ERR_COUNT,
  1111. "Fails to write or read",
  1112. EBPF_COMMON_DIMENSION_CALL,
  1113. NETDATA_VFS_GROUP,
  1114. NULL,
  1115. NETDATA_EBPF_CHART_TYPE_LINE,
  1116. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EBYTES,
  1117. ebpf_create_global_dimension,
  1118. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  1119. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1120. }
  1121. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1122. NETDATA_VFS_FSYNC,
  1123. "Calls for <code>vfs_fsync</code>",
  1124. EBPF_COMMON_DIMENSION_CALL,
  1125. NETDATA_VFS_GROUP,
  1126. NULL,
  1127. NETDATA_EBPF_CHART_TYPE_LINE,
  1128. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_FSYNC,
  1129. ebpf_create_global_dimension,
  1130. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  1131. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1132. if (em->mode < MODE_ENTRY) {
  1133. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1134. NETDATA_VFS_FSYNC_ERR,
  1135. "Fails to synchronize",
  1136. EBPF_COMMON_DIMENSION_CALL,
  1137. NETDATA_VFS_GROUP,
  1138. NULL,
  1139. NETDATA_EBPF_CHART_TYPE_LINE,
  1140. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EFSYNC,
  1141. ebpf_create_global_dimension,
  1142. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  1143. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1144. }
  1145. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1146. NETDATA_VFS_OPEN,
  1147. "Calls for <code>vfs_open</code>",
  1148. EBPF_COMMON_DIMENSION_CALL,
  1149. NETDATA_VFS_GROUP,
  1150. NULL,
  1151. NETDATA_EBPF_CHART_TYPE_LINE,
  1152. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_OPEN,
  1153. ebpf_create_global_dimension,
  1154. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  1155. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1156. if (em->mode < MODE_ENTRY) {
  1157. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1158. NETDATA_VFS_OPEN_ERR,
  1159. "Fails to open a file",
  1160. EBPF_COMMON_DIMENSION_CALL,
  1161. NETDATA_VFS_GROUP,
  1162. NULL,
  1163. NETDATA_EBPF_CHART_TYPE_LINE,
  1164. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EOPEN,
  1165. ebpf_create_global_dimension,
  1166. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  1167. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1168. }
  1169. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1170. NETDATA_VFS_CREATE,
  1171. "Calls for <code>vfs_create</code>",
  1172. EBPF_COMMON_DIMENSION_CALL,
  1173. NETDATA_VFS_GROUP,
  1174. NULL,
  1175. NETDATA_EBPF_CHART_TYPE_LINE,
  1176. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_CREATE,
  1177. ebpf_create_global_dimension,
  1178. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  1179. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1180. if (em->mode < MODE_ENTRY) {
  1181. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1182. NETDATA_VFS_CREATE_ERR,
  1183. "Fails to create a file.",
  1184. EBPF_COMMON_DIMENSION_CALL,
  1185. NETDATA_VFS_GROUP,
  1186. NULL,
  1187. NETDATA_EBPF_CHART_TYPE_LINE,
  1188. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_ECREATE,
  1189. ebpf_create_global_dimension,
  1190. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  1191. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1192. }
  1193. }
  1194. /**
  1195. * Create process apps charts
  1196. *
  1197. * Call ebpf_create_chart to create the charts on apps submenu.
  1198. *
  1199. * @param em a pointer to the structure with the default values.
  1200. * @param ptr a pointer for the targets.
  1201. **/
  1202. void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr)
  1203. {
  1204. struct target *root = ptr;
  1205. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_DELETED,
  1206. "Files deleted",
  1207. EBPF_COMMON_DIMENSION_CALL,
  1208. NETDATA_VFS_GROUP,
  1209. NETDATA_EBPF_CHART_TYPE_STACKED,
  1210. 20065,
  1211. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1212. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1213. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
  1214. "Write to disk",
  1215. EBPF_COMMON_DIMENSION_CALL,
  1216. NETDATA_VFS_GROUP,
  1217. NETDATA_EBPF_CHART_TYPE_STACKED,
  1218. 20066,
  1219. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1220. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1221. if (em->mode < MODE_ENTRY) {
  1222. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
  1223. "Fails to write",
  1224. EBPF_COMMON_DIMENSION_CALL,
  1225. NETDATA_VFS_GROUP,
  1226. NETDATA_EBPF_CHART_TYPE_STACKED,
  1227. 20067,
  1228. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1229. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1230. }
  1231. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
  1232. "Read from disk",
  1233. EBPF_COMMON_DIMENSION_CALL,
  1234. NETDATA_VFS_GROUP,
  1235. NETDATA_EBPF_CHART_TYPE_STACKED,
  1236. 20068,
  1237. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1238. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1239. if (em->mode < MODE_ENTRY) {
  1240. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
  1241. "Fails to read",
  1242. EBPF_COMMON_DIMENSION_CALL,
  1243. NETDATA_VFS_GROUP,
  1244. NETDATA_EBPF_CHART_TYPE_STACKED,
  1245. 20069,
  1246. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1247. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1248. }
  1249. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
  1250. "Bytes written on disk", EBPF_COMMON_DIMENSION_BYTES,
  1251. NETDATA_VFS_GROUP,
  1252. NETDATA_EBPF_CHART_TYPE_STACKED,
  1253. 20070,
  1254. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1255. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1256. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
  1257. "Bytes read from disk", EBPF_COMMON_DIMENSION_BYTES,
  1258. NETDATA_VFS_GROUP,
  1259. NETDATA_EBPF_CHART_TYPE_STACKED,
  1260. 20071,
  1261. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1262. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1263. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_FSYNC,
  1264. "Calls for <code>vfs_fsync</code>", EBPF_COMMON_DIMENSION_CALL,
  1265. NETDATA_VFS_GROUP,
  1266. NETDATA_EBPF_CHART_TYPE_STACKED,
  1267. 20072,
  1268. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1269. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1270. if (em->mode < MODE_ENTRY) {
  1271. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
  1272. "Sync error",
  1273. EBPF_COMMON_DIMENSION_CALL,
  1274. NETDATA_VFS_GROUP,
  1275. NETDATA_EBPF_CHART_TYPE_STACKED,
  1276. 20073,
  1277. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1278. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1279. }
  1280. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_OPEN,
  1281. "Calls for <code>vfs_open</code>", EBPF_COMMON_DIMENSION_CALL,
  1282. NETDATA_VFS_GROUP,
  1283. NETDATA_EBPF_CHART_TYPE_STACKED,
  1284. 20074,
  1285. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1286. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1287. if (em->mode < MODE_ENTRY) {
  1288. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
  1289. "Open error",
  1290. EBPF_COMMON_DIMENSION_CALL,
  1291. NETDATA_VFS_GROUP,
  1292. NETDATA_EBPF_CHART_TYPE_STACKED,
  1293. 20075,
  1294. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1295. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1296. }
  1297. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_CREATE,
  1298. "Calls for <code>vfs_create</code>", EBPF_COMMON_DIMENSION_CALL,
  1299. NETDATA_VFS_GROUP,
  1300. NETDATA_EBPF_CHART_TYPE_STACKED,
  1301. 20076,
  1302. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1303. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1304. if (em->mode < MODE_ENTRY) {
  1305. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
  1306. "Create error",
  1307. EBPF_COMMON_DIMENSION_CALL,
  1308. NETDATA_VFS_GROUP,
  1309. NETDATA_EBPF_CHART_TYPE_STACKED,
  1310. 20077,
  1311. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1312. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1313. }
  1314. }
  1315. /*****************************************************************
  1316. *
  1317. * FUNCTIONS TO START THREAD
  1318. *
  1319. *****************************************************************/
  1320. /**
  1321. * Allocate vectors used with this thread.
  1322. * We are not testing the return, because callocz does this and shutdown the software
  1323. * case it was not possible to allocate.
  1324. *
  1325. * @param apps is apps enabled?
  1326. */
  1327. static void ebpf_vfs_allocate_global_vectors(int apps)
  1328. {
  1329. memset(vfs_aggregated_data, 0, sizeof(vfs_aggregated_data));
  1330. memset(vfs_publish_aggregated, 0, sizeof(vfs_publish_aggregated));
  1331. vfs_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
  1332. vfs_vector = callocz(ebpf_nprocs, sizeof(netdata_publish_vfs_t));
  1333. if (apps)
  1334. vfs_pid = callocz((size_t)pid_max, sizeof(netdata_publish_vfs_t *));
  1335. }
  1336. /*****************************************************************
  1337. *
  1338. * EBPF VFS THREAD
  1339. *
  1340. *****************************************************************/
  1341. /**
  1342. * Process thread
  1343. *
  1344. * Thread used to generate process charts.
  1345. *
  1346. * @param ptr a pointer to `struct ebpf_module`
  1347. *
  1348. * @return It always return NULL
  1349. */
  1350. void *ebpf_vfs_thread(void *ptr)
  1351. {
  1352. netdata_thread_cleanup_push(ebpf_vfs_cleanup, ptr);
  1353. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1354. em->maps = vfs_maps;
  1355. ebpf_update_pid_table(&vfs_maps[NETDATA_VFS_PID], em);
  1356. ebpf_vfs_allocate_global_vectors(em->apps_charts);
  1357. if (!em->enabled)
  1358. goto endvfs;
  1359. probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &objects);
  1360. if (!probe_links) {
  1361. em->enabled = CONFIG_BOOLEAN_NO;
  1362. goto endvfs;
  1363. }
  1364. int algorithms[NETDATA_KEY_PUBLISH_VFS_END] = {
  1365. NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX,NETDATA_EBPF_INCREMENTAL_IDX,
  1366. NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX,NETDATA_EBPF_INCREMENTAL_IDX
  1367. };
  1368. ebpf_global_labels(vfs_aggregated_data, vfs_publish_aggregated, vfs_dimension_names,
  1369. vfs_id_names, algorithms, NETDATA_KEY_PUBLISH_VFS_END);
  1370. pthread_mutex_lock(&lock);
  1371. ebpf_create_global_charts(em);
  1372. ebpf_update_stats(&plugin_statistics, em);
  1373. pthread_mutex_unlock(&lock);
  1374. vfs_collector(em);
  1375. endvfs:
  1376. if (!em->enabled)
  1377. ebpf_update_disabled_plugin_stats(em);
  1378. netdata_thread_cleanup_pop(1);
  1379. return NULL;
  1380. }