ebpf_dcstat.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "ebpf.h"
  3. #include "ebpf_dcstat.h"
  4. static char *dcstat_counter_dimension_name[NETDATA_DCSTAT_IDX_END] = { "ratio", "reference", "slow", "miss" };
  5. static netdata_syscall_stat_t dcstat_counter_aggregated_data[NETDATA_DCSTAT_IDX_END];
  6. static netdata_publish_syscall_t dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_END];
  7. netdata_dcstat_pid_t *dcstat_vector = NULL;
  8. netdata_publish_dcstat_t **dcstat_pid = NULL;
  9. static netdata_idx_t dcstat_hash_values[NETDATA_DCSTAT_IDX_END];
  10. static netdata_idx_t *dcstat_values = NULL;
  11. struct config dcstat_config = { .first_section = NULL,
  12. .last_section = NULL,
  13. .mutex = NETDATA_MUTEX_INITIALIZER,
  14. .index = { .avl_tree = { .root = NULL, .compar = appconfig_section_compare },
  15. .rwlock = AVL_LOCK_INITIALIZER } };
  16. ebpf_local_maps_t dcstat_maps[] = {{.name = "dcstat_global", .internal_input = NETDATA_DIRECTORY_CACHE_END,
  17. .user_input = 0, .type = NETDATA_EBPF_MAP_STATIC,
  18. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  19. {.name = "dcstat_pid", .internal_input = ND_EBPF_DEFAULT_PID_SIZE,
  20. .user_input = 0,
  21. .type = NETDATA_EBPF_MAP_RESIZABLE | NETDATA_EBPF_MAP_PID,
  22. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  23. {.name = "dcstat_ctrl", .internal_input = NETDATA_CONTROLLER_END,
  24. .user_input = 0,
  25. .type = NETDATA_EBPF_MAP_CONTROLLER,
  26. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED},
  27. {.name = NULL, .internal_input = 0, .user_input = 0,
  28. .type = NETDATA_EBPF_MAP_CONTROLLER,
  29. .map_fd = ND_EBPF_MAP_FD_NOT_INITIALIZED}};
  30. static ebpf_specify_name_t dc_optional_name[] = { {.program_name = "netdata_lookup_fast",
  31. .function_to_attach = "lookup_fast",
  32. .optional = NULL,
  33. .retprobe = CONFIG_BOOLEAN_NO},
  34. {.program_name = NULL}};
  35. netdata_ebpf_targets_t dc_targets[] = { {.name = "lookup_fast", .mode = EBPF_LOAD_TRAMPOLINE},
  36. {.name = "d_lookup", .mode = EBPF_LOAD_TRAMPOLINE},
  37. {.name = NULL, .mode = EBPF_LOAD_TRAMPOLINE}};
  38. #ifdef LIBBPF_MAJOR_VERSION
  39. #include "includes/dc.skel.h" // BTF code
  40. static struct dc_bpf *bpf_obj = NULL;
  41. /**
  42. * Disable probe
  43. *
  44. * Disable all probes to use exclusively another method.
  45. *
  46. * @param obj is the main structure for bpf objects
  47. */
  48. static inline void ebpf_dc_disable_probes(struct dc_bpf *obj)
  49. {
  50. bpf_program__set_autoload(obj->progs.netdata_lookup_fast_kprobe, false);
  51. bpf_program__set_autoload(obj->progs.netdata_d_lookup_kretprobe, false);
  52. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
  53. }
  54. /*
  55. * Disable trampoline
  56. *
  57. * Disable all trampoline to use exclusively another method.
  58. *
  59. * @param obj is the main structure for bpf objects.
  60. */
  61. static inline void ebpf_dc_disable_trampoline(struct dc_bpf *obj)
  62. {
  63. bpf_program__set_autoload(obj->progs.netdata_lookup_fast_fentry, false);
  64. bpf_program__set_autoload(obj->progs.netdata_d_lookup_fexit, false);
  65. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
  66. }
  67. /**
  68. * Set trampoline target
  69. *
  70. * Set the targets we will monitor.
  71. *
  72. * @param obj is the main structure for bpf objects.
  73. */
  74. static void ebpf_dc_set_trampoline_target(struct dc_bpf *obj)
  75. {
  76. bpf_program__set_attach_target(obj->progs.netdata_lookup_fast_fentry, 0,
  77. dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name);
  78. bpf_program__set_attach_target(obj->progs.netdata_d_lookup_fexit, 0,
  79. dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
  80. bpf_program__set_attach_target(obj->progs.netdata_dcstat_release_task_fentry, 0,
  81. EBPF_COMMON_FNCT_CLEAN_UP);
  82. }
  83. /**
  84. * Mount Attach Probe
  85. *
  86. * Attach probes to target
  87. *
  88. * @param obj is the main structure for bpf objects.
  89. *
  90. * @return It returns 0 on success and -1 otherwise.
  91. */
  92. static int ebpf_dc_attach_probes(struct dc_bpf *obj)
  93. {
  94. obj->links.netdata_d_lookup_kretprobe = bpf_program__attach_kprobe(obj->progs.netdata_d_lookup_kretprobe,
  95. true,
  96. dc_targets[NETDATA_DC_TARGET_D_LOOKUP].name);
  97. int ret = libbpf_get_error(obj->links.netdata_d_lookup_kretprobe);
  98. if (ret)
  99. return -1;
  100. char *lookup_name = (dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional) ?
  101. dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional :
  102. dc_targets[NETDATA_DC_TARGET_LOOKUP_FAST].name ;
  103. obj->links.netdata_lookup_fast_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_lookup_fast_kprobe,
  104. false,
  105. lookup_name);
  106. ret = libbpf_get_error(obj->links.netdata_lookup_fast_kprobe);
  107. if (ret)
  108. return -1;
  109. obj->links.netdata_dcstat_release_task_kprobe = bpf_program__attach_kprobe(obj->progs.netdata_dcstat_release_task_kprobe,
  110. false,
  111. EBPF_COMMON_FNCT_CLEAN_UP);
  112. ret = libbpf_get_error(obj->links.netdata_dcstat_release_task_kprobe);
  113. if (ret)
  114. return -1;
  115. return 0;
  116. }
  117. /**
  118. * Adjust Map Size
  119. *
  120. * Resize maps according input from users.
  121. *
  122. * @param obj is the main structure for bpf objects.
  123. * @param em structure with configuration
  124. */
  125. static void ebpf_dc_adjust_map_size(struct dc_bpf *obj, ebpf_module_t *em)
  126. {
  127. ebpf_update_map_size(obj->maps.dcstat_pid, &dcstat_maps[NETDATA_DCSTAT_PID_STATS],
  128. em, bpf_map__name(obj->maps.dcstat_pid));
  129. }
  130. /**
  131. * Set hash tables
  132. *
  133. * Set the values for maps according the value given by kernel.
  134. *
  135. * @param obj is the main structure for bpf objects.
  136. */
  137. static void ebpf_dc_set_hash_tables(struct dc_bpf *obj)
  138. {
  139. dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_global);
  140. dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd = bpf_map__fd(obj->maps.dcstat_pid);
  141. dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd = bpf_map__fd(obj->maps.dcstat_ctrl);
  142. }
  143. /**
  144. * Update Load
  145. *
  146. * For directory cache, some distributions change the function name, and we do not have condition to use
  147. * TRAMPOLINE like other functions.
  148. *
  149. * @param em structure with configuration
  150. *
  151. * @return When then symbols were not modified, it returns TRAMPOLINE, else it returns RETPROBE.
  152. */
  153. netdata_ebpf_program_loaded_t ebpf_dc_update_load(ebpf_module_t *em)
  154. {
  155. if (!strcmp(dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].optional,
  156. dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach))
  157. return EBPF_LOAD_TRAMPOLINE;
  158. if (em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode != EBPF_LOAD_RETPROBE)
  159. info("When your kernel was compiled the symbol %s was modified, instead to use `trampoline`, the plugin will use `probes`.",
  160. dc_optional_name[NETDATA_DC_TARGET_LOOKUP_FAST].function_to_attach);
  161. return EBPF_LOAD_RETPROBE;
  162. }
  163. /**
  164. * Disable Release Task
  165. *
  166. * Disable release task when apps is not enabled.
  167. *
  168. * @param obj is the main structure for bpf objects.
  169. */
  170. static void ebpf_dc_disable_release_task(struct dc_bpf *obj)
  171. {
  172. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_kprobe, false);
  173. bpf_program__set_autoload(obj->progs.netdata_dcstat_release_task_fentry, false);
  174. }
  175. /**
  176. * Load and attach
  177. *
  178. * Load and attach the eBPF code in kernel.
  179. *
  180. * @param obj is the main structure for bpf objects.
  181. * @param em structure with configuration
  182. *
  183. * @return it returns 0 on success and -1 otherwise
  184. */
  185. static inline int ebpf_dc_load_and_attach(struct dc_bpf *obj, ebpf_module_t *em)
  186. {
  187. netdata_ebpf_program_loaded_t test = ebpf_dc_update_load(em);
  188. if (test == EBPF_LOAD_TRAMPOLINE) {
  189. ebpf_dc_disable_probes(obj);
  190. ebpf_dc_set_trampoline_target(obj);
  191. } else {
  192. ebpf_dc_disable_trampoline(obj);
  193. }
  194. ebpf_dc_adjust_map_size(obj, em);
  195. if (!em->apps_charts && !em->cgroup_charts)
  196. ebpf_dc_disable_release_task(obj);
  197. int ret = dc_bpf__load(obj);
  198. if (ret) {
  199. return ret;
  200. }
  201. ret = (test == EBPF_LOAD_TRAMPOLINE) ? dc_bpf__attach(obj) : ebpf_dc_attach_probes(obj);
  202. if (!ret) {
  203. ebpf_dc_set_hash_tables(obj);
  204. ebpf_update_controller(dcstat_maps[NETDATA_DCSTAT_CTRL].map_fd, em);
  205. }
  206. return ret;
  207. }
  208. #endif
  209. /*****************************************************************
  210. *
  211. * COMMON FUNCTIONS
  212. *
  213. *****************************************************************/
  214. /**
  215. * Update publish
  216. *
  217. * Update publish values before to write dimension.
  218. *
  219. * @param out structure that will receive data.
  220. * @param cache_access number of access to directory cache.
  221. * @param not_found number of files not found on the file system
  222. */
  223. void dcstat_update_publish(netdata_publish_dcstat_t *out, uint64_t cache_access, uint64_t not_found)
  224. {
  225. NETDATA_DOUBLE successful_access = (NETDATA_DOUBLE) (((long long)cache_access) - ((long long)not_found));
  226. NETDATA_DOUBLE ratio = (cache_access) ? successful_access/(NETDATA_DOUBLE)cache_access : 0;
  227. out->ratio = (long long )(ratio*100);
  228. }
  229. /*****************************************************************
  230. *
  231. * FUNCTIONS TO CLOSE THE THREAD
  232. *
  233. *****************************************************************/
  234. /**
  235. * Clean names
  236. *
  237. * Clean the optional names allocated during startup.
  238. */
  239. void ebpf_dcstat_clean_names()
  240. {
  241. size_t i = 0;
  242. while (dc_optional_name[i].program_name) {
  243. freez(dc_optional_name[i].optional);
  244. i++;
  245. }
  246. }
  247. /**
  248. * DCstat Free
  249. *
  250. * Cleanup variables after child threads to stop
  251. *
  252. * @param ptr thread data.
  253. */
  254. static void ebpf_dcstat_free(ebpf_module_t *em )
  255. {
  256. pthread_mutex_lock(&ebpf_exit_cleanup);
  257. em->thread->enabled = NETDATA_THREAD_EBPF_STOPPING;
  258. pthread_mutex_unlock(&ebpf_exit_cleanup);
  259. freez(dcstat_vector);
  260. freez(dcstat_values);
  261. ebpf_cleanup_publish_syscall(dcstat_counter_publish_aggregated);
  262. ebpf_dcstat_clean_names();
  263. #ifdef LIBBPF_MAJOR_VERSION
  264. if (bpf_obj)
  265. dc_bpf__destroy(bpf_obj);
  266. #endif
  267. pthread_mutex_lock(&ebpf_exit_cleanup);
  268. em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
  269. pthread_mutex_unlock(&ebpf_exit_cleanup);
  270. }
  271. /**
  272. * DCstat exit
  273. *
  274. * Cancel child and exit.
  275. *
  276. * @param ptr thread data.
  277. */
  278. static void ebpf_dcstat_exit(void *ptr)
  279. {
  280. ebpf_module_t *em = (ebpf_module_t *)ptr;
  281. ebpf_dcstat_free(em);
  282. }
  283. /*****************************************************************
  284. *
  285. * APPS
  286. *
  287. *****************************************************************/
  288. /**
  289. * Create apps charts
  290. *
  291. * Call ebpf_create_chart to create the charts on apps submenu.
  292. *
  293. * @param em a pointer to the structure with the default values.
  294. */
  295. void ebpf_dcstat_create_apps_charts(struct ebpf_module *em, void *ptr)
  296. {
  297. struct target *root = ptr;
  298. ebpf_create_charts_on_apps(NETDATA_DC_HIT_CHART,
  299. "Percentage of files inside directory cache",
  300. EBPF_COMMON_DIMENSION_PERCENTAGE,
  301. NETDATA_DIRECTORY_CACHE_SUBMENU,
  302. NETDATA_EBPF_CHART_TYPE_LINE,
  303. 20100,
  304. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  305. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  306. ebpf_create_charts_on_apps(NETDATA_DC_REFERENCE_CHART,
  307. "Count file access",
  308. EBPF_COMMON_DIMENSION_FILES,
  309. NETDATA_DIRECTORY_CACHE_SUBMENU,
  310. NETDATA_EBPF_CHART_TYPE_STACKED,
  311. 20101,
  312. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  313. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  314. ebpf_create_charts_on_apps(NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  315. "Files not present inside directory cache",
  316. EBPF_COMMON_DIMENSION_FILES,
  317. NETDATA_DIRECTORY_CACHE_SUBMENU,
  318. NETDATA_EBPF_CHART_TYPE_STACKED,
  319. 20102,
  320. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  321. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  322. ebpf_create_charts_on_apps(NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  323. "Files not found",
  324. EBPF_COMMON_DIMENSION_FILES,
  325. NETDATA_DIRECTORY_CACHE_SUBMENU,
  326. NETDATA_EBPF_CHART_TYPE_STACKED,
  327. 20103,
  328. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  329. root, em->update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  330. em->apps_charts |= NETDATA_EBPF_APPS_FLAG_CHART_CREATED;
  331. }
  332. /*****************************************************************
  333. *
  334. * MAIN LOOP
  335. *
  336. *****************************************************************/
  337. /**
  338. * Apps Accumulator
  339. *
  340. * Sum all values read from kernel and store in the first address.
  341. *
  342. * @param out the vector with read values.
  343. */
  344. static void dcstat_apps_accumulator(netdata_dcstat_pid_t *out)
  345. {
  346. int i, end = (running_on_kernel >= NETDATA_KERNEL_V4_15) ? ebpf_nprocs : 1;
  347. netdata_dcstat_pid_t *total = &out[0];
  348. for (i = 1; i < end; i++) {
  349. netdata_dcstat_pid_t *w = &out[i];
  350. total->cache_access += w->cache_access;
  351. total->file_system += w->file_system;
  352. total->not_found += w->not_found;
  353. }
  354. }
  355. /**
  356. * Save PID values
  357. *
  358. * Save the current values inside the structure
  359. *
  360. * @param out vector used to plot charts
  361. * @param publish vector with values read from hash tables.
  362. */
  363. static inline void dcstat_save_pid_values(netdata_publish_dcstat_t *out, netdata_dcstat_pid_t *publish)
  364. {
  365. memcpy(&out->curr, &publish[0], sizeof(netdata_dcstat_pid_t));
  366. }
  367. /**
  368. * Fill PID
  369. *
  370. * Fill PID structures
  371. *
  372. * @param current_pid pid that we are collecting data
  373. * @param out values read from hash tables;
  374. */
  375. static void dcstat_fill_pid(uint32_t current_pid, netdata_dcstat_pid_t *publish)
  376. {
  377. netdata_publish_dcstat_t *curr = dcstat_pid[current_pid];
  378. if (!curr) {
  379. curr = callocz(1, sizeof(netdata_publish_dcstat_t));
  380. dcstat_pid[current_pid] = curr;
  381. }
  382. dcstat_save_pid_values(curr, publish);
  383. }
  384. /**
  385. * Read APPS table
  386. *
  387. * Read the apps table and store data inside the structure.
  388. */
  389. static void read_apps_table()
  390. {
  391. netdata_dcstat_pid_t *cv = dcstat_vector;
  392. uint32_t key;
  393. struct pid_stat *pids = root_of_pids;
  394. int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
  395. size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
  396. while (pids) {
  397. key = pids->pid;
  398. if (bpf_map_lookup_elem(fd, &key, cv)) {
  399. pids = pids->next;
  400. continue;
  401. }
  402. dcstat_apps_accumulator(cv);
  403. dcstat_fill_pid(key, cv);
  404. // We are cleaning to avoid passing data read from one process to other.
  405. memset(cv, 0, length);
  406. pids = pids->next;
  407. }
  408. }
  409. /**
  410. * Update cgroup
  411. *
  412. * Update cgroup data based in
  413. */
  414. static void ebpf_update_dc_cgroup()
  415. {
  416. netdata_dcstat_pid_t *cv = dcstat_vector;
  417. int fd = dcstat_maps[NETDATA_DCSTAT_PID_STATS].map_fd;
  418. size_t length = sizeof(netdata_dcstat_pid_t)*ebpf_nprocs;
  419. ebpf_cgroup_target_t *ect;
  420. pthread_mutex_lock(&mutex_cgroup_shm);
  421. for (ect = ebpf_cgroup_pids; ect; ect = ect->next) {
  422. struct pid_on_target2 *pids;
  423. for (pids = ect->pids; pids; pids = pids->next) {
  424. int pid = pids->pid;
  425. netdata_dcstat_pid_t *out = &pids->dc;
  426. if (likely(dcstat_pid) && dcstat_pid[pid]) {
  427. netdata_publish_dcstat_t *in = dcstat_pid[pid];
  428. memcpy(out, &in->curr, sizeof(netdata_dcstat_pid_t));
  429. } else {
  430. memset(cv, 0, length);
  431. if (bpf_map_lookup_elem(fd, &pid, cv)) {
  432. continue;
  433. }
  434. dcstat_apps_accumulator(cv);
  435. memcpy(out, cv, sizeof(netdata_dcstat_pid_t));
  436. }
  437. }
  438. }
  439. pthread_mutex_unlock(&mutex_cgroup_shm);
  440. }
  441. /**
  442. * Read global table
  443. *
  444. * Read the table with number of calls for all functions
  445. */
  446. static void ebpf_dc_read_global_table()
  447. {
  448. uint32_t idx;
  449. netdata_idx_t *val = dcstat_hash_values;
  450. netdata_idx_t *stored = dcstat_values;
  451. int fd = dcstat_maps[NETDATA_DCSTAT_GLOBAL_STATS].map_fd;
  452. for (idx = NETDATA_KEY_DC_REFERENCE; idx < NETDATA_DIRECTORY_CACHE_END; idx++) {
  453. if (!bpf_map_lookup_elem(fd, &idx, stored)) {
  454. int i;
  455. int end = ebpf_nprocs;
  456. netdata_idx_t total = 0;
  457. for (i = 0; i < end; i++)
  458. total += stored[i];
  459. val[idx] = total;
  460. }
  461. }
  462. }
  463. /**
  464. * Cachestat sum PIDs
  465. *
  466. * Sum values for all PIDs associated to a group
  467. *
  468. * @param publish output structure.
  469. * @param root structure with listed IPs
  470. */
  471. void ebpf_dcstat_sum_pids(netdata_publish_dcstat_t *publish, struct pid_on_target *root)
  472. {
  473. memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
  474. netdata_dcstat_pid_t *dst = &publish->curr;
  475. while (root) {
  476. int32_t pid = root->pid;
  477. netdata_publish_dcstat_t *w = dcstat_pid[pid];
  478. if (w) {
  479. netdata_dcstat_pid_t *src = &w->curr;
  480. dst->cache_access += src->cache_access;
  481. dst->file_system += src->file_system;
  482. dst->not_found += src->not_found;
  483. }
  484. root = root->next;
  485. }
  486. }
  487. /**
  488. * Send data to Netdata calling auxiliary functions.
  489. *
  490. * @param root the target list.
  491. */
  492. void ebpf_dcache_send_apps_data(struct target *root)
  493. {
  494. struct target *w;
  495. collected_number value;
  496. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_HIT_CHART);
  497. for (w = root; w; w = w->next) {
  498. if (unlikely(w->exposed && w->processes)) {
  499. ebpf_dcstat_sum_pids(&w->dcstat, w->root_pid);
  500. uint64_t cache = w->dcstat.curr.cache_access;
  501. uint64_t not_found = w->dcstat.curr.not_found;
  502. dcstat_update_publish(&w->dcstat, cache, not_found);
  503. value = (collected_number) w->dcstat.ratio;
  504. write_chart_dimension(w->name, value);
  505. }
  506. }
  507. write_end_chart();
  508. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_REFERENCE_CHART);
  509. for (w = root; w; w = w->next) {
  510. if (unlikely(w->exposed && w->processes)) {
  511. if (w->dcstat.curr.cache_access < w->dcstat.prev.cache_access) {
  512. w->dcstat.prev.cache_access = 0;
  513. }
  514. w->dcstat.cache_access = (long long)w->dcstat.curr.cache_access - (long long)w->dcstat.prev.cache_access;
  515. value = (collected_number) w->dcstat.cache_access;
  516. write_chart_dimension(w->name, value);
  517. w->dcstat.prev.cache_access = w->dcstat.curr.cache_access;
  518. }
  519. }
  520. write_end_chart();
  521. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
  522. for (w = root; w; w = w->next) {
  523. if (unlikely(w->exposed && w->processes)) {
  524. if (w->dcstat.curr.file_system < w->dcstat.prev.file_system) {
  525. w->dcstat.prev.file_system = 0;
  526. }
  527. value = (collected_number) (!w->dcstat.cache_access) ? 0 :
  528. (long long )w->dcstat.curr.file_system - (long long)w->dcstat.prev.file_system;
  529. write_chart_dimension(w->name, value);
  530. w->dcstat.prev.file_system = w->dcstat.curr.file_system;
  531. }
  532. }
  533. write_end_chart();
  534. write_begin_chart(NETDATA_APPS_FAMILY, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
  535. for (w = root; w; w = w->next) {
  536. if (unlikely(w->exposed && w->processes)) {
  537. if (w->dcstat.curr.not_found < w->dcstat.prev.not_found) {
  538. w->dcstat.prev.not_found = 0;
  539. }
  540. value = (collected_number) (!w->dcstat.cache_access) ? 0 :
  541. (long long)w->dcstat.curr.not_found - (long long)w->dcstat.prev.not_found;
  542. write_chart_dimension(w->name, value);
  543. w->dcstat.prev.not_found = w->dcstat.curr.not_found;
  544. }
  545. }
  546. write_end_chart();
  547. }
  548. /**
  549. * Send global
  550. *
  551. * Send global charts to Netdata
  552. */
  553. static void dcstat_send_global(netdata_publish_dcstat_t *publish)
  554. {
  555. dcstat_update_publish(publish, dcstat_hash_values[NETDATA_KEY_DC_REFERENCE],
  556. dcstat_hash_values[NETDATA_KEY_DC_MISS]);
  557. netdata_publish_syscall_t *ptr = dcstat_counter_publish_aggregated;
  558. netdata_idx_t value = dcstat_hash_values[NETDATA_KEY_DC_REFERENCE];
  559. if (value != ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall) {
  560. ptr[NETDATA_DCSTAT_IDX_REFERENCE].ncall = value - ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall;
  561. ptr[NETDATA_DCSTAT_IDX_REFERENCE].pcall = value;
  562. value = dcstat_hash_values[NETDATA_KEY_DC_SLOW];
  563. ptr[NETDATA_DCSTAT_IDX_SLOW].ncall = value - ptr[NETDATA_DCSTAT_IDX_SLOW].pcall;
  564. ptr[NETDATA_DCSTAT_IDX_SLOW].pcall = value;
  565. value = dcstat_hash_values[NETDATA_KEY_DC_MISS];
  566. ptr[NETDATA_DCSTAT_IDX_MISS].ncall = value - ptr[NETDATA_DCSTAT_IDX_MISS].pcall;
  567. ptr[NETDATA_DCSTAT_IDX_MISS].pcall = value;
  568. } else {
  569. ptr[NETDATA_DCSTAT_IDX_REFERENCE].ncall = 0;
  570. ptr[NETDATA_DCSTAT_IDX_SLOW].ncall = 0;
  571. ptr[NETDATA_DCSTAT_IDX_MISS].ncall = 0;
  572. }
  573. ebpf_one_dimension_write_charts(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
  574. ptr[NETDATA_DCSTAT_IDX_RATIO].dimension, publish->ratio);
  575. write_count_chart(
  576. NETDATA_DC_REFERENCE_CHART, NETDATA_FILESYSTEM_FAMILY,
  577. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3);
  578. }
  579. /**
  580. * Create specific directory cache charts
  581. *
  582. * Create charts for cgroup/application.
  583. *
  584. * @param type the chart type.
  585. * @param update_every value to overwrite the update frequency set by the server.
  586. */
  587. static void ebpf_create_specific_dc_charts(char *type, int update_every)
  588. {
  589. ebpf_create_chart(type, NETDATA_DC_HIT_CHART, "Percentage of files inside directory cache",
  590. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  591. NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  592. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700,
  593. ebpf_create_global_dimension,
  594. dcstat_counter_publish_aggregated, 1, update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  595. ebpf_create_chart(type, NETDATA_DC_REFERENCE_CHART, "Count file access",
  596. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  597. NETDATA_CGROUP_DC_REFERENCE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  598. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701,
  599. ebpf_create_global_dimension,
  600. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 1,
  601. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  602. ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  603. "Files not present inside directory cache",
  604. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  605. NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  606. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702,
  607. ebpf_create_global_dimension,
  608. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW], 1,
  609. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  610. ebpf_create_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  611. "Files not found",
  612. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  613. NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_CHART_TYPE_LINE,
  614. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703,
  615. ebpf_create_global_dimension,
  616. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS], 1,
  617. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  618. }
  619. /**
  620. * Obsolete specific directory cache charts
  621. *
  622. * Obsolete charts for cgroup/application.
  623. *
  624. * @param type the chart type.
  625. * @param update_every value to overwrite the update frequency set by the server.
  626. */
  627. static void ebpf_obsolete_specific_dc_charts(char *type, int update_every)
  628. {
  629. ebpf_write_chart_obsolete(type, NETDATA_DC_HIT_CHART,
  630. "Percentage of files inside directory cache",
  631. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  632. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_HIT_RATIO_CONTEXT,
  633. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5700, update_every);
  634. ebpf_write_chart_obsolete(type, NETDATA_DC_REFERENCE_CHART,
  635. "Count file access",
  636. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  637. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_REFERENCE_CONTEXT,
  638. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5701, update_every);
  639. ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  640. "Files not present inside directory cache",
  641. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  642. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_CACHE_CONTEXT,
  643. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5702, update_every);
  644. ebpf_write_chart_obsolete(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  645. "Files not found",
  646. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  647. NETDATA_EBPF_CHART_TYPE_LINE, NETDATA_CGROUP_DC_NOT_FOUND_CONTEXT,
  648. NETDATA_CHART_PRIO_CGROUPS_CONTAINERS + 5703, update_every);
  649. }
  650. /**
  651. * Cachestat sum PIDs
  652. *
  653. * Sum values for all PIDs associated to a group
  654. *
  655. * @param publish output structure.
  656. * @param root structure with listed IPs
  657. */
  658. void ebpf_dc_sum_cgroup_pids(netdata_publish_dcstat_t *publish, struct pid_on_target2 *root)
  659. {
  660. memset(&publish->curr, 0, sizeof(netdata_dcstat_pid_t));
  661. netdata_dcstat_pid_t *dst = &publish->curr;
  662. while (root) {
  663. netdata_dcstat_pid_t *src = &root->dc;
  664. dst->cache_access += src->cache_access;
  665. dst->file_system += src->file_system;
  666. dst->not_found += src->not_found;
  667. root = root->next;
  668. }
  669. }
  670. /**
  671. * Calc chart values
  672. *
  673. * Do necessary math to plot charts.
  674. */
  675. void ebpf_dc_calc_chart_values()
  676. {
  677. ebpf_cgroup_target_t *ect;
  678. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  679. ebpf_dc_sum_cgroup_pids(&ect->publish_dc, ect->pids);
  680. uint64_t cache = ect->publish_dc.curr.cache_access;
  681. uint64_t not_found = ect->publish_dc.curr.not_found;
  682. dcstat_update_publish(&ect->publish_dc, cache, not_found);
  683. ect->publish_dc.cache_access = (long long)ect->publish_dc.curr.cache_access -
  684. (long long)ect->publish_dc.prev.cache_access;
  685. ect->publish_dc.prev.cache_access = ect->publish_dc.curr.cache_access;
  686. if (ect->publish_dc.curr.not_found < ect->publish_dc.prev.not_found) {
  687. ect->publish_dc.prev.not_found = 0;
  688. }
  689. }
  690. }
  691. /**
  692. * Create Systemd directory cache Charts
  693. *
  694. * Create charts when systemd is enabled
  695. *
  696. * @param update_every value to overwrite the update frequency set by the server.
  697. **/
  698. static void ebpf_create_systemd_dc_charts(int update_every)
  699. {
  700. ebpf_create_charts_on_systemd(NETDATA_DC_HIT_CHART,
  701. "Percentage of files inside directory cache",
  702. EBPF_COMMON_DIMENSION_PERCENTAGE,
  703. NETDATA_DIRECTORY_CACHE_SUBMENU,
  704. NETDATA_EBPF_CHART_TYPE_LINE,
  705. 21200,
  706. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  707. NETDATA_SYSTEMD_DC_HIT_RATIO_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  708. update_every);
  709. ebpf_create_charts_on_systemd(NETDATA_DC_REFERENCE_CHART,
  710. "Count file access",
  711. EBPF_COMMON_DIMENSION_FILES,
  712. NETDATA_DIRECTORY_CACHE_SUBMENU,
  713. NETDATA_EBPF_CHART_TYPE_LINE,
  714. 21201,
  715. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  716. NETDATA_SYSTEMD_DC_REFERENCE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  717. update_every);
  718. ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_CACHE_CHART,
  719. "Files not present inside directory cache",
  720. EBPF_COMMON_DIMENSION_FILES,
  721. NETDATA_DIRECTORY_CACHE_SUBMENU,
  722. NETDATA_EBPF_CHART_TYPE_LINE,
  723. 21202,
  724. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  725. NETDATA_SYSTEMD_DC_NOT_CACHE_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  726. update_every);
  727. ebpf_create_charts_on_systemd(NETDATA_DC_REQUEST_NOT_FOUND_CHART,
  728. "Files not found",
  729. EBPF_COMMON_DIMENSION_FILES,
  730. NETDATA_DIRECTORY_CACHE_SUBMENU,
  731. NETDATA_EBPF_CHART_TYPE_LINE,
  732. 21202,
  733. ebpf_algorithms[NETDATA_EBPF_ABSOLUTE_IDX],
  734. NETDATA_SYSTEMD_DC_NOT_FOUND_CONTEXT, NETDATA_EBPF_MODULE_NAME_DCSTAT,
  735. update_every);
  736. }
  737. /**
  738. * Send Directory Cache charts
  739. *
  740. * Send collected data to Netdata.
  741. */
  742. static void ebpf_send_systemd_dc_charts()
  743. {
  744. collected_number value;
  745. ebpf_cgroup_target_t *ect;
  746. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_HIT_CHART);
  747. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  748. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  749. write_chart_dimension(ect->name, (long long) ect->publish_dc.ratio);
  750. }
  751. }
  752. write_end_chart();
  753. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REFERENCE_CHART);
  754. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  755. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  756. write_chart_dimension(ect->name, (long long) ect->publish_dc.cache_access);
  757. }
  758. }
  759. write_end_chart();
  760. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
  761. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  762. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  763. value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
  764. (long long )ect->publish_dc.curr.file_system - (long long)ect->publish_dc.prev.file_system;
  765. ect->publish_dc.prev.file_system = ect->publish_dc.curr.file_system;
  766. write_chart_dimension(ect->name, (long long) value);
  767. }
  768. }
  769. write_end_chart();
  770. write_begin_chart(NETDATA_SERVICE_FAMILY, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
  771. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  772. if (unlikely(ect->systemd) && unlikely(ect->updated)) {
  773. value = (collected_number) (!ect->publish_dc.cache_access) ? 0 :
  774. (long long)ect->publish_dc.curr.not_found - (long long)ect->publish_dc.prev.not_found;
  775. ect->publish_dc.prev.not_found = ect->publish_dc.curr.not_found;
  776. write_chart_dimension(ect->name, (long long) value);
  777. }
  778. }
  779. write_end_chart();
  780. }
  781. /**
  782. * Send Directory Cache charts
  783. *
  784. * Send collected data to Netdata.
  785. *
  786. */
  787. static void ebpf_send_specific_dc_data(char *type, netdata_publish_dcstat_t *pdc)
  788. {
  789. collected_number value;
  790. write_begin_chart(type, NETDATA_DC_HIT_CHART);
  791. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_RATIO].name,
  792. (long long) pdc->ratio);
  793. write_end_chart();
  794. write_begin_chart(type, NETDATA_DC_REFERENCE_CHART);
  795. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE].name,
  796. (long long) pdc->cache_access);
  797. write_end_chart();
  798. value = (collected_number) (!pdc->cache_access) ? 0 :
  799. (long long )pdc->curr.file_system - (long long)pdc->prev.file_system;
  800. pdc->prev.file_system = pdc->curr.file_system;
  801. write_begin_chart(type, NETDATA_DC_REQUEST_NOT_CACHE_CHART);
  802. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_SLOW].name, (long long) value);
  803. write_end_chart();
  804. value = (collected_number) (!pdc->cache_access) ? 0 :
  805. (long long)pdc->curr.not_found - (long long)pdc->prev.not_found;
  806. pdc->prev.not_found = pdc->curr.not_found;
  807. write_begin_chart(type, NETDATA_DC_REQUEST_NOT_FOUND_CHART);
  808. write_chart_dimension(dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_MISS].name, (long long) value);
  809. write_end_chart();
  810. }
  811. /**
  812. * Send data to Netdata calling auxiliary functions.
  813. *
  814. * @param update_every value to overwrite the update frequency set by the server.
  815. */
  816. void ebpf_dc_send_cgroup_data(int update_every)
  817. {
  818. if (!ebpf_cgroup_pids)
  819. return;
  820. pthread_mutex_lock(&mutex_cgroup_shm);
  821. ebpf_cgroup_target_t *ect;
  822. ebpf_dc_calc_chart_values();
  823. int has_systemd = shm_ebpf_cgroup.header->systemd_enabled;
  824. if (has_systemd) {
  825. if (send_cgroup_chart) {
  826. ebpf_create_systemd_dc_charts(update_every);
  827. }
  828. ebpf_send_systemd_dc_charts();
  829. }
  830. for (ect = ebpf_cgroup_pids; ect ; ect = ect->next) {
  831. if (ect->systemd)
  832. continue;
  833. if (!(ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) && ect->updated) {
  834. ebpf_create_specific_dc_charts(ect->name, update_every);
  835. ect->flags |= NETDATA_EBPF_CGROUP_HAS_DC_CHART;
  836. }
  837. if (ect->flags & NETDATA_EBPF_CGROUP_HAS_DC_CHART) {
  838. if (ect->updated) {
  839. ebpf_send_specific_dc_data(ect->name, &ect->publish_dc);
  840. } else {
  841. ebpf_obsolete_specific_dc_charts(ect->name, update_every);
  842. ect->flags &= ~NETDATA_EBPF_CGROUP_HAS_DC_CHART;
  843. }
  844. }
  845. }
  846. pthread_mutex_unlock(&mutex_cgroup_shm);
  847. }
  848. /**
  849. * Main loop for this collector.
  850. */
  851. static void dcstat_collector(ebpf_module_t *em)
  852. {
  853. netdata_publish_dcstat_t publish;
  854. memset(&publish, 0, sizeof(publish));
  855. int cgroups = em->cgroup_charts;
  856. int update_every = em->update_every;
  857. heartbeat_t hb;
  858. heartbeat_init(&hb);
  859. int counter = update_every - 1;
  860. while (!ebpf_exit_plugin) {
  861. (void)heartbeat_next(&hb, USEC_PER_SEC);
  862. if (ebpf_exit_plugin || ++counter != update_every)
  863. continue;
  864. counter = 0;
  865. netdata_apps_integration_flags_t apps = em->apps_charts;
  866. ebpf_dc_read_global_table();
  867. pthread_mutex_lock(&collect_data_mutex);
  868. if (apps)
  869. read_apps_table();
  870. if (cgroups)
  871. ebpf_update_dc_cgroup();
  872. pthread_mutex_lock(&lock);
  873. dcstat_send_global(&publish);
  874. if (apps & NETDATA_EBPF_APPS_FLAG_CHART_CREATED)
  875. ebpf_dcache_send_apps_data(apps_groups_root_target);
  876. if (cgroups)
  877. ebpf_dc_send_cgroup_data(update_every);
  878. pthread_mutex_unlock(&lock);
  879. pthread_mutex_unlock(&collect_data_mutex);
  880. }
  881. }
  882. /*****************************************************************
  883. *
  884. * INITIALIZE THREAD
  885. *
  886. *****************************************************************/
  887. /**
  888. * Create filesystem charts
  889. *
  890. * Call ebpf_create_chart to create the charts for the collector.
  891. *
  892. * @param update_every value to overwrite the update frequency set by the server.
  893. */
  894. static void ebpf_create_filesystem_charts(int update_every)
  895. {
  896. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_HIT_CHART,
  897. "Percentage of files inside directory cache",
  898. EBPF_COMMON_DIMENSION_PERCENTAGE, NETDATA_DIRECTORY_CACHE_SUBMENU,
  899. NULL,
  900. NETDATA_EBPF_CHART_TYPE_LINE,
  901. 21200,
  902. ebpf_create_global_dimension,
  903. dcstat_counter_publish_aggregated, 1, update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  904. ebpf_create_chart(NETDATA_FILESYSTEM_FAMILY, NETDATA_DC_REFERENCE_CHART,
  905. "Variables used to calculate hit ratio.",
  906. EBPF_COMMON_DIMENSION_FILES, NETDATA_DIRECTORY_CACHE_SUBMENU,
  907. NULL,
  908. NETDATA_EBPF_CHART_TYPE_LINE,
  909. 21201,
  910. ebpf_create_global_dimension,
  911. &dcstat_counter_publish_aggregated[NETDATA_DCSTAT_IDX_REFERENCE], 3,
  912. update_every, NETDATA_EBPF_MODULE_NAME_DCSTAT);
  913. fflush(stdout);
  914. }
  915. /**
  916. * Allocate vectors used with this thread.
  917. *
  918. * We are not testing the return, because callocz does this and shutdown the software
  919. * case it was not possible to allocate.
  920. *
  921. * @param apps is apps enabled?
  922. */
  923. static void ebpf_dcstat_allocate_global_vectors(int apps)
  924. {
  925. if (apps)
  926. dcstat_pid = callocz((size_t)pid_max, sizeof(netdata_publish_dcstat_t *));
  927. dcstat_vector = callocz((size_t)ebpf_nprocs, sizeof(netdata_dcstat_pid_t));
  928. dcstat_values = callocz((size_t)ebpf_nprocs, sizeof(netdata_idx_t));
  929. memset(dcstat_counter_aggregated_data, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_syscall_stat_t));
  930. memset(dcstat_counter_publish_aggregated, 0, NETDATA_DCSTAT_IDX_END * sizeof(netdata_publish_syscall_t));
  931. }
  932. /*****************************************************************
  933. *
  934. * MAIN THREAD
  935. *
  936. *****************************************************************/
  937. /*
  938. * Load BPF
  939. *
  940. * Load BPF files.
  941. *
  942. * @param em the structure with configuration
  943. */
  944. static int ebpf_dcstat_load_bpf(ebpf_module_t *em)
  945. {
  946. int ret = 0;
  947. ebpf_adjust_apps_cgroup(em, em->targets[NETDATA_DC_TARGET_LOOKUP_FAST].mode);
  948. if (em->load & EBPF_LOAD_LEGACY) {
  949. em->probe_links = ebpf_load_program(ebpf_plugin_dir, em, running_on_kernel, isrh, &em->objects);
  950. if (!em->probe_links) {
  951. ret = -1;
  952. }
  953. }
  954. #ifdef LIBBPF_MAJOR_VERSION
  955. else {
  956. bpf_obj = dc_bpf__open();
  957. if (!bpf_obj)
  958. ret = -1;
  959. else
  960. ret = ebpf_dc_load_and_attach(bpf_obj, em);
  961. }
  962. #endif
  963. if (ret)
  964. error("%s %s", EBPF_DEFAULT_ERROR_MSG, em->thread_name);
  965. return ret;
  966. }
  967. /**
  968. * Directory Cache thread
  969. *
  970. * Thread used to make dcstat thread
  971. *
  972. * @param ptr a pointer to `struct ebpf_module`
  973. *
  974. * @return It always returns NULL
  975. */
  976. void *ebpf_dcstat_thread(void *ptr)
  977. {
  978. netdata_thread_cleanup_push(ebpf_dcstat_exit, ptr);
  979. ebpf_module_t *em = (ebpf_module_t *)ptr;
  980. em->maps = dcstat_maps;
  981. ebpf_update_pid_table(&dcstat_maps[NETDATA_DCSTAT_PID_STATS], em);
  982. ebpf_update_names(dc_optional_name, em);
  983. #ifdef LIBBPF_MAJOR_VERSION
  984. ebpf_adjust_thread_load(em, default_btf);
  985. #endif
  986. if (ebpf_dcstat_load_bpf(em)) {
  987. em->thread->enabled = NETDATA_THREAD_EBPF_STOPPED;
  988. goto enddcstat;
  989. }
  990. ebpf_dcstat_allocate_global_vectors(em->apps_charts);
  991. int algorithms[NETDATA_DCSTAT_IDX_END] = {
  992. NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX, NETDATA_EBPF_ABSOLUTE_IDX,
  993. NETDATA_EBPF_ABSOLUTE_IDX
  994. };
  995. ebpf_global_labels(dcstat_counter_aggregated_data, dcstat_counter_publish_aggregated,
  996. dcstat_counter_dimension_name, dcstat_counter_dimension_name,
  997. algorithms, NETDATA_DCSTAT_IDX_END);
  998. pthread_mutex_lock(&lock);
  999. ebpf_create_filesystem_charts(em->update_every);
  1000. ebpf_update_stats(&plugin_statistics, em);
  1001. pthread_mutex_unlock(&lock);
  1002. dcstat_collector(em);
  1003. enddcstat:
  1004. ebpf_update_disabled_plugin_stats(em);
  1005. netdata_thread_cleanup_pop(1);
  1006. return NULL;
  1007. }