sys_fs_btrfs.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "plugin_proc.h"
  3. #define PLUGIN_PROC_MODULE_BTRFS_NAME "/sys/fs/btrfs"
  4. typedef struct btrfs_disk {
  5. char *name;
  6. uint32_t hash;
  7. int exists;
  8. char *size_filename;
  9. char *hw_sector_size_filename;
  10. unsigned long long size;
  11. unsigned long long hw_sector_size;
  12. struct btrfs_disk *next;
  13. } BTRFS_DISK;
  14. typedef struct btrfs_node {
  15. int exists;
  16. int logged_error;
  17. char *id;
  18. uint32_t hash;
  19. char *label;
  20. // unsigned long long int sectorsize;
  21. // unsigned long long int nodesize;
  22. // unsigned long long int quota_override;
  23. #define declare_btrfs_allocation_section_field(SECTION, FIELD) \
  24. char *allocation_ ## SECTION ## _ ## FIELD ## _filename; \
  25. unsigned long long int allocation_ ## SECTION ## _ ## FIELD;
  26. #define declare_btrfs_allocation_field(FIELD) \
  27. char *allocation_ ## FIELD ## _filename; \
  28. unsigned long long int allocation_ ## FIELD;
  29. RRDSET *st_allocation_disks;
  30. RRDDIM *rd_allocation_disks_unallocated;
  31. RRDDIM *rd_allocation_disks_data_used;
  32. RRDDIM *rd_allocation_disks_data_free;
  33. RRDDIM *rd_allocation_disks_metadata_used;
  34. RRDDIM *rd_allocation_disks_metadata_free;
  35. RRDDIM *rd_allocation_disks_system_used;
  36. RRDDIM *rd_allocation_disks_system_free;
  37. unsigned long long all_disks_total;
  38. RRDSET *st_allocation_data;
  39. RRDDIM *rd_allocation_data_free;
  40. RRDDIM *rd_allocation_data_used;
  41. declare_btrfs_allocation_section_field(data, total_bytes)
  42. declare_btrfs_allocation_section_field(data, bytes_used)
  43. declare_btrfs_allocation_section_field(data, disk_total)
  44. declare_btrfs_allocation_section_field(data, disk_used)
  45. RRDSET *st_allocation_metadata;
  46. RRDDIM *rd_allocation_metadata_free;
  47. RRDDIM *rd_allocation_metadata_used;
  48. RRDDIM *rd_allocation_metadata_reserved;
  49. declare_btrfs_allocation_section_field(metadata, total_bytes)
  50. declare_btrfs_allocation_section_field(metadata, bytes_used)
  51. declare_btrfs_allocation_section_field(metadata, disk_total)
  52. declare_btrfs_allocation_section_field(metadata, disk_used)
  53. //declare_btrfs_allocation_field(global_rsv_reserved)
  54. declare_btrfs_allocation_field(global_rsv_size)
  55. RRDSET *st_allocation_system;
  56. RRDDIM *rd_allocation_system_free;
  57. RRDDIM *rd_allocation_system_used;
  58. declare_btrfs_allocation_section_field(system, total_bytes)
  59. declare_btrfs_allocation_section_field(system, bytes_used)
  60. declare_btrfs_allocation_section_field(system, disk_total)
  61. declare_btrfs_allocation_section_field(system, disk_used)
  62. BTRFS_DISK *disks;
  63. struct btrfs_node *next;
  64. } BTRFS_NODE;
  65. static BTRFS_NODE *nodes = NULL;
  66. static inline void btrfs_free_disk(BTRFS_DISK *d) {
  67. freez(d->name);
  68. freez(d->size_filename);
  69. freez(d->hw_sector_size_filename);
  70. freez(d);
  71. }
  72. static inline void btrfs_free_node(BTRFS_NODE *node) {
  73. // info("BTRFS: destroying '%s'", node->id);
  74. if(node->st_allocation_disks)
  75. rrdset_is_obsolete(node->st_allocation_disks);
  76. if(node->st_allocation_data)
  77. rrdset_is_obsolete(node->st_allocation_data);
  78. if(node->st_allocation_metadata)
  79. rrdset_is_obsolete(node->st_allocation_metadata);
  80. if(node->st_allocation_system)
  81. rrdset_is_obsolete(node->st_allocation_system);
  82. freez(node->allocation_data_bytes_used_filename);
  83. freez(node->allocation_data_total_bytes_filename);
  84. freez(node->allocation_metadata_bytes_used_filename);
  85. freez(node->allocation_metadata_total_bytes_filename);
  86. freez(node->allocation_system_bytes_used_filename);
  87. freez(node->allocation_system_total_bytes_filename);
  88. while(node->disks) {
  89. BTRFS_DISK *d = node->disks;
  90. node->disks = node->disks->next;
  91. btrfs_free_disk(d);
  92. }
  93. freez(node->label);
  94. freez(node->id);
  95. freez(node);
  96. }
  97. static inline int find_btrfs_disks(BTRFS_NODE *node, const char *path) {
  98. char filename[FILENAME_MAX + 1];
  99. node->all_disks_total = 0;
  100. BTRFS_DISK *d;
  101. for(d = node->disks ; d ; d = d->next)
  102. d->exists = 0;
  103. DIR *dir = opendir(path);
  104. if (!dir) {
  105. if(!node->logged_error) {
  106. error("BTRFS: Cannot open directory '%s'.", path);
  107. node->logged_error = 1;
  108. }
  109. return 1;
  110. }
  111. node->logged_error = 0;
  112. struct dirent *de = NULL;
  113. while ((de = readdir(dir))) {
  114. if (de->d_type != DT_LNK
  115. || !strcmp(de->d_name, ".")
  116. || !strcmp(de->d_name, "..")
  117. ) {
  118. // info("BTRFS: ignoring '%s'", de->d_name);
  119. continue;
  120. }
  121. uint32_t hash = simple_hash(de->d_name);
  122. // --------------------------------------------------------------------
  123. // search for it
  124. for(d = node->disks ; d ; d = d->next) {
  125. if(hash == d->hash && !strcmp(de->d_name, d->name))
  126. break;
  127. }
  128. // --------------------------------------------------------------------
  129. // did we find it?
  130. if(!d) {
  131. d = callocz(sizeof(BTRFS_DISK), 1);
  132. d->name = strdupz(de->d_name);
  133. d->hash = simple_hash(d->name);
  134. snprintfz(filename, FILENAME_MAX, "%s/%s/size", path, de->d_name);
  135. d->size_filename = strdupz(filename);
  136. // for bcache
  137. snprintfz(filename, FILENAME_MAX, "%s/%s/bcache/../queue/hw_sector_size", path, de->d_name);
  138. struct stat sb;
  139. if(stat(filename, &sb) == -1) {
  140. // for disks
  141. snprintfz(filename, FILENAME_MAX, "%s/%s/queue/hw_sector_size", path, de->d_name);
  142. if(stat(filename, &sb) == -1)
  143. // for partitions
  144. snprintfz(filename, FILENAME_MAX, "%s/%s/../queue/hw_sector_size", path, de->d_name);
  145. }
  146. d->hw_sector_size_filename = strdupz(filename);
  147. // link it
  148. d->next = node->disks;
  149. node->disks = d;
  150. }
  151. d->exists = 1;
  152. // --------------------------------------------------------------------
  153. // update the values
  154. if(read_single_number_file(d->size_filename, &d->size) != 0) {
  155. error("BTRFS: failed to read '%s'", d->size_filename);
  156. d->exists = 0;
  157. continue;
  158. }
  159. if(read_single_number_file(d->hw_sector_size_filename, &d->hw_sector_size) != 0) {
  160. error("BTRFS: failed to read '%s'", d->hw_sector_size_filename);
  161. d->exists = 0;
  162. continue;
  163. }
  164. node->all_disks_total += d->size * d->hw_sector_size;
  165. }
  166. closedir(dir);
  167. // ------------------------------------------------------------------------
  168. // cleanup
  169. BTRFS_DISK *last = NULL;
  170. d = node->disks;
  171. while(d) {
  172. if(unlikely(!d->exists)) {
  173. if(unlikely(node->disks == d)) {
  174. node->disks = d->next;
  175. btrfs_free_disk(d);
  176. d = node->disks;
  177. last = NULL;
  178. }
  179. else {
  180. last->next = d->next;
  181. btrfs_free_disk(d);
  182. d = last->next;
  183. }
  184. continue;
  185. }
  186. last = d;
  187. d = d->next;
  188. }
  189. return 0;
  190. }
  191. static inline int find_all_btrfs_pools(const char *path) {
  192. static int logged_error = 0;
  193. char filename[FILENAME_MAX + 1];
  194. BTRFS_NODE *node;
  195. for(node = nodes ; node ; node = node->next)
  196. node->exists = 0;
  197. DIR *dir = opendir(path);
  198. if (!dir) {
  199. if(!logged_error) {
  200. error("BTRFS: Cannot open directory '%s'.", path);
  201. logged_error = 1;
  202. }
  203. return 1;
  204. }
  205. logged_error = 0;
  206. struct dirent *de = NULL;
  207. while ((de = readdir(dir))) {
  208. if(de->d_type != DT_DIR
  209. || !strcmp(de->d_name, ".")
  210. || !strcmp(de->d_name, "..")
  211. || !strcmp(de->d_name, "features")
  212. ) {
  213. // info("BTRFS: ignoring '%s'", de->d_name);
  214. continue;
  215. }
  216. uint32_t hash = simple_hash(de->d_name);
  217. // search for it
  218. for(node = nodes ; node ; node = node->next) {
  219. if(hash == node->hash && !strcmp(de->d_name, node->id))
  220. break;
  221. }
  222. // did we find it?
  223. if(node) {
  224. // info("BTRFS: already exists '%s'", de->d_name);
  225. node->exists = 1;
  226. // update the disk sizes
  227. snprintfz(filename, FILENAME_MAX, "%s/%s/devices", path, de->d_name);
  228. find_btrfs_disks(node, filename);
  229. continue;
  230. }
  231. // info("BTRFS: adding '%s'", de->d_name);
  232. // not found, create it
  233. node = callocz(sizeof(BTRFS_NODE), 1);
  234. node->id = strdupz(de->d_name);
  235. node->hash = simple_hash(node->id);
  236. node->exists = 1;
  237. {
  238. char label[FILENAME_MAX + 1] = "";
  239. snprintfz(filename, FILENAME_MAX, "%s/%s/label", path, de->d_name);
  240. if(read_file(filename, label, FILENAME_MAX) != 0) {
  241. error("BTRFS: failed to read '%s'", filename);
  242. btrfs_free_node(node);
  243. continue;
  244. }
  245. char *s = label;
  246. if (s[0])
  247. s = trim(label);
  248. if(s && s[0])
  249. node->label = strdupz(s);
  250. else
  251. node->label = strdupz(node->id);
  252. }
  253. //snprintfz(filename, FILENAME_MAX, "%s/%s/sectorsize", path, de->d_name);
  254. //if(read_single_number_file(filename, &node->sectorsize) != 0) {
  255. // error("BTRFS: failed to read '%s'", filename);
  256. // btrfs_free_node(node);
  257. // continue;
  258. //}
  259. //snprintfz(filename, FILENAME_MAX, "%s/%s/nodesize", path, de->d_name);
  260. //if(read_single_number_file(filename, &node->nodesize) != 0) {
  261. // error("BTRFS: failed to read '%s'", filename);
  262. // btrfs_free_node(node);
  263. // continue;
  264. //}
  265. //snprintfz(filename, FILENAME_MAX, "%s/%s/quota_override", path, de->d_name);
  266. //if(read_single_number_file(filename, &node->quota_override) != 0) {
  267. // error("BTRFS: failed to read '%s'", filename);
  268. // btrfs_free_node(node);
  269. // continue;
  270. //}
  271. // --------------------------------------------------------------------
  272. // macros to simplify our life
  273. #define init_btrfs_allocation_field(FIELD) {\
  274. snprintfz(filename, FILENAME_MAX, "%s/%s/allocation/" #FIELD, path, de->d_name); \
  275. if(read_single_number_file(filename, &node->allocation_ ## FIELD) != 0) {\
  276. error("BTRFS: failed to read '%s'", filename);\
  277. btrfs_free_node(node);\
  278. continue;\
  279. }\
  280. if(!node->allocation_ ## FIELD ## _filename)\
  281. node->allocation_ ## FIELD ## _filename = strdupz(filename);\
  282. }
  283. #define init_btrfs_allocation_section_field(SECTION, FIELD) {\
  284. snprintfz(filename, FILENAME_MAX, "%s/%s/allocation/" #SECTION "/" #FIELD, path, de->d_name); \
  285. if(read_single_number_file(filename, &node->allocation_ ## SECTION ## _ ## FIELD) != 0) {\
  286. error("BTRFS: failed to read '%s'", filename);\
  287. btrfs_free_node(node);\
  288. continue;\
  289. }\
  290. if(!node->allocation_ ## SECTION ## _ ## FIELD ## _filename)\
  291. node->allocation_ ## SECTION ## _ ## FIELD ## _filename = strdupz(filename);\
  292. }
  293. // --------------------------------------------------------------------
  294. // allocation/data
  295. init_btrfs_allocation_section_field(data, total_bytes);
  296. init_btrfs_allocation_section_field(data, bytes_used);
  297. init_btrfs_allocation_section_field(data, disk_total);
  298. init_btrfs_allocation_section_field(data, disk_used);
  299. // --------------------------------------------------------------------
  300. // allocation/metadata
  301. init_btrfs_allocation_section_field(metadata, total_bytes);
  302. init_btrfs_allocation_section_field(metadata, bytes_used);
  303. init_btrfs_allocation_section_field(metadata, disk_total);
  304. init_btrfs_allocation_section_field(metadata, disk_used);
  305. init_btrfs_allocation_field(global_rsv_size);
  306. // init_btrfs_allocation_field(global_rsv_reserved);
  307. // --------------------------------------------------------------------
  308. // allocation/system
  309. init_btrfs_allocation_section_field(system, total_bytes);
  310. init_btrfs_allocation_section_field(system, bytes_used);
  311. init_btrfs_allocation_section_field(system, disk_total);
  312. init_btrfs_allocation_section_field(system, disk_used);
  313. // --------------------------------------------------------------------
  314. // find all disks related to this node
  315. // and collect their sizes
  316. snprintfz(filename, FILENAME_MAX, "%s/%s/devices", path, de->d_name);
  317. find_btrfs_disks(node, filename);
  318. // --------------------------------------------------------------------
  319. // link it
  320. // info("BTRFS: linking '%s'", node->id);
  321. node->next = nodes;
  322. nodes = node;
  323. }
  324. closedir(dir);
  325. // ------------------------------------------------------------------------
  326. // cleanup
  327. BTRFS_NODE *last = NULL;
  328. node = nodes;
  329. while(node) {
  330. if(unlikely(!node->exists)) {
  331. if(unlikely(nodes == node)) {
  332. nodes = node->next;
  333. btrfs_free_node(node);
  334. node = nodes;
  335. last = NULL;
  336. }
  337. else {
  338. last->next = node->next;
  339. btrfs_free_node(node);
  340. node = last->next;
  341. }
  342. continue;
  343. }
  344. last = node;
  345. node = node->next;
  346. }
  347. return 0;
  348. }
  349. int do_sys_fs_btrfs(int update_every, usec_t dt) {
  350. static int initialized = 0
  351. , do_allocation_disks = CONFIG_BOOLEAN_AUTO
  352. , do_allocation_system = CONFIG_BOOLEAN_AUTO
  353. , do_allocation_data = CONFIG_BOOLEAN_AUTO
  354. , do_allocation_metadata = CONFIG_BOOLEAN_AUTO;
  355. static usec_t refresh_delta = 0, refresh_every = 60 * USEC_PER_SEC;
  356. static char *btrfs_path = NULL;
  357. (void)dt;
  358. if(unlikely(!initialized)) {
  359. initialized = 1;
  360. char filename[FILENAME_MAX + 1];
  361. snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/fs/btrfs");
  362. btrfs_path = config_get("plugin:proc:/sys/fs/btrfs", "path to monitor", filename);
  363. refresh_every = config_get_number("plugin:proc:/sys/fs/btrfs", "check for btrfs changes every", refresh_every / USEC_PER_SEC) * USEC_PER_SEC;
  364. refresh_delta = refresh_every;
  365. do_allocation_disks = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "physical disks allocation", do_allocation_disks);
  366. do_allocation_data = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "data allocation", do_allocation_data);
  367. do_allocation_metadata = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "metadata allocation", do_allocation_metadata);
  368. do_allocation_system = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "system allocation", do_allocation_system);
  369. }
  370. refresh_delta += dt;
  371. if(refresh_delta >= refresh_every) {
  372. refresh_delta = 0;
  373. find_all_btrfs_pools(btrfs_path);
  374. }
  375. BTRFS_NODE *node;
  376. for(node = nodes; node ; node = node->next) {
  377. // --------------------------------------------------------------------
  378. // allocation/system
  379. #define collect_btrfs_allocation_field(FIELD) \
  380. read_single_number_file(node->allocation_ ## FIELD ## _filename, &node->allocation_ ## FIELD)
  381. #define collect_btrfs_allocation_section_field(SECTION, FIELD) \
  382. read_single_number_file(node->allocation_ ## SECTION ## _ ## FIELD ## _filename, &node->allocation_ ## SECTION ## _ ## FIELD)
  383. if(do_allocation_disks != CONFIG_BOOLEAN_NO) {
  384. if( collect_btrfs_allocation_section_field(data, disk_total) != 0
  385. || collect_btrfs_allocation_section_field(data, disk_used) != 0
  386. || collect_btrfs_allocation_section_field(metadata, disk_total) != 0
  387. || collect_btrfs_allocation_section_field(metadata, disk_used) != 0
  388. || collect_btrfs_allocation_section_field(system, disk_total) != 0
  389. || collect_btrfs_allocation_section_field(system, disk_used) != 0) {
  390. error("BTRFS: failed to collect physical disks allocation for '%s'", node->id);
  391. // make it refresh btrfs at the next iteration
  392. refresh_delta = refresh_every;
  393. continue;
  394. }
  395. }
  396. if(do_allocation_data != CONFIG_BOOLEAN_NO) {
  397. if (collect_btrfs_allocation_section_field(data, total_bytes) != 0
  398. || collect_btrfs_allocation_section_field(data, bytes_used) != 0) {
  399. error("BTRFS: failed to collect allocation/data for '%s'", node->id);
  400. // make it refresh btrfs at the next iteration
  401. refresh_delta = refresh_every;
  402. continue;
  403. }
  404. }
  405. if(do_allocation_metadata != CONFIG_BOOLEAN_NO) {
  406. if (collect_btrfs_allocation_section_field(metadata, total_bytes) != 0
  407. || collect_btrfs_allocation_section_field(metadata, bytes_used) != 0
  408. || collect_btrfs_allocation_field(global_rsv_size) != 0
  409. ) {
  410. error("BTRFS: failed to collect allocation/metadata for '%s'", node->id);
  411. // make it refresh btrfs at the next iteration
  412. refresh_delta = refresh_every;
  413. continue;
  414. }
  415. }
  416. if(do_allocation_system != CONFIG_BOOLEAN_NO) {
  417. if (collect_btrfs_allocation_section_field(system, total_bytes) != 0
  418. || collect_btrfs_allocation_section_field(system, bytes_used) != 0) {
  419. error("BTRFS: failed to collect allocation/system for '%s'", node->id);
  420. // make it refresh btrfs at the next iteration
  421. refresh_delta = refresh_every;
  422. continue;
  423. }
  424. }
  425. // --------------------------------------------------------------------
  426. // allocation/disks
  427. if(do_allocation_disks == CONFIG_BOOLEAN_YES || (do_allocation_disks == CONFIG_BOOLEAN_AUTO &&
  428. ((node->all_disks_total && node->allocation_data_disk_total) ||
  429. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  430. do_allocation_disks = CONFIG_BOOLEAN_YES;
  431. if(unlikely(!node->st_allocation_disks)) {
  432. char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
  433. snprintf(id, RRD_ID_LENGTH_MAX, "disk_%s", node->id);
  434. snprintf(name, RRD_ID_LENGTH_MAX, "disk_%s", node->label);
  435. snprintf(title, 200, "BTRFS Physical Disk Allocation");
  436. netdata_fix_chart_id(id);
  437. netdata_fix_chart_name(name);
  438. node->st_allocation_disks = rrdset_create_localhost(
  439. "btrfs"
  440. , id
  441. , name
  442. , node->label
  443. , "btrfs.disk"
  444. , title
  445. , "MiB"
  446. , PLUGIN_PROC_NAME
  447. , PLUGIN_PROC_MODULE_BTRFS_NAME
  448. , NETDATA_CHART_PRIO_BTRFS_DISK
  449. , update_every
  450. , RRDSET_TYPE_STACKED
  451. );
  452. node->rd_allocation_disks_unallocated = rrddim_add(node->st_allocation_disks, "unallocated", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  453. node->rd_allocation_disks_data_free = rrddim_add(node->st_allocation_disks, "data_free", "data free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  454. node->rd_allocation_disks_data_used = rrddim_add(node->st_allocation_disks, "data_used", "data used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  455. node->rd_allocation_disks_metadata_free = rrddim_add(node->st_allocation_disks, "meta_free", "meta free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  456. node->rd_allocation_disks_metadata_used = rrddim_add(node->st_allocation_disks, "meta_used", "meta used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  457. node->rd_allocation_disks_system_free = rrddim_add(node->st_allocation_disks, "sys_free", "sys free", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  458. node->rd_allocation_disks_system_used = rrddim_add(node->st_allocation_disks, "sys_used", "sys used", 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  459. }
  460. else rrdset_next(node->st_allocation_disks);
  461. // unsigned long long disk_used = node->allocation_data_disk_used + node->allocation_metadata_disk_used + node->allocation_system_disk_used;
  462. unsigned long long disk_total = node->allocation_data_disk_total + node->allocation_metadata_disk_total + node->allocation_system_disk_total;
  463. unsigned long long disk_unallocated = node->all_disks_total - disk_total;
  464. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_unallocated, disk_unallocated);
  465. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_data_used, node->allocation_data_disk_used);
  466. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_data_free, node->allocation_data_disk_total - node->allocation_data_disk_used);
  467. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_metadata_used, node->allocation_metadata_disk_used);
  468. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_metadata_free, node->allocation_metadata_disk_total - node->allocation_metadata_disk_used);
  469. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_system_used, node->allocation_system_disk_used);
  470. rrddim_set_by_pointer(node->st_allocation_disks, node->rd_allocation_disks_system_free, node->allocation_system_disk_total - node->allocation_system_disk_used);
  471. rrdset_done(node->st_allocation_disks);
  472. }
  473. // --------------------------------------------------------------------
  474. // allocation/data
  475. if(do_allocation_data == CONFIG_BOOLEAN_YES || (do_allocation_data == CONFIG_BOOLEAN_AUTO &&
  476. (node->allocation_data_total_bytes ||
  477. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  478. do_allocation_data = CONFIG_BOOLEAN_YES;
  479. if(unlikely(!node->st_allocation_data)) {
  480. char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
  481. snprintf(id, RRD_ID_LENGTH_MAX, "data_%s", node->id);
  482. snprintf(name, RRD_ID_LENGTH_MAX, "data_%s", node->label);
  483. snprintf(title, 200, "BTRFS Data Allocation");
  484. netdata_fix_chart_id(id);
  485. netdata_fix_chart_name(name);
  486. node->st_allocation_data = rrdset_create_localhost(
  487. "btrfs"
  488. , id
  489. , name
  490. , node->label
  491. , "btrfs.data"
  492. , title
  493. , "MiB"
  494. , PLUGIN_PROC_NAME
  495. , PLUGIN_PROC_MODULE_BTRFS_NAME
  496. , NETDATA_CHART_PRIO_BTRFS_DATA
  497. , update_every
  498. , RRDSET_TYPE_STACKED
  499. );
  500. node->rd_allocation_data_free = rrddim_add(node->st_allocation_data, "free", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  501. node->rd_allocation_data_used = rrddim_add(node->st_allocation_data, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  502. }
  503. else rrdset_next(node->st_allocation_data);
  504. rrddim_set_by_pointer(node->st_allocation_data, node->rd_allocation_data_free, node->allocation_data_total_bytes - node->allocation_data_bytes_used);
  505. rrddim_set_by_pointer(node->st_allocation_data, node->rd_allocation_data_used, node->allocation_data_bytes_used);
  506. rrdset_done(node->st_allocation_data);
  507. }
  508. // --------------------------------------------------------------------
  509. // allocation/metadata
  510. if(do_allocation_metadata == CONFIG_BOOLEAN_YES || (do_allocation_metadata == CONFIG_BOOLEAN_AUTO &&
  511. (node->allocation_metadata_total_bytes ||
  512. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  513. do_allocation_metadata = CONFIG_BOOLEAN_YES;
  514. if(unlikely(!node->st_allocation_metadata)) {
  515. char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
  516. snprintf(id, RRD_ID_LENGTH_MAX, "metadata_%s", node->id);
  517. snprintf(name, RRD_ID_LENGTH_MAX, "metadata_%s", node->label);
  518. snprintf(title, 200, "BTRFS Metadata Allocation");
  519. netdata_fix_chart_id(id);
  520. netdata_fix_chart_name(name);
  521. node->st_allocation_metadata = rrdset_create_localhost(
  522. "btrfs"
  523. , id
  524. , name
  525. , node->label
  526. , "btrfs.metadata"
  527. , title
  528. , "MiB"
  529. , PLUGIN_PROC_NAME
  530. , PLUGIN_PROC_MODULE_BTRFS_NAME
  531. , NETDATA_CHART_PRIO_BTRFS_METADATA
  532. , update_every
  533. , RRDSET_TYPE_STACKED
  534. );
  535. node->rd_allocation_metadata_free = rrddim_add(node->st_allocation_metadata, "free", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  536. node->rd_allocation_metadata_used = rrddim_add(node->st_allocation_metadata, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  537. node->rd_allocation_metadata_reserved = rrddim_add(node->st_allocation_metadata, "reserved", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  538. }
  539. else rrdset_next(node->st_allocation_metadata);
  540. rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_free, node->allocation_metadata_total_bytes - node->allocation_metadata_bytes_used - node->allocation_global_rsv_size);
  541. rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_used, node->allocation_metadata_bytes_used);
  542. rrddim_set_by_pointer(node->st_allocation_metadata, node->rd_allocation_metadata_reserved, node->allocation_global_rsv_size);
  543. rrdset_done(node->st_allocation_metadata);
  544. }
  545. // --------------------------------------------------------------------
  546. // allocation/system
  547. if(do_allocation_system == CONFIG_BOOLEAN_YES || (do_allocation_system == CONFIG_BOOLEAN_AUTO &&
  548. (node->allocation_system_total_bytes ||
  549. netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
  550. do_allocation_system = CONFIG_BOOLEAN_YES;
  551. if(unlikely(!node->st_allocation_system)) {
  552. char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
  553. snprintf(id, RRD_ID_LENGTH_MAX, "system_%s", node->id);
  554. snprintf(name, RRD_ID_LENGTH_MAX, "system_%s", node->label);
  555. snprintf(title, 200, "BTRFS System Allocation");
  556. netdata_fix_chart_id(id);
  557. netdata_fix_chart_name(name);
  558. node->st_allocation_system = rrdset_create_localhost(
  559. "btrfs"
  560. , id
  561. , name
  562. , node->label
  563. , "btrfs.system"
  564. , title
  565. , "MiB"
  566. , PLUGIN_PROC_NAME
  567. , PLUGIN_PROC_MODULE_BTRFS_NAME
  568. , NETDATA_CHART_PRIO_BTRFS_SYSTEM
  569. , update_every
  570. , RRDSET_TYPE_STACKED
  571. );
  572. node->rd_allocation_system_free = rrddim_add(node->st_allocation_system, "free", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  573. node->rd_allocation_system_used = rrddim_add(node->st_allocation_system, "used", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
  574. }
  575. else rrdset_next(node->st_allocation_system);
  576. rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_free, node->allocation_system_total_bytes - node->allocation_system_bytes_used);
  577. rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_used, node->allocation_system_bytes_used);
  578. rrdset_done(node->st_allocation_system);
  579. }
  580. }
  581. return 0;
  582. }