ebpf_vfs.c 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596
  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. struct netdata_static_thread vfs_threads = {"VFS KERNEL",
  31. NULL, NULL, 1, NULL,
  32. NULL, NULL};
  33. static enum ebpf_threads_status ebpf_vfs_exited = NETDATA_THREAD_EBPF_RUNNING;
  34. /*****************************************************************
  35. *
  36. * FUNCTIONS TO CLOSE THE THREAD
  37. *
  38. *****************************************************************/
  39. /**
  40. * Exit
  41. *
  42. * Cancel thread and exit.
  43. *
  44. * @param ptr thread data.
  45. **/
  46. static void ebpf_vfs_exit(void *ptr)
  47. {
  48. ebpf_module_t *em = (ebpf_module_t *)ptr;
  49. if (!em->enabled) {
  50. em->enabled = NETDATA_MAIN_THREAD_EXITED;
  51. return;
  52. }
  53. ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPING;
  54. }
  55. /**
  56. * Clean up the main thread.
  57. *
  58. * @param ptr thread data.
  59. **/
  60. static void ebpf_vfs_cleanup(void *ptr)
  61. {
  62. ebpf_module_t *em = (ebpf_module_t *)ptr;
  63. if (ebpf_vfs_exited != NETDATA_THREAD_EBPF_STOPPED)
  64. return;
  65. freez(vfs_hash_values);
  66. freez(vfs_vector);
  67. freez(vfs_threads.thread);
  68. vfs_threads.enabled = NETDATA_MAIN_THREAD_EXITED;
  69. em->enabled = NETDATA_MAIN_THREAD_EXITED;
  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. netdata_thread_cleanup_push(ebpf_vfs_cleanup, ptr);
  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. //This will be cancelled by its parent
  452. while (ebpf_vfs_exited == NETDATA_THREAD_EBPF_RUNNING) {
  453. usec_t dt = heartbeat_next(&hb, step);
  454. (void)dt;
  455. if (ebpf_vfs_exited == NETDATA_THREAD_EBPF_STOPPING)
  456. break;
  457. read_global_table();
  458. }
  459. ebpf_vfs_exited = NETDATA_THREAD_EBPF_STOPPED;
  460. netdata_thread_cleanup_pop(1);
  461. return NULL;
  462. }
  463. /**
  464. * Sum PIDs
  465. *
  466. * Sum values for all targets.
  467. *
  468. * @param vfs structure used to store data
  469. * @param pids input data
  470. */
  471. static void ebpf_vfs_sum_cgroup_pids(netdata_publish_vfs_t *vfs, struct pid_on_target2 *pids)
  472. {
  473. netdata_publish_vfs_t accumulator;
  474. memset(&accumulator, 0, sizeof(accumulator));
  475. while (pids) {
  476. netdata_publish_vfs_t *w = &pids->vfs;
  477. accumulator.write_call += w->write_call;
  478. accumulator.writev_call += w->writev_call;
  479. accumulator.read_call += w->read_call;
  480. accumulator.readv_call += w->readv_call;
  481. accumulator.unlink_call += w->unlink_call;
  482. accumulator.fsync_call += w->fsync_call;
  483. accumulator.open_call += w->open_call;
  484. accumulator.create_call += w->create_call;
  485. accumulator.write_bytes += w->write_bytes;
  486. accumulator.writev_bytes += w->writev_bytes;
  487. accumulator.read_bytes += w->read_bytes;
  488. accumulator.readv_bytes += w->readv_bytes;
  489. accumulator.write_err += w->write_err;
  490. accumulator.writev_err += w->writev_err;
  491. accumulator.read_err += w->read_err;
  492. accumulator.readv_err += w->readv_err;
  493. accumulator.unlink_err += w->unlink_err;
  494. accumulator.fsync_err += w->fsync_err;
  495. accumulator.open_err += w->open_err;
  496. accumulator.create_err += w->create_err;
  497. pids = pids->next;
  498. }
  499. // These conditions were added, because we are using incremental algorithm
  500. vfs->write_call = (accumulator.write_call >= vfs->write_call) ? accumulator.write_call : vfs->write_call;
  501. vfs->writev_call = (accumulator.writev_call >= vfs->writev_call) ? accumulator.writev_call : vfs->writev_call;
  502. vfs->read_call = (accumulator.read_call >= vfs->read_call) ? accumulator.read_call : vfs->read_call;
  503. vfs->readv_call = (accumulator.readv_call >= vfs->readv_call) ? accumulator.readv_call : vfs->readv_call;
  504. vfs->unlink_call = (accumulator.unlink_call >= vfs->unlink_call) ? accumulator.unlink_call : vfs->unlink_call;
  505. vfs->fsync_call = (accumulator.fsync_call >= vfs->fsync_call) ? accumulator.fsync_call : vfs->fsync_call;
  506. vfs->open_call = (accumulator.open_call >= vfs->open_call) ? accumulator.open_call : vfs->open_call;
  507. vfs->create_call = (accumulator.create_call >= vfs->create_call) ? accumulator.create_call : vfs->create_call;
  508. vfs->write_bytes = (accumulator.write_bytes >= vfs->write_bytes) ? accumulator.write_bytes : vfs->write_bytes;
  509. vfs->writev_bytes = (accumulator.writev_bytes >= vfs->writev_bytes) ? accumulator.writev_bytes : vfs->writev_bytes;
  510. vfs->read_bytes = (accumulator.read_bytes >= vfs->read_bytes) ? accumulator.read_bytes : vfs->read_bytes;
  511. vfs->readv_bytes = (accumulator.readv_bytes >= vfs->readv_bytes) ? accumulator.readv_bytes : vfs->readv_bytes;
  512. vfs->write_err = (accumulator.write_err >= vfs->write_err) ? accumulator.write_err : vfs->write_err;
  513. vfs->writev_err = (accumulator.writev_err >= vfs->writev_err) ? accumulator.writev_err : vfs->writev_err;
  514. vfs->read_err = (accumulator.read_err >= vfs->read_err) ? accumulator.read_err : vfs->read_err;
  515. vfs->readv_err = (accumulator.readv_err >= vfs->readv_err) ? accumulator.readv_err : vfs->readv_err;
  516. vfs->unlink_err = (accumulator.unlink_err >= vfs->unlink_err) ? accumulator.unlink_err : vfs->unlink_err;
  517. vfs->fsync_err = (accumulator.fsync_err >= vfs->fsync_err) ? accumulator.fsync_err : vfs->fsync_err;
  518. vfs->open_err = (accumulator.open_err >= vfs->open_err) ? accumulator.open_err : vfs->open_err;
  519. vfs->create_err = (accumulator.create_err >= vfs->create_err) ? accumulator.create_err : vfs->create_err;
  520. }
  521. /**
  522. * Create specific VFS charts
  523. *
  524. * Create charts for cgroup/application.
  525. *
  526. * @param type the chart type.
  527. * @param em the main thread structure.
  528. */
  529. static void ebpf_create_specific_vfs_charts(char *type, ebpf_module_t *em)
  530. {
  531. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED,"Files deleted",
  532. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
  533. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500,
  534. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
  535. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  536. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
  537. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_CONTEXT,
  538. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501,
  539. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
  540. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  541. if (em->mode < MODE_ENTRY) {
  542. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
  543. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
  544. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502,
  545. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
  546. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  547. }
  548. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
  549. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_CONTEXT,
  550. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503,
  551. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  552. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  553. if (em->mode < MODE_ENTRY) {
  554. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
  555. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
  556. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504,
  557. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  558. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  559. }
  560. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
  561. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
  562. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505,
  563. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE],
  564. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  565. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
  566. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
  567. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506,
  568. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  569. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  570. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls for <code>vfs_fsync</code>",
  571. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_FSYNC_CONTEXT,
  572. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507,
  573. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  574. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  575. if (em->mode < MODE_ENTRY) {
  576. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
  577. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_FSYNC_ERROR_CONTEXT,
  578. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508,
  579. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  580. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  581. }
  582. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls for <code>vfs_open</code>",
  583. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_OPEN_CONTEXT,
  584. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509,
  585. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  586. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  587. if (em->mode < MODE_ENTRY) {
  588. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
  589. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_OPEN_ERROR_CONTEXT,
  590. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510,
  591. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  592. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  593. }
  594. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls for <code>vfs_create</code>",
  595. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_CREATE_CONTEXT,
  596. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511,
  597. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  598. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  599. if (em->mode < MODE_ENTRY) {
  600. ebpf_create_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
  601. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP, NETDATA_CGROUP_VFS_CREATE_ERROR_CONTEXT,
  602. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512,
  603. ebpf_create_global_dimension, &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  604. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_SWAP);
  605. }
  606. }
  607. /**
  608. * Obsolete specific VFS charts
  609. *
  610. * Obsolete charts for cgroup/application.
  611. *
  612. * @param type the chart type.
  613. * @param em the main thread structure.
  614. */
  615. static void ebpf_obsolete_specific_vfs_charts(char *type, ebpf_module_t *em)
  616. {
  617. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_FILE_DELETED, "Files deleted",
  618. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  619. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_UNLINK_CONTEXT,
  620. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5500, em->update_every);
  621. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
  622. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  623. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_CONTEXT,
  624. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5501, em->update_every);
  625. if (em->mode < MODE_ENTRY) {
  626. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
  627. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  628. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_ERROR_CONTEXT,
  629. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5502, em->update_every);
  630. }
  631. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
  632. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  633. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_CONTEXT,
  634. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5503, em->update_every);
  635. if (em->mode < MODE_ENTRY) {
  636. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
  637. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  638. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_ERROR_CONTEXT,
  639. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5504, em->update_every);
  640. }
  641. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
  642. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_GROUP,
  643. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_WRITE_BYTES_CONTEXT,
  644. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5505, em->update_every);
  645. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
  646. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_GROUP,
  647. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_READ_BYTES_CONTEXT,
  648. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5506, em->update_every);
  649. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls for <code>vfs_fsync</code>",
  650. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  651. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_FSYNC_CONTEXT,
  652. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5507, em->update_every);
  653. if (em->mode < MODE_ENTRY) {
  654. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
  655. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  656. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_FSYNC_ERROR_CONTEXT,
  657. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5508, em->update_every);
  658. }
  659. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls for <code>vfs_open</code>",
  660. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  661. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_OPEN_CONTEXT,
  662. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5509, em->update_every);
  663. if (em->mode < MODE_ENTRY) {
  664. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
  665. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  666. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_OPEN_ERROR_CONTEXT,
  667. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5510, em->update_every);
  668. }
  669. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls for <code>vfs_create</code>",
  670. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  671. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_CREATE_CONTEXT,
  672. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5511, em->update_every);
  673. if (em->mode < MODE_ENTRY) {
  674. ebpf_write_chart_obsolete(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
  675. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_GROUP,
  676. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_VFS_CREATE_ERROR_CONTEXT,
  677. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5512, em->update_every);
  678. }
  679. }
  680. /*
  681. * Send specific VFS data
  682. *
  683. * Send data for specific cgroup/apps.
  684. *
  685. * @param type chart type
  686. * @param values structure with values that will be sent to netdata
  687. */
  688. static void ebpf_send_specific_vfs_data(char *type, netdata_publish_vfs_t *values, ebpf_module_t *em)
  689. {
  690. write_begin_chart(type, NETDATA_SYSCALL_APPS_FILE_DELETED);
  691. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK].name, (long long)values->unlink_call);
  692. write_end_chart();
  693. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
  694. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
  695. (long long)values->write_call + (long long)values->writev_call);
  696. write_end_chart();
  697. if (em->mode < MODE_ENTRY) {
  698. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
  699. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
  700. (long long)values->write_err + (long long)values->writev_err);
  701. write_end_chart();
  702. }
  703. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
  704. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
  705. (long long)values->read_call + (long long)values->readv_call);
  706. write_end_chart();
  707. if (em->mode < MODE_ENTRY) {
  708. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
  709. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
  710. (long long)values->read_err + (long long)values->readv_err);
  711. write_end_chart();
  712. }
  713. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
  714. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_WRITE].name,
  715. (long long)values->write_bytes + (long long)values->writev_bytes);
  716. write_end_chart();
  717. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
  718. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ].name,
  719. (long long)values->read_bytes + (long long)values->readv_bytes);
  720. write_end_chart();
  721. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC);
  722. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name,
  723. (long long)values->fsync_call);
  724. write_end_chart();
  725. if (em->mode < MODE_ENTRY) {
  726. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
  727. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC].name,
  728. (long long)values->fsync_err);
  729. write_end_chart();
  730. }
  731. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN);
  732. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name,
  733. (long long)values->open_call);
  734. write_end_chart();
  735. if (em->mode < MODE_ENTRY) {
  736. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
  737. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN].name,
  738. (long long)values->open_err);
  739. write_end_chart();
  740. }
  741. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE);
  742. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name,
  743. (long long)values->create_call);
  744. write_end_chart();
  745. if (em->mode < MODE_ENTRY) {
  746. write_begin_chart(type, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
  747. write_chart_dimension(vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE].name,
  748. (long long)values->create_err);
  749. write_end_chart();
  750. }
  751. }
  752. /**
  753. * Create Systemd Socket Charts
  754. *
  755. * Create charts when systemd is enabled
  756. *
  757. * @param em the main collector structure
  758. **/
  759. static void ebpf_create_systemd_vfs_charts(ebpf_module_t *em)
  760. {
  761. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_FILE_DELETED, "Files deleted",
  762. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  763. NETDATA_EBPF_CHART_TYPE_STACKED, 20065,
  764. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_UNLINK_CONTEXT,
  765. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  766. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS, "Write to disk",
  767. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  768. NETDATA_EBPF_CHART_TYPE_STACKED, 20066,
  769. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_WRITE_CONTEXT,
  770. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  771. if (em->mode < MODE_ENTRY) {
  772. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR, "Fails to write",
  773. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  774. NETDATA_EBPF_CHART_TYPE_STACKED, 20067,
  775. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  776. NETDATA_SYSTEMD_VFS_WRITE_ERROR_CONTEXT,
  777. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  778. }
  779. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_CALLS, "Read from disk",
  780. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  781. NETDATA_EBPF_CHART_TYPE_STACKED, 20068,
  782. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_READ_CONTEXT,
  783. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  784. if (em->mode < MODE_ENTRY) {
  785. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR, "Fails to read",
  786. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  787. NETDATA_EBPF_CHART_TYPE_STACKED, 20069,
  788. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  789. NETDATA_SYSTEMD_VFS_READ_ERROR_CONTEXT,
  790. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  791. }
  792. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES, "Bytes written on disk",
  793. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP,
  794. NETDATA_EBPF_CHART_TYPE_STACKED, 20070,
  795. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_WRITE_BYTES_CONTEXT,
  796. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  797. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_READ_BYTES, "Bytes read from disk",
  798. EBPF_COMMON_DIMENSION_BYTES, NETDATA_VFS_CGROUP_GROUP,
  799. NETDATA_EBPF_CHART_TYPE_STACKED, 20071,
  800. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_READ_BYTES_CONTEXT,
  801. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  802. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_FSYNC, "Calls to <code>vfs_fsync</code>",
  803. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  804. NETDATA_EBPF_CHART_TYPE_STACKED, 20072,
  805. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_FSYNC_CONTEXT,
  806. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  807. if (em->mode < MODE_ENTRY) {
  808. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR, "Sync error",
  809. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  810. NETDATA_EBPF_CHART_TYPE_STACKED, 20073,
  811. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_FSYNC_ERROR_CONTEXT,
  812. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  813. }
  814. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_OPEN, "Calls to <code>vfs_open</code>",
  815. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  816. NETDATA_EBPF_CHART_TYPE_STACKED, 20074,
  817. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_OPEN_CONTEXT,
  818. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  819. if (em->mode < MODE_ENTRY) {
  820. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR, "Open error",
  821. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  822. NETDATA_EBPF_CHART_TYPE_STACKED, 20075,
  823. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_OPEN_ERROR_CONTEXT,
  824. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  825. }
  826. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_CREATE, "Calls to <code>vfs_create</code>",
  827. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  828. NETDATA_EBPF_CHART_TYPE_STACKED, 20076,
  829. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_CREATE_CONTEXT,
  830. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  831. if (em->mode < MODE_ENTRY) {
  832. ebpf_create_charts_on_systemd(NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR, "Create error",
  833. EBPF_COMMON_DIMENSION_CALL, NETDATA_VFS_CGROUP_GROUP,
  834. NETDATA_EBPF_CHART_TYPE_STACKED, 20077,
  835. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX], NETDATA_SYSTEMD_VFS_CREATE_ERROR_CONTEXT,
  836. NETDATA_EBPF_MODULE_NAME_VFS, em->update_every);
  837. }
  838. }
  839. /**
  840. * Send Systemd charts
  841. *
  842. * Send collected data to Netdata.
  843. *
  844. * @param em the main collector structure
  845. *
  846. * @return It returns the status for chart creation, if it is necessary to remove a specific dimension, zero is returned
  847. * otherwise function returns 1 to avoid chart recreation
  848. */
  849. static int ebpf_send_systemd_vfs_charts(ebpf_module_t *em)
  850. {
  851. int ret = 1;
  852. ebpf_cgroup_target_t *ect;
  853. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_FILE_DELETED);
  854. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  855. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  856. write_chart_dimension(ect->name, ect->publish_systemd_vfs.unlink_call);
  857. } else if (unlikely(ect->systemd))
  858. ret = 0;
  859. }
  860. write_end_chart();
  861. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS);
  862. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  863. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  864. write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_call +
  865. ect->publish_systemd_vfs.writev_call);
  866. }
  867. }
  868. write_end_chart();
  869. if (em->mode < MODE_ENTRY) {
  870. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR);
  871. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  872. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  873. write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_err +
  874. ect->publish_systemd_vfs.writev_err);
  875. }
  876. }
  877. write_end_chart();
  878. }
  879. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS);
  880. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  881. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  882. write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_call +
  883. ect->publish_systemd_vfs.readv_call);
  884. }
  885. }
  886. write_end_chart();
  887. if (em->mode < MODE_ENTRY) {
  888. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR);
  889. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  890. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  891. write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_err +
  892. ect->publish_systemd_vfs.readv_err);
  893. }
  894. }
  895. write_end_chart();
  896. }
  897. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES);
  898. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  899. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  900. write_chart_dimension(ect->name, ect->publish_systemd_vfs.write_bytes +
  901. ect->publish_systemd_vfs.writev_bytes);
  902. }
  903. }
  904. write_end_chart();
  905. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_READ_BYTES);
  906. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  907. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  908. write_chart_dimension(ect->name, ect->publish_systemd_vfs.read_bytes +
  909. ect->publish_systemd_vfs.readv_bytes);
  910. }
  911. }
  912. write_end_chart();
  913. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC);
  914. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  915. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  916. write_chart_dimension(ect->name, ect->publish_systemd_vfs.fsync_call);
  917. }
  918. }
  919. write_end_chart();
  920. if (em->mode < MODE_ENTRY) {
  921. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR);
  922. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  923. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  924. write_chart_dimension(ect->name, ect->publish_systemd_vfs.fsync_err);
  925. }
  926. }
  927. write_end_chart();
  928. }
  929. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN);
  930. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  931. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  932. write_chart_dimension(ect->name, ect->publish_systemd_vfs.open_call);
  933. }
  934. }
  935. write_end_chart();
  936. if (em->mode < MODE_ENTRY) {
  937. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR);
  938. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  939. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  940. write_chart_dimension(ect->name, ect->publish_systemd_vfs.open_err);
  941. }
  942. }
  943. write_end_chart();
  944. }
  945. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE);
  946. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  947. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  948. write_chart_dimension(ect->name, ect->publish_systemd_vfs.create_call);
  949. }
  950. }
  951. write_end_chart();
  952. if (em->mode < MODE_ENTRY) {
  953. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR);
  954. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  955. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  956. write_chart_dimension(ect->name, ect->publish_systemd_vfs.create_err);
  957. }
  958. }
  959. write_end_chart();
  960. }
  961. return ret;
  962. }
  963. /**
  964. * Send data to Netdata calling auxiliary functions.
  965. *
  966. * @param em the main collector structure
  967. */
  968. static void ebpf_vfs_send_cgroup_data(ebpf_module_t *em)
  969. {
  970. if (!ebpf_cgroup_pids)
  971. return;
  972. pthread_mutex_lock(&mutex_cgroup_shm);
  973. ebpf_cgroup_target_t *ect;
  974. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  975. ebpf_vfs_sum_cgroup_pids(&ect->publish_systemd_vfs, ect->pids);
  976. }
  977. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  978. if (has_systemd) {
  979. static int systemd_charts = 0;
  980. if (!systemd_charts) {
  981. ebpf_create_systemd_vfs_charts(em);
  982. systemd_charts = 1;
  983. }
  984. systemd_charts = ebpf_send_systemd_vfs_charts(em);
  985. }
  986. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  987. if (ect->systemd)
  988. continue;
  989. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) && ect->updated) {
  990. ebpf_create_specific_vfs_charts(ect->name, em);
  991. ect->flags |= NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
  992. }
  993. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_VFS_CHART) {
  994. if (ect->updated) {
  995. ebpf_send_specific_vfs_data(ect->name, &ect->publish_systemd_vfs, em);
  996. } else {
  997. ebpf_obsolete_specific_vfs_charts(ect->name, em);
  998. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_VFS_CHART;
  999. }
  1000. }
  1001. }
  1002. pthread_mutex_unlock(&mutex_cgroup_shm);
  1003. }
  1004. /**
  1005. * Main loop for this collector.
  1006. *
  1007. * @param step the number of microseconds used with heart beat
  1008. * @param em the structure with thread information
  1009. */
  1010. static void vfs_collector(ebpf_module_t *em)
  1011. {
  1012. vfs_threads.thread = mallocz(sizeof(netdata_thread_t));
  1013. vfs_threads.start_routine = ebpf_vfs_read_hash;
  1014. netdata_thread_create(vfs_threads.thread, vfs_threads.name, NETDATA_THREAD_OPTION_DEFAULT,
  1015. ebpf_vfs_read_hash, em);
  1016. int cgroups = em->cgroup_charts;
  1017. heartbeat_t hb;
  1018. heartbeat_init(&hb);
  1019. usec_t step = em->update_every * USEC_PER_SEC;
  1020. while (!ebpf_exit_plugin) {
  1021. (void)heartbeat_next(&hb, step);
  1022. if (ebpf_exit_plugin)
  1023. break;
  1024. netdata_apps_integration_flags_t apps = em->apps_charts;
  1025. pthread_mutex_lock(&collect_data_mutex);
  1026. if (apps)
  1027. ebpf_vfs_read_apps();
  1028. if (cgroups)
  1029. read_update_vfs_cgroup();
  1030. pthread_mutex_lock(&lock);
  1031. ebpf_vfs_send_data(em);
  1032. fflush(stdout);
  1033. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
  1034. ebpf_vfs_send_apps_data(em, apps_groups_root_target);
  1035. if (cgroups)
  1036. ebpf_vfs_send_cgroup_data(em);
  1037. pthread_mutex_unlock(&lock);
  1038. pthread_mutex_unlock(&collect_data_mutex);
  1039. }
  1040. }
  1041. /*****************************************************************
  1042. *
  1043. * FUNCTIONS TO CREATE CHARTS
  1044. *
  1045. *****************************************************************/
  1046. /**
  1047. * Create IO chart
  1048. *
  1049. * @param family the chart family
  1050. * @param name the chart name
  1051. * @param axis the axis label
  1052. * @param web the group name used to attach the chart on dashboard
  1053. * @param order the order number of the specified chart
  1054. * @param algorithm the algorithm used to make the charts.
  1055. * @param update_every value to overwrite the update frequency set by the server.
  1056. */
  1057. static void ebpf_create_io_chart(char *family, char *name, char *axis, char *web,
  1058. int order, int algorithm, int update_every)
  1059. {
  1060. printf("CHART %s.%s '' 'Bytes written and read' '%s' '%s' '' line %d %d '' 'ebpf.plugin' 'filesystem'\n",
  1061. family,
  1062. name,
  1063. axis,
  1064. web,
  1065. order,
  1066. update_every);
  1067. printf("DIMENSION %s %s %s 1 1\n",
  1068. vfs_id_names[NETDATA_KEY_PUBLISH_VFS_READ],
  1069. vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_READ],
  1070. ebpf_algorithms[algorithm]);
  1071. printf("DIMENSION %s %s %s -1 1\n",
  1072. vfs_id_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
  1073. vfs_dimension_names[NETDATA_KEY_PUBLISH_VFS_WRITE],
  1074. ebpf_algorithms[algorithm]);
  1075. }
  1076. /**
  1077. * Create global charts
  1078. *
  1079. * Call ebpf_create_chart to create the charts for the collector.
  1080. *
  1081. * @param em a pointer to the structure with the default values.
  1082. */
  1083. static void ebpf_create_global_charts(ebpf_module_t *em)
  1084. {
  1085. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1086. NETDATA_VFS_FILE_CLEAN_COUNT,
  1087. "Remove files",
  1088. EBPF_COMMON_DIMENSION_CALL,
  1089. NETDATA_VFS_GROUP,
  1090. NULL,
  1091. NETDATA_EBPF_CHART_TYPE_LINE,
  1092. NETDATA_CHART_PRIO_FILESYSTEM_VFS_CLEAN,
  1093. ebpf_create_global_dimension,
  1094. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_UNLINK],
  1095. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1096. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1097. NETDATA_VFS_FILE_IO_COUNT,
  1098. "Calls to IO",
  1099. EBPF_COMMON_DIMENSION_CALL,
  1100. NETDATA_VFS_GROUP,
  1101. NULL,
  1102. NETDATA_EBPF_CHART_TYPE_LINE,
  1103. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_COUNT,
  1104. ebpf_create_global_dimension,
  1105. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  1106. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1107. ebpf_create_io_chart(NETDATA_FILESYSTEM_FAMILY,
  1108. NETDATA_VFS_IO_FILE_BYTES, EBPF_COMMON_DIMENSION_BYTES,
  1109. NETDATA_VFS_GROUP,
  1110. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_BYTES,
  1111. NETDATA_EBPF_INCREMENTAL_IDX, em->update_every);
  1112. if (em->mode < MODE_ENTRY) {
  1113. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1114. NETDATA_VFS_FILE_ERR_COUNT,
  1115. "Fails to write or read",
  1116. EBPF_COMMON_DIMENSION_CALL,
  1117. NETDATA_VFS_GROUP,
  1118. NULL,
  1119. NETDATA_EBPF_CHART_TYPE_LINE,
  1120. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EBYTES,
  1121. ebpf_create_global_dimension,
  1122. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_READ],
  1123. 2, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1124. }
  1125. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1126. NETDATA_VFS_FSYNC,
  1127. "Calls for <code>vfs_fsync</code>",
  1128. EBPF_COMMON_DIMENSION_CALL,
  1129. NETDATA_VFS_GROUP,
  1130. NULL,
  1131. NETDATA_EBPF_CHART_TYPE_LINE,
  1132. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_FSYNC,
  1133. ebpf_create_global_dimension,
  1134. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  1135. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1136. if (em->mode < MODE_ENTRY) {
  1137. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1138. NETDATA_VFS_FSYNC_ERR,
  1139. "Fails to synchronize",
  1140. EBPF_COMMON_DIMENSION_CALL,
  1141. NETDATA_VFS_GROUP,
  1142. NULL,
  1143. NETDATA_EBPF_CHART_TYPE_LINE,
  1144. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EFSYNC,
  1145. ebpf_create_global_dimension,
  1146. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_FSYNC],
  1147. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1148. }
  1149. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1150. NETDATA_VFS_OPEN,
  1151. "Calls for <code>vfs_open</code>",
  1152. EBPF_COMMON_DIMENSION_CALL,
  1153. NETDATA_VFS_GROUP,
  1154. NULL,
  1155. NETDATA_EBPF_CHART_TYPE_LINE,
  1156. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_OPEN,
  1157. ebpf_create_global_dimension,
  1158. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  1159. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1160. if (em->mode < MODE_ENTRY) {
  1161. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1162. NETDATA_VFS_OPEN_ERR,
  1163. "Fails to open a file",
  1164. EBPF_COMMON_DIMENSION_CALL,
  1165. NETDATA_VFS_GROUP,
  1166. NULL,
  1167. NETDATA_EBPF_CHART_TYPE_LINE,
  1168. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_EOPEN,
  1169. ebpf_create_global_dimension,
  1170. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_OPEN],
  1171. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1172. }
  1173. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1174. NETDATA_VFS_CREATE,
  1175. "Calls for <code>vfs_create</code>",
  1176. EBPF_COMMON_DIMENSION_CALL,
  1177. NETDATA_VFS_GROUP,
  1178. NULL,
  1179. NETDATA_EBPF_CHART_TYPE_LINE,
  1180. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_CREATE,
  1181. ebpf_create_global_dimension,
  1182. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  1183. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1184. if (em->mode < MODE_ENTRY) {
  1185. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY,
  1186. NETDATA_VFS_CREATE_ERR,
  1187. "Fails to create a file.",
  1188. EBPF_COMMON_DIMENSION_CALL,
  1189. NETDATA_VFS_GROUP,
  1190. NULL,
  1191. NETDATA_EBPF_CHART_TYPE_LINE,
  1192. NETDATA_CHART_PRIO_FILESYSTEM_VFS_IO_ECREATE,
  1193. ebpf_create_global_dimension,
  1194. &vfs_publish_aggregated[NETDATA_KEY_PUBLISH_VFS_CREATE],
  1195. 1, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1196. }
  1197. }
  1198. /**
  1199. * Create process apps charts
  1200. *
  1201. * Call ebpf_create_chart to create the charts on apps submenu.
  1202. *
  1203. * @param em a pointer to the structure with the default values.
  1204. * @param ptr a pointer for the targets.
  1205. **/
  1206. void ebpf_vfs_create_apps_charts(struct ebpf_module *em, void *ptr)
  1207. {
  1208. struct target *root = ptr;
  1209. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_FILE_DELETED,
  1210. "Files deleted",
  1211. EBPF_COMMON_DIMENSION_CALL,
  1212. NETDATA_VFS_GROUP,
  1213. NETDATA_EBPF_CHART_TYPE_STACKED,
  1214. 20065,
  1215. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1216. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1217. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS,
  1218. "Write to disk",
  1219. EBPF_COMMON_DIMENSION_CALL,
  1220. NETDATA_VFS_GROUP,
  1221. NETDATA_EBPF_CHART_TYPE_STACKED,
  1222. 20066,
  1223. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1224. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1225. if (em->mode < MODE_ENTRY) {
  1226. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_CALLS_ERROR,
  1227. "Fails to write",
  1228. EBPF_COMMON_DIMENSION_CALL,
  1229. NETDATA_VFS_GROUP,
  1230. NETDATA_EBPF_CHART_TYPE_STACKED,
  1231. 20067,
  1232. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1233. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1234. }
  1235. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_CALLS,
  1236. "Read from disk",
  1237. EBPF_COMMON_DIMENSION_CALL,
  1238. NETDATA_VFS_GROUP,
  1239. NETDATA_EBPF_CHART_TYPE_STACKED,
  1240. 20068,
  1241. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1242. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1243. if (em->mode < MODE_ENTRY) {
  1244. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_CALLS_ERROR,
  1245. "Fails to read",
  1246. EBPF_COMMON_DIMENSION_CALL,
  1247. NETDATA_VFS_GROUP,
  1248. NETDATA_EBPF_CHART_TYPE_STACKED,
  1249. 20069,
  1250. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1251. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1252. }
  1253. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_WRITE_BYTES,
  1254. "Bytes written on disk", EBPF_COMMON_DIMENSION_BYTES,
  1255. NETDATA_VFS_GROUP,
  1256. NETDATA_EBPF_CHART_TYPE_STACKED,
  1257. 20070,
  1258. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1259. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1260. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_READ_BYTES,
  1261. "Bytes read from disk", EBPF_COMMON_DIMENSION_BYTES,
  1262. NETDATA_VFS_GROUP,
  1263. NETDATA_EBPF_CHART_TYPE_STACKED,
  1264. 20071,
  1265. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1266. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1267. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_FSYNC,
  1268. "Calls for <code>vfs_fsync</code>", EBPF_COMMON_DIMENSION_CALL,
  1269. NETDATA_VFS_GROUP,
  1270. NETDATA_EBPF_CHART_TYPE_STACKED,
  1271. 20072,
  1272. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1273. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1274. if (em->mode < MODE_ENTRY) {
  1275. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_FSYNC_CALLS_ERROR,
  1276. "Sync error",
  1277. EBPF_COMMON_DIMENSION_CALL,
  1278. NETDATA_VFS_GROUP,
  1279. NETDATA_EBPF_CHART_TYPE_STACKED,
  1280. 20073,
  1281. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1282. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1283. }
  1284. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_OPEN,
  1285. "Calls for <code>vfs_open</code>", EBPF_COMMON_DIMENSION_CALL,
  1286. NETDATA_VFS_GROUP,
  1287. NETDATA_EBPF_CHART_TYPE_STACKED,
  1288. 20074,
  1289. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1290. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1291. if (em->mode < MODE_ENTRY) {
  1292. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_OPEN_CALLS_ERROR,
  1293. "Open error",
  1294. EBPF_COMMON_DIMENSION_CALL,
  1295. NETDATA_VFS_GROUP,
  1296. NETDATA_EBPF_CHART_TYPE_STACKED,
  1297. 20075,
  1298. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1299. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1300. }
  1301. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_CREATE,
  1302. "Calls for <code>vfs_create</code>", EBPF_COMMON_DIMENSION_CALL,
  1303. NETDATA_VFS_GROUP,
  1304. NETDATA_EBPF_CHART_TYPE_STACKED,
  1305. 20076,
  1306. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1307. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1308. if (em->mode < MODE_ENTRY) {
  1309. ebpf_create_charts_on_apps(NETDATA_SYSCALL_APPS_VFS_CREATE_CALLS_ERROR,
  1310. "Create error",
  1311. EBPF_COMMON_DIMENSION_CALL,
  1312. NETDATA_VFS_GROUP,
  1313. NETDATA_EBPF_CHART_TYPE_STACKED,
  1314. 20077,
  1315. ebpf_algorithms[NETDATA_EBPF_INCREMENTAL_IDX],
  1316. root, em->update_every, NETDATA_EBPF_MODULE_NAME_VFS);
  1317. }
  1318. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  1319. }
  1320. /*****************************************************************
  1321. *
  1322. * FUNCTIONS TO START THREAD
  1323. *
  1324. *****************************************************************/
  1325. /**
  1326. * Allocate vectors used with this thread.
  1327. * We are not testing the return, because callocz does this and shutdown the software
  1328. * case it was not possible to allocate.
  1329. *
  1330. * @param apps is apps enabled?
  1331. */
  1332. static void ebpf_vfs_allocate_global_vectors(int apps)
  1333. {
  1334. memset(vfs_aggregated_data, 0, sizeof(vfs_aggregated_data));
  1335. memset(vfs_publish_aggregated, 0, sizeof(vfs_publish_aggregated));
  1336. vfs_hash_values = callocz(ebpf_nprocs, sizeof(netdata_idx_t));
  1337. vfs_vector = callocz(ebpf_nprocs, sizeof(netdata_publish_vfs_t));
  1338. if (apps)
  1339. vfs_pid = callocz((size_t)pid_max, sizeof(netdata_publish_vfs_t *));
  1340. }
  1341. /*****************************************************************
  1342. *
  1343. * EBPF VFS THREAD
  1344. *
  1345. *****************************************************************/
  1346. /**
  1347. * Process thread
  1348. *
  1349. * Thread used to generate process charts.
  1350. *
  1351. * @param ptr a pointer to `struct ebpf_module`
  1352. *
  1353. * @return It always return NULL
  1354. */
  1355. void *ebpf_vfs_thread(void *ptr)
  1356. {
  1357. netdata_thread_cleanup_push(ebpf_vfs_exit, ptr);
  1358. ebpf_module_t *em = (ebpf_module_t *)ptr;
  1359. em->maps = vfs_maps;
  1360. ebpf_update_pid_table(&vfs_maps[NETDATA_VFS_PID], em);
  1361. ebpf_vfs_allocate_global_vectors(em->apps_charts);
  1362. if (!em->enabled)
  1363. goto endvfs;
  1364. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  1365. if (!em->probe_links) {
  1366. em->enabled = CONFIG_BOOLEAN_NO;
  1367. goto endvfs;
  1368. }
  1369. int algorithms[NETDATA_KEY_PUBLISH_VFS_END] = {
  1370. NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX,NETDATA_EBPF_INCREMENTAL_IDX,
  1371. NETDATA_EBPF_INCREMENTAL_IDX, NETDATA_EBPF_INCREMENTAL_IDX,NETDATA_EBPF_INCREMENTAL_IDX
  1372. };
  1373. ebpf_global_labels(vfs_aggregated_data, vfs_publish_aggregated, vfs_dimension_names,
  1374. vfs_id_names, algorithms, NETDATA_KEY_PUBLISH_VFS_END);
  1375. pthread_mutex_lock(&lock);
  1376. ebpf_create_global_charts(em);
  1377. ebpf_update_stats(&plugin_statistics, em);
  1378. pthread_mutex_unlock(&lock);
  1379. vfs_collector(em);
  1380. endvfs:
  1381. if (!em->enabled)
  1382. ebpf_update_disabled_plugin_stats(em);
  1383. netdata_thread_cleanup_pop(1);
  1384. return NULL;
  1385. }