proc_meminfo.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define PLUGIN_PROC_MODULE_MEMINFO_NAME "/proc/meminfo"
  4. #define CONFIG_SECTION_PLUGIN_PROC_MEMINFO "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_MEMINFO_NAME
  5. int do_proc_meminfo(int update_every, usec_t dt) {
  6. (void)dt;
  7. static procfile *ff = NULL;
  8. static int do_ram = -1
  9. , do_swap = -1
  10. , do_hwcorrupt = -1
  11. , do_committed = -1
  12. , do_writeback = -1
  13. , do_kernel = -1
  14. , do_slab = -1
  15. , do_hugepages = -1
  16. , do_transparent_hugepages = -1
  17. , do_reclaiming = -1
  18. , do_high_low = -1
  19. , do_cma = -1
  20. , do_directmap = -1;
  21. static ARL_BASE *arl_base = NULL;
  22. static ARL_ENTRY *arl_hwcorrupted = NULL, *arl_memavailable = NULL, *arl_hugepages_total = NULL,
  23. *arl_zswapped = NULL, *arl_high_low = NULL, *arl_cma_total = NULL,
  24. *arl_directmap4k = NULL, *arl_directmap2m = NULL, *arl_directmap4m = NULL, *arl_directmap1g = NULL;
  25. static unsigned long long
  26. MemTotal = 0
  27. , MemFree = 0
  28. , MemAvailable = 0
  29. , Buffers = 0
  30. , Cached = 0
  31. , SwapCached = 0
  32. , Active = 0
  33. , Inactive = 0
  34. , ActiveAnon = 0
  35. , InactiveAnon = 0
  36. , ActiveFile = 0
  37. , InactiveFile = 0
  38. , Unevictable = 0
  39. , Mlocked = 0
  40. , HighTotal = 0
  41. , HighFree = 0
  42. , LowTotal = 0
  43. , LowFree = 0
  44. , MmapCopy = 0
  45. , SwapTotal = 0
  46. , SwapFree = 0
  47. , Zswap = 0
  48. , Zswapped = 0
  49. , Dirty = 0
  50. , Writeback = 0
  51. , AnonPages = 0
  52. , Mapped = 0
  53. , Shmem = 0
  54. , KReclaimable = 0
  55. , Slab = 0
  56. , SReclaimable = 0
  57. , SUnreclaim = 0
  58. , KernelStack = 0
  59. , ShadowCallStack = 0
  60. , PageTables = 0
  61. , SecPageTables = 0
  62. , NFS_Unstable = 0
  63. , Bounce = 0
  64. , WritebackTmp = 0
  65. , CommitLimit = 0
  66. , Committed_AS = 0
  67. , VmallocTotal = 0
  68. , VmallocUsed = 0
  69. , VmallocChunk = 0
  70. , Percpu = 0
  71. //, EarlyMemtestBad = 0
  72. , HardwareCorrupted = 0
  73. , AnonHugePages = 0
  74. , ShmemHugePages = 0
  75. , ShmemPmdMapped = 0
  76. , FileHugePages = 0
  77. , FilePmdMapped = 0
  78. , CmaTotal = 0
  79. , CmaFree = 0
  80. //, Unaccepted = 0
  81. , HugePages_Total = 0
  82. , HugePages_Free = 0
  83. , HugePages_Rsvd = 0
  84. , HugePages_Surp = 0
  85. , Hugepagesize = 0
  86. //, Hugetlb = 0
  87. , DirectMap4k = 0
  88. , DirectMap2M = 0
  89. , DirectMap4M = 0
  90. , DirectMap1G = 0
  91. ;
  92. if(unlikely(!arl_base)) {
  93. do_ram = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "system ram", 1);
  94. do_swap = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "system swap", CONFIG_BOOLEAN_AUTO);
  95. do_hwcorrupt = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "hardware corrupted ECC", CONFIG_BOOLEAN_AUTO);
  96. do_committed = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "committed memory", 1);
  97. do_writeback = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "writeback memory", 1);
  98. do_kernel = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "kernel memory", 1);
  99. do_slab = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "slab memory", 1);
  100. do_hugepages = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "hugepages", CONFIG_BOOLEAN_AUTO);
  101. do_transparent_hugepages = config_get_boolean_ondemand(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "transparent hugepages", CONFIG_BOOLEAN_AUTO);
  102. do_reclaiming = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "memory reclaiming", CONFIG_BOOLEAN_AUTO);
  103. do_high_low = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "high low memory", CONFIG_BOOLEAN_AUTO);
  104. do_cma = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "cma memory", CONFIG_BOOLEAN_AUTO);
  105. do_directmap = config_get_boolean(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "direct maps", CONFIG_BOOLEAN_AUTO);
  106. // https://github.com/torvalds/linux/blob/master/fs/proc/meminfo.c
  107. arl_base = arl_create("meminfo", NULL, 60);
  108. arl_expect(arl_base, "MemTotal", &MemTotal);
  109. arl_expect(arl_base, "MemFree", &MemFree);
  110. arl_memavailable = arl_expect(arl_base, "MemAvailable", &MemAvailable);
  111. arl_expect(arl_base, "Buffers", &Buffers);
  112. arl_expect(arl_base, "Cached", &Cached);
  113. arl_expect(arl_base, "SwapCached", &SwapCached);
  114. arl_expect(arl_base, "Active", &Active);
  115. arl_expect(arl_base, "Inactive", &Inactive);
  116. arl_expect(arl_base, "Active(anon)", &ActiveAnon);
  117. arl_expect(arl_base, "Inactive(anon)", &InactiveAnon);
  118. arl_expect(arl_base, "Active(file)", &ActiveFile);
  119. arl_expect(arl_base, "Inactive(file)", &InactiveFile);
  120. arl_expect(arl_base, "Unevictable", &Unevictable);
  121. arl_expect(arl_base, "Mlocked", &Mlocked);
  122. // CONFIG_HIGHMEM
  123. arl_high_low = arl_expect(arl_base, "HighTotal", &HighTotal);
  124. arl_expect(arl_base, "HighFree", &HighFree);
  125. arl_expect(arl_base, "LowTotal", &LowTotal);
  126. arl_expect(arl_base, "LowFree", &LowFree);
  127. // CONFIG_MMU
  128. arl_expect(arl_base, "MmapCopy", &MmapCopy);
  129. arl_expect(arl_base, "SwapTotal", &SwapTotal);
  130. arl_expect(arl_base, "SwapFree", &SwapFree);
  131. // CONFIG_ZSWAP
  132. arl_zswapped = arl_expect(arl_base, "Zswap", &Zswap);
  133. arl_expect(arl_base, "Zswapped", &Zswapped);
  134. arl_expect(arl_base, "Dirty", &Dirty);
  135. arl_expect(arl_base, "Writeback", &Writeback);
  136. arl_expect(arl_base, "AnonPages", &AnonPages);
  137. arl_expect(arl_base, "Mapped", &Mapped);
  138. arl_expect(arl_base, "Shmem", &Shmem);
  139. arl_expect(arl_base, "KReclaimable", &KReclaimable);
  140. arl_expect(arl_base, "Slab", &Slab);
  141. arl_expect(arl_base, "SReclaimable", &SReclaimable);
  142. arl_expect(arl_base, "SUnreclaim", &SUnreclaim);
  143. arl_expect(arl_base, "KernelStack", &KernelStack);
  144. // CONFIG_SHADOW_CALL_STACK
  145. arl_expect(arl_base, "ShadowCallStack", &ShadowCallStack);
  146. arl_expect(arl_base, "PageTables", &PageTables);
  147. arl_expect(arl_base, "SecPageTables", &SecPageTables);
  148. arl_expect(arl_base, "NFS_Unstable", &NFS_Unstable);
  149. arl_expect(arl_base, "Bounce", &Bounce);
  150. arl_expect(arl_base, "WritebackTmp", &WritebackTmp);
  151. arl_expect(arl_base, "CommitLimit", &CommitLimit);
  152. arl_expect(arl_base, "Committed_AS", &Committed_AS);
  153. arl_expect(arl_base, "VmallocTotal", &VmallocTotal);
  154. arl_expect(arl_base, "VmallocUsed", &VmallocUsed);
  155. arl_expect(arl_base, "VmallocChunk", &VmallocChunk);
  156. arl_expect(arl_base, "Percpu", &Percpu);
  157. // CONFIG_MEMTEST
  158. //arl_expect(arl_base, "EarlyMemtestBad", &EarlyMemtestBad);
  159. // CONFIG_MEMORY_FAILURE
  160. arl_hwcorrupted = arl_expect(arl_base, "HardwareCorrupted", &HardwareCorrupted);
  161. // CONFIG_TRANSPARENT_HUGEPAGE
  162. arl_expect(arl_base, "AnonHugePages", &AnonHugePages);
  163. arl_expect(arl_base, "ShmemHugePages", &ShmemHugePages);
  164. arl_expect(arl_base, "ShmemPmdMapped", &ShmemPmdMapped);
  165. arl_expect(arl_base, "FileHugePages", &FileHugePages);
  166. arl_expect(arl_base, "FilePmdMapped", &FilePmdMapped);
  167. // CONFIG_CMA
  168. arl_cma_total = arl_expect(arl_base, "CmaTotal", &CmaTotal);
  169. arl_expect(arl_base, "CmaFree", &CmaFree);
  170. // CONFIG_UNACCEPTED_MEMORY
  171. //arl_expect(arl_base, "Unaccepted", &Unaccepted);
  172. // these appear only when hugepages are supported
  173. arl_hugepages_total = arl_expect(arl_base, "HugePages_Total", &HugePages_Total);
  174. arl_expect(arl_base, "HugePages_Free", &HugePages_Free);
  175. arl_expect(arl_base, "HugePages_Rsvd", &HugePages_Rsvd);
  176. arl_expect(arl_base, "HugePages_Surp", &HugePages_Surp);
  177. arl_expect(arl_base, "Hugepagesize", &Hugepagesize);
  178. //arl_expect(arl_base, "Hugetlb", &Hugetlb);
  179. arl_directmap4k = arl_expect(arl_base, "DirectMap4k", &DirectMap4k);
  180. arl_directmap2m = arl_expect(arl_base, "DirectMap2M", &DirectMap2M);
  181. arl_directmap4m = arl_expect(arl_base, "DirectMap4M", &DirectMap4M);
  182. arl_directmap1g = arl_expect(arl_base, "DirectMap1G", &DirectMap1G);
  183. }
  184. if(unlikely(!ff)) {
  185. char filename[FILENAME_MAX + 1];
  186. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/meminfo");
  187. ff = procfile_open(config_get(CONFIG_SECTION_PLUGIN_PROC_MEMINFO, "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
  188. if(unlikely(!ff))
  189. return 1;
  190. }
  191. ff = procfile_readall(ff);
  192. if(unlikely(!ff))
  193. return 0; // we return 0, so that we will retry to open it next time
  194. size_t lines = procfile_lines(ff), l;
  195. arl_begin(arl_base);
  196. for(l = 0; l < lines ;l++) {
  197. size_t words = procfile_linewords(ff, l);
  198. if(unlikely(words < 2)) continue;
  199. if(unlikely(arl_check(arl_base,
  200. procfile_lineword(ff, l, 0),
  201. procfile_lineword(ff, l, 1)))) break;
  202. }
  203. // http://calimeroteknik.free.fr/blag/?article20/really-used-memory-on-gnu-linux
  204. // KReclaimable includes SReclaimable, it was added in kernel v4.20
  205. unsigned long long reclaimable = KReclaimable > 0 ? KReclaimable : SReclaimable;
  206. unsigned long long MemCached = Cached + reclaimable - Shmem;
  207. unsigned long long MemUsed = MemTotal - MemFree - MemCached - Buffers;
  208. // The Linux kernel doesn't report ZFS ARC usage as cache memory (the ARC is included in the total used system memory)
  209. if (!inside_lxc_container) {
  210. MemCached += (zfs_arcstats_shrinkable_cache_size_bytes / 1024);
  211. MemUsed -= (zfs_arcstats_shrinkable_cache_size_bytes / 1024);
  212. MemAvailable += (zfs_arcstats_shrinkable_cache_size_bytes / 1024);
  213. }
  214. if(do_ram) {
  215. {
  216. static RRDSET *st_system_ram = NULL;
  217. static RRDDIM *rd_free = NULL, *rd_used = NULL, *rd_cached = NULL, *rd_buffers = NULL;
  218. if(unlikely(!st_system_ram)) {
  219. st_system_ram = rrdset_create_localhost(
  220. "system"
  221. , "ram"
  222. , NULL
  223. , "ram"
  224. , NULL
  225. , "System RAM"
  226. , "MiB"
  227. , PLUGIN_PROC_NAME
  228. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  229. , NETDATA_CHART_PRIO_SYSTEM_RAM
  230. , update_every
  231. , RRDSET_TYPE_STACKED
  232. );
  233. rd_free = rrddim_add(st_system_ram, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  234. rd_used = rrddim_add(st_system_ram, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  235. rd_cached = rrddim_add(st_system_ram, "cached", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  236. rd_buffers = rrddim_add(st_system_ram, "buffers", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  237. }
  238. rrddim_set_by_pointer(st_system_ram, rd_free, MemFree);
  239. rrddim_set_by_pointer(st_system_ram, rd_used, MemUsed);
  240. rrddim_set_by_pointer(st_system_ram, rd_cached, MemCached);
  241. rrddim_set_by_pointer(st_system_ram, rd_buffers, Buffers);
  242. rrdset_done(st_system_ram);
  243. }
  244. if(arl_memavailable->flags & ARL_ENTRY_FLAG_FOUND) {
  245. static RRDSET *st_mem_available = NULL;
  246. static RRDDIM *rd_avail = NULL;
  247. if(unlikely(!st_mem_available)) {
  248. st_mem_available = rrdset_create_localhost(
  249. "mem"
  250. , "available"
  251. , NULL
  252. , "overview"
  253. , NULL
  254. , "Available RAM for applications"
  255. , "MiB"
  256. , PLUGIN_PROC_NAME
  257. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  258. , NETDATA_CHART_PRIO_MEM_SYSTEM_AVAILABLE
  259. , update_every
  260. , RRDSET_TYPE_AREA
  261. );
  262. rd_avail = rrddim_add(st_mem_available, "MemAvailable", "avail", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  263. }
  264. rrddim_set_by_pointer(st_mem_available, rd_avail, MemAvailable);
  265. rrdset_done(st_mem_available);
  266. }
  267. }
  268. unsigned long long SwapUsed = SwapTotal - SwapFree;
  269. if(do_swap == CONFIG_BOOLEAN_YES || (do_swap == CONFIG_BOOLEAN_AUTO &&
  270. (SwapTotal || SwapUsed || SwapFree ||
  271. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  272. do_swap = CONFIG_BOOLEAN_YES;
  273. static RRDSET *st_system_swap = NULL;
  274. static RRDDIM *rd_free = NULL, *rd_used = NULL;
  275. if(unlikely(!st_system_swap)) {
  276. st_system_swap = rrdset_create_localhost(
  277. "mem"
  278. , "swap"
  279. , NULL
  280. , "swap"
  281. , NULL
  282. , "System Swap"
  283. , "MiB"
  284. , PLUGIN_PROC_NAME
  285. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  286. , NETDATA_CHART_PRIO_MEM_SWAP
  287. , update_every
  288. , RRDSET_TYPE_STACKED
  289. );
  290. rrdset_flag_set(st_system_swap, RRDSET_FLAG_DETAIL);
  291. rd_free = rrddim_add(st_system_swap, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  292. rd_used = rrddim_add(st_system_swap, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  293. }
  294. rrddim_set_by_pointer(st_system_swap, rd_used, SwapUsed);
  295. rrddim_set_by_pointer(st_system_swap, rd_free, SwapFree);
  296. rrdset_done(st_system_swap);
  297. {
  298. static RRDSET *st_mem_swap_cached = NULL;
  299. static RRDDIM *rd_cached = NULL;
  300. if (unlikely(!st_mem_swap_cached)) {
  301. st_mem_swap_cached = rrdset_create_localhost(
  302. "mem"
  303. , "swap_cached"
  304. , NULL
  305. , "swap"
  306. , NULL
  307. , "Swap Memory Cached in RAM"
  308. , "MiB"
  309. , PLUGIN_PROC_NAME
  310. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  311. , NETDATA_CHART_PRIO_MEM_SWAP + 1
  312. , update_every
  313. , RRDSET_TYPE_AREA
  314. );
  315. rd_cached = rrddim_add(st_mem_swap_cached, "cached", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  316. }
  317. rrddim_set_by_pointer(st_mem_swap_cached, rd_cached, SwapCached);
  318. rrdset_done(st_mem_swap_cached);
  319. }
  320. if(arl_zswapped->flags & ARL_ENTRY_FLAG_FOUND) {
  321. static RRDSET *st_mem_zswap = NULL;
  322. static RRDDIM *rd_zswap = NULL, *rd_zswapped = NULL;
  323. if (unlikely(!st_mem_zswap)) {
  324. st_mem_zswap = rrdset_create_localhost(
  325. "mem"
  326. , "zswap"
  327. , NULL
  328. , "zswap"
  329. , NULL
  330. , "Zswap Usage"
  331. , "MiB"
  332. , PLUGIN_PROC_NAME
  333. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  334. , NETDATA_CHART_PRIO_MEM_ZSWAP
  335. , update_every
  336. , RRDSET_TYPE_STACKED
  337. );
  338. rd_zswap = rrddim_add(st_mem_zswap, "zswap", "in-ram", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  339. rd_zswapped = rrddim_add(st_mem_zswap, "zswapped", "on-disk", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  340. }
  341. rrddim_set_by_pointer(st_mem_zswap, rd_zswap, Zswap);
  342. rrddim_set_by_pointer(st_mem_zswap, rd_zswapped, Zswapped);
  343. rrdset_done(st_mem_zswap);
  344. }
  345. }
  346. if(arl_hwcorrupted->flags & ARL_ENTRY_FLAG_FOUND &&
  347. (do_hwcorrupt == CONFIG_BOOLEAN_YES || (do_hwcorrupt == CONFIG_BOOLEAN_AUTO &&
  348. (HardwareCorrupted > 0 ||
  349. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES)))) {
  350. do_hwcorrupt = CONFIG_BOOLEAN_YES;
  351. static RRDSET *st_mem_hwcorrupt = NULL;
  352. static RRDDIM *rd_corrupted = NULL;
  353. if(unlikely(!st_mem_hwcorrupt)) {
  354. st_mem_hwcorrupt = rrdset_create_localhost(
  355. "mem"
  356. , "hwcorrupt"
  357. , NULL
  358. , "ecc"
  359. , NULL
  360. , "Corrupted Memory, detected by ECC"
  361. , "MiB"
  362. , PLUGIN_PROC_NAME
  363. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  364. , NETDATA_CHART_PRIO_MEM_HW
  365. , update_every
  366. , RRDSET_TYPE_LINE
  367. );
  368. rrdset_flag_set(st_mem_hwcorrupt, RRDSET_FLAG_DETAIL);
  369. rd_corrupted = rrddim_add(st_mem_hwcorrupt, "HardwareCorrupted", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  370. }
  371. rrddim_set_by_pointer(st_mem_hwcorrupt, rd_corrupted, HardwareCorrupted);
  372. rrdset_done(st_mem_hwcorrupt);
  373. }
  374. if(do_committed) {
  375. static RRDSET *st_mem_committed = NULL;
  376. static RRDDIM *rd_committed = NULL;
  377. if(unlikely(!st_mem_committed)) {
  378. st_mem_committed = rrdset_create_localhost(
  379. "mem"
  380. , "committed"
  381. , NULL
  382. , "overview"
  383. , NULL
  384. , "Committed (Allocated) Memory"
  385. , "MiB"
  386. , PLUGIN_PROC_NAME
  387. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  388. , NETDATA_CHART_PRIO_MEM_SYSTEM_COMMITTED
  389. , update_every
  390. , RRDSET_TYPE_AREA
  391. );
  392. rrdset_flag_set(st_mem_committed, RRDSET_FLAG_DETAIL);
  393. rd_committed = rrddim_add(st_mem_committed, "Committed_AS", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  394. }
  395. rrddim_set_by_pointer(st_mem_committed, rd_committed, Committed_AS);
  396. rrdset_done(st_mem_committed);
  397. }
  398. if(do_writeback) {
  399. static RRDSET *st_mem_writeback = NULL;
  400. static RRDDIM *rd_dirty = NULL, *rd_writeback = NULL, *rd_fusewriteback = NULL, *rd_nfs_writeback = NULL, *rd_bounce = NULL;
  401. if(unlikely(!st_mem_writeback)) {
  402. st_mem_writeback = rrdset_create_localhost(
  403. "mem"
  404. , "writeback"
  405. , NULL
  406. , "writeback"
  407. , NULL
  408. , "Writeback Memory"
  409. , "MiB"
  410. , PLUGIN_PROC_NAME
  411. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  412. , NETDATA_CHART_PRIO_MEM_KERNEL
  413. , update_every
  414. , RRDSET_TYPE_LINE
  415. );
  416. rrdset_flag_set(st_mem_writeback, RRDSET_FLAG_DETAIL);
  417. rd_dirty = rrddim_add(st_mem_writeback, "Dirty", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  418. rd_writeback = rrddim_add(st_mem_writeback, "Writeback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  419. rd_fusewriteback = rrddim_add(st_mem_writeback, "FuseWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  420. rd_nfs_writeback = rrddim_add(st_mem_writeback, "NfsWriteback", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  421. rd_bounce = rrddim_add(st_mem_writeback, "Bounce", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  422. }
  423. rrddim_set_by_pointer(st_mem_writeback, rd_dirty, Dirty);
  424. rrddim_set_by_pointer(st_mem_writeback, rd_writeback, Writeback);
  425. rrddim_set_by_pointer(st_mem_writeback, rd_fusewriteback, WritebackTmp);
  426. rrddim_set_by_pointer(st_mem_writeback, rd_nfs_writeback, NFS_Unstable);
  427. rrddim_set_by_pointer(st_mem_writeback, rd_bounce, Bounce);
  428. rrdset_done(st_mem_writeback);
  429. }
  430. // --------------------------------------------------------------------
  431. if(do_kernel) {
  432. static RRDSET *st_mem_kernel = NULL;
  433. static RRDDIM *rd_slab = NULL, *rd_kernelstack = NULL, *rd_pagetables = NULL, *rd_vmallocused = NULL,
  434. *rd_percpu = NULL, *rd_kreclaimable = NULL;
  435. if(unlikely(!st_mem_kernel)) {
  436. st_mem_kernel = rrdset_create_localhost(
  437. "mem"
  438. , "kernel"
  439. , NULL
  440. , "kernel"
  441. , NULL
  442. , "Memory Used by Kernel"
  443. , "MiB"
  444. , PLUGIN_PROC_NAME
  445. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  446. , NETDATA_CHART_PRIO_MEM_KERNEL + 1
  447. , update_every
  448. , RRDSET_TYPE_STACKED
  449. );
  450. rrdset_flag_set(st_mem_kernel, RRDSET_FLAG_DETAIL);
  451. rd_slab = rrddim_add(st_mem_kernel, "Slab", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  452. rd_kernelstack = rrddim_add(st_mem_kernel, "KernelStack", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  453. rd_pagetables = rrddim_add(st_mem_kernel, "PageTables", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  454. rd_vmallocused = rrddim_add(st_mem_kernel, "VmallocUsed", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  455. rd_percpu = rrddim_add(st_mem_kernel, "Percpu", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  456. rd_kreclaimable = rrddim_add(st_mem_kernel, "KReclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  457. }
  458. rrddim_set_by_pointer(st_mem_kernel, rd_slab, Slab);
  459. rrddim_set_by_pointer(st_mem_kernel, rd_kernelstack, KernelStack);
  460. rrddim_set_by_pointer(st_mem_kernel, rd_pagetables, PageTables);
  461. rrddim_set_by_pointer(st_mem_kernel, rd_vmallocused, VmallocUsed);
  462. rrddim_set_by_pointer(st_mem_kernel, rd_percpu, Percpu);
  463. rrddim_set_by_pointer(st_mem_kernel, rd_kreclaimable, KReclaimable);
  464. rrdset_done(st_mem_kernel);
  465. }
  466. if(do_slab) {
  467. static RRDSET *st_mem_slab = NULL;
  468. static RRDDIM *rd_reclaimable = NULL, *rd_unreclaimable = NULL;
  469. if(unlikely(!st_mem_slab)) {
  470. st_mem_slab = rrdset_create_localhost(
  471. "mem"
  472. , "slab"
  473. , NULL
  474. , "slab"
  475. , NULL
  476. , "Reclaimable Kernel Memory"
  477. , "MiB"
  478. , PLUGIN_PROC_NAME
  479. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  480. , NETDATA_CHART_PRIO_MEM_SLAB
  481. , update_every
  482. , RRDSET_TYPE_STACKED
  483. );
  484. rrdset_flag_set(st_mem_slab, RRDSET_FLAG_DETAIL);
  485. rd_reclaimable = rrddim_add(st_mem_slab, "reclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  486. rd_unreclaimable = rrddim_add(st_mem_slab, "unreclaimable", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  487. }
  488. rrddim_set_by_pointer(st_mem_slab, rd_reclaimable, SReclaimable);
  489. rrddim_set_by_pointer(st_mem_slab, rd_unreclaimable, SUnreclaim);
  490. rrdset_done(st_mem_slab);
  491. }
  492. if(arl_hugepages_total->flags & ARL_ENTRY_FLAG_FOUND &&
  493. (do_hugepages == CONFIG_BOOLEAN_YES || (do_hugepages == CONFIG_BOOLEAN_AUTO &&
  494. ((Hugepagesize && HugePages_Total) ||
  495. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES)))) {
  496. do_hugepages = CONFIG_BOOLEAN_YES;
  497. static RRDSET *st_mem_hugepages = NULL;
  498. static RRDDIM *rd_used = NULL, *rd_free = NULL, *rd_rsvd = NULL, *rd_surp = NULL;
  499. if(unlikely(!st_mem_hugepages)) {
  500. st_mem_hugepages = rrdset_create_localhost(
  501. "mem"
  502. , "hugepages"
  503. , NULL
  504. , "hugepages"
  505. , NULL
  506. , "Dedicated HugePages Memory"
  507. , "MiB"
  508. , PLUGIN_PROC_NAME
  509. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  510. , NETDATA_CHART_PRIO_MEM_HUGEPAGES
  511. , update_every
  512. , RRDSET_TYPE_STACKED
  513. );
  514. rrdset_flag_set(st_mem_hugepages, RRDSET_FLAG_DETAIL);
  515. rd_free = rrddim_add(st_mem_hugepages, "free", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
  516. rd_used = rrddim_add(st_mem_hugepages, "used", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
  517. rd_surp = rrddim_add(st_mem_hugepages, "surplus", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
  518. rd_rsvd = rrddim_add(st_mem_hugepages, "reserved", NULL, Hugepagesize, 1024, RRD_ALGORITHM_ABSOLUTE);
  519. }
  520. rrddim_set_by_pointer(st_mem_hugepages, rd_used, HugePages_Total - HugePages_Free - HugePages_Rsvd);
  521. rrddim_set_by_pointer(st_mem_hugepages, rd_free, HugePages_Free);
  522. rrddim_set_by_pointer(st_mem_hugepages, rd_rsvd, HugePages_Rsvd);
  523. rrddim_set_by_pointer(st_mem_hugepages, rd_surp, HugePages_Surp);
  524. rrdset_done(st_mem_hugepages);
  525. }
  526. if(do_transparent_hugepages == CONFIG_BOOLEAN_YES || (do_transparent_hugepages == CONFIG_BOOLEAN_AUTO &&
  527. (AnonHugePages ||
  528. ShmemHugePages ||
  529. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  530. do_transparent_hugepages = CONFIG_BOOLEAN_YES;
  531. static RRDSET *st_mem_transparent_hugepages = NULL;
  532. static RRDDIM *rd_anonymous = NULL, *rd_shared = NULL;
  533. if(unlikely(!st_mem_transparent_hugepages)) {
  534. st_mem_transparent_hugepages = rrdset_create_localhost(
  535. "mem"
  536. , "thp"
  537. , NULL
  538. , "hugepages"
  539. , NULL
  540. , "Transparent HugePages Memory"
  541. , "MiB"
  542. , PLUGIN_PROC_NAME
  543. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  544. , NETDATA_CHART_PRIO_MEM_HUGEPAGES + 1
  545. , update_every
  546. , RRDSET_TYPE_STACKED
  547. );
  548. rrdset_flag_set(st_mem_transparent_hugepages, RRDSET_FLAG_DETAIL);
  549. rd_anonymous = rrddim_add(st_mem_transparent_hugepages, "anonymous", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  550. rd_shared = rrddim_add(st_mem_transparent_hugepages, "shmem", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  551. }
  552. rrddim_set_by_pointer(st_mem_transparent_hugepages, rd_anonymous, AnonHugePages);
  553. rrddim_set_by_pointer(st_mem_transparent_hugepages, rd_shared, ShmemHugePages);
  554. rrdset_done(st_mem_transparent_hugepages);
  555. {
  556. static RRDSET *st_mem_thp_details = NULL;
  557. static RRDDIM *rd_shmem_pmd_mapped = NULL, *rd_file_huge_pages = NULL, *rd_file_pmd_mapped = NULL;
  558. if(unlikely(!st_mem_thp_details)) {
  559. st_mem_thp_details = rrdset_create_localhost(
  560. "mem"
  561. , "thp_details"
  562. , NULL
  563. , "hugepages"
  564. , NULL
  565. , "Details of Transparent HugePages Usage"
  566. , "MiB"
  567. , PLUGIN_PROC_NAME
  568. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  569. , NETDATA_CHART_PRIO_MEM_HUGEPAGES_DETAILS
  570. , update_every
  571. , RRDSET_TYPE_LINE
  572. );
  573. rrdset_flag_set(st_mem_thp_details, RRDSET_FLAG_DETAIL);
  574. rd_shmem_pmd_mapped = rrddim_add(st_mem_thp_details, "shmem_pmd", "ShmemPmdMapped", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  575. rd_file_huge_pages = rrddim_add(st_mem_thp_details, "file", "FileHugePages", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  576. rd_file_pmd_mapped = rrddim_add(st_mem_thp_details, "file_pmd", "FilePmdMapped", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  577. }
  578. rrddim_set_by_pointer(st_mem_thp_details, rd_shmem_pmd_mapped, ShmemPmdMapped);
  579. rrddim_set_by_pointer(st_mem_thp_details, rd_file_huge_pages, FileHugePages);
  580. rrddim_set_by_pointer(st_mem_thp_details, rd_file_pmd_mapped, FilePmdMapped);
  581. rrdset_done(st_mem_thp_details);
  582. }
  583. }
  584. if(do_reclaiming != CONFIG_BOOLEAN_NO) {
  585. static RRDSET *st_mem_reclaiming = NULL;
  586. static RRDDIM *rd_active = NULL, *rd_inactive = NULL,
  587. *rd_active_anon = NULL, *rd_inactive_anon = NULL,
  588. *rd_active_file = NULL, *rd_inactive_file = NULL,
  589. *rd_unevictable = NULL, *rd_mlocked = NULL;
  590. if(unlikely(!st_mem_reclaiming)) {
  591. st_mem_reclaiming = rrdset_create_localhost(
  592. "mem"
  593. , "reclaiming"
  594. , NULL
  595. , "reclaiming"
  596. , NULL
  597. , "Memory Reclaiming"
  598. , "MiB"
  599. , PLUGIN_PROC_NAME
  600. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  601. , NETDATA_CHART_PRIO_MEM_RECLAIMING
  602. , update_every
  603. , RRDSET_TYPE_LINE
  604. );
  605. rrdset_flag_set(st_mem_reclaiming, RRDSET_FLAG_DETAIL);
  606. rd_active = rrddim_add(st_mem_reclaiming, "active", "Active", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  607. rd_inactive = rrddim_add(st_mem_reclaiming, "inactive", "Inactive", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  608. rd_active_anon = rrddim_add(st_mem_reclaiming, "active_anon", "Active(anon)", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  609. rd_inactive_anon = rrddim_add(st_mem_reclaiming, "inactive_anon", "Inactive(anon)", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  610. rd_active_file = rrddim_add(st_mem_reclaiming, "active_file", "Active(file)", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  611. rd_inactive_file = rrddim_add(st_mem_reclaiming, "inactive_file", "Inactive(file)", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  612. rd_unevictable = rrddim_add(st_mem_reclaiming, "unevictable", "Unevictable", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  613. rd_mlocked = rrddim_add(st_mem_reclaiming, "mlocked", "Mlocked", 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  614. }
  615. rrddim_set_by_pointer(st_mem_reclaiming, rd_active, Active);
  616. rrddim_set_by_pointer(st_mem_reclaiming, rd_inactive, Inactive);
  617. rrddim_set_by_pointer(st_mem_reclaiming, rd_active_anon, ActiveAnon);
  618. rrddim_set_by_pointer(st_mem_reclaiming, rd_inactive_anon, InactiveAnon);
  619. rrddim_set_by_pointer(st_mem_reclaiming, rd_active_file, ActiveFile);
  620. rrddim_set_by_pointer(st_mem_reclaiming, rd_inactive_file, InactiveFile);
  621. rrddim_set_by_pointer(st_mem_reclaiming, rd_unevictable, Unevictable);
  622. rrddim_set_by_pointer(st_mem_reclaiming, rd_mlocked, Mlocked);
  623. rrdset_done(st_mem_reclaiming);
  624. }
  625. if(do_high_low != CONFIG_BOOLEAN_NO && (arl_high_low->flags & ARL_ENTRY_FLAG_FOUND)) {
  626. static RRDSET *st_mem_high_low = NULL;
  627. static RRDDIM *rd_high_used = NULL, *rd_low_used = NULL;
  628. static RRDDIM *rd_high_free = NULL, *rd_low_free = NULL;
  629. if(unlikely(!st_mem_high_low)) {
  630. st_mem_high_low = rrdset_create_localhost(
  631. "mem"
  632. , "high_low"
  633. , NULL
  634. , "high_low"
  635. , NULL
  636. , "High and Low Used and Free Memory Areas"
  637. , "MiB"
  638. , PLUGIN_PROC_NAME
  639. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  640. , NETDATA_CHART_PRIO_MEM_HIGH_LOW
  641. , update_every
  642. , RRDSET_TYPE_STACKED
  643. );
  644. rrdset_flag_set(st_mem_high_low, RRDSET_FLAG_DETAIL);
  645. rd_high_used = rrddim_add(st_mem_high_low, "high_used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  646. rd_low_used = rrddim_add(st_mem_high_low, "low_used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  647. rd_high_free = rrddim_add(st_mem_high_low, "high_free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  648. rd_low_free = rrddim_add(st_mem_high_low, "low_free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  649. }
  650. rrddim_set_by_pointer(st_mem_high_low, rd_high_used, HighTotal - HighFree);
  651. rrddim_set_by_pointer(st_mem_high_low, rd_low_used, LowTotal - LowFree);
  652. rrddim_set_by_pointer(st_mem_high_low, rd_high_free, HighFree);
  653. rrddim_set_by_pointer(st_mem_high_low, rd_low_free, LowFree);
  654. rrdset_done(st_mem_high_low);
  655. }
  656. if(do_cma == CONFIG_BOOLEAN_YES || (do_cma == CONFIG_BOOLEAN_AUTO && (arl_cma_total->flags & ARL_ENTRY_FLAG_FOUND) && CmaTotal)) {
  657. do_cma = CONFIG_BOOLEAN_YES;
  658. static RRDSET *st_mem_cma = NULL;
  659. static RRDDIM *rd_used = NULL, *rd_free = NULL;
  660. if(unlikely(!st_mem_cma)) {
  661. st_mem_cma = rrdset_create_localhost(
  662. "mem"
  663. , "cma"
  664. , NULL
  665. , "cma"
  666. , NULL
  667. , "Contiguous Memory Allocator (CMA) Memory"
  668. , "MiB"
  669. , PLUGIN_PROC_NAME
  670. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  671. , NETDATA_CHART_PRIO_MEM_CMA
  672. , update_every
  673. , RRDSET_TYPE_STACKED
  674. );
  675. rd_used = rrddim_add(st_mem_cma, "used", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  676. rd_free = rrddim_add(st_mem_cma, "free", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  677. }
  678. rrddim_set_by_pointer(st_mem_cma, rd_used, CmaTotal - CmaFree);
  679. rrddim_set_by_pointer(st_mem_cma, rd_free, CmaFree);
  680. rrdset_done(st_mem_cma);
  681. }
  682. if(do_directmap != CONFIG_BOOLEAN_NO &&
  683. ((arl_directmap4k->flags & ARL_ENTRY_FLAG_FOUND) ||
  684. (arl_directmap2m->flags & ARL_ENTRY_FLAG_FOUND) ||
  685. (arl_directmap4m->flags & ARL_ENTRY_FLAG_FOUND) ||
  686. (arl_directmap1g->flags & ARL_ENTRY_FLAG_FOUND)))
  687. {
  688. static RRDSET *st_mem_directmap = NULL;
  689. static RRDDIM *rd_4k = NULL, *rd_2m = NULL, *rd_1g = NULL, *rd_4m = NULL;
  690. if(unlikely(!st_mem_directmap)) {
  691. st_mem_directmap = rrdset_create_localhost(
  692. "mem"
  693. , "directmaps"
  694. , NULL
  695. , "overview"
  696. , NULL
  697. , "Direct Memory Mappings"
  698. , "MiB"
  699. , PLUGIN_PROC_NAME
  700. , PLUGIN_PROC_MODULE_MEMINFO_NAME
  701. , NETDATA_CHART_PRIO_MEM_DIRECTMAP
  702. , update_every
  703. , RRDSET_TYPE_STACKED
  704. );
  705. if(arl_directmap4k->flags & ARL_ENTRY_FLAG_FOUND)
  706. rd_4k = rrddim_add(st_mem_directmap, "4k", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  707. if(arl_directmap2m->flags & ARL_ENTRY_FLAG_FOUND)
  708. rd_2m = rrddim_add(st_mem_directmap, "2m", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  709. if(arl_directmap4m->flags & ARL_ENTRY_FLAG_FOUND)
  710. rd_4m = rrddim_add(st_mem_directmap, "4m", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  711. if(arl_directmap1g->flags & ARL_ENTRY_FLAG_FOUND)
  712. rd_1g = rrddim_add(st_mem_directmap, "1g", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
  713. }
  714. if(rd_4k)
  715. rrddim_set_by_pointer(st_mem_directmap, rd_4k, DirectMap4k);
  716. if(rd_2m)
  717. rrddim_set_by_pointer(st_mem_directmap, rd_2m, DirectMap2M);
  718. if(rd_4m)
  719. rrddim_set_by_pointer(st_mem_directmap, rd_4m, DirectMap4M);
  720. if(rd_1g)
  721. rrddim_set_by_pointer(st_mem_directmap, rd_1g, DirectMap1G);
  722. rrdset_done(st_mem_directmap);
  723. }
  724. return 0;
  725. }