15
struct btrfs_disk *next;
16
} BTRFS_DISK;
17
18
+typedef struct btrfs_device {
19
+ int id;
20
+ int exists;
21
+
22
+ char *error_stats_filename;
23
+ RRDSET *st_error_stats;
24
+ RRDDIM *rd_write_errs;
25
+ RRDDIM *rd_read_errs;
26
+ RRDDIM *rd_flush_errs;
27
+ RRDDIM *rd_corruption_errs;
28
+ RRDDIM *rd_generation_errs;
29
+ collected_number write_errs;
30
+ collected_number read_errs;
31
+ collected_number flush_errs;
32
+ collected_number corruption_errs;
33
+ collected_number generation_errs;
34
+
35
+ struct btrfs_device *next;
36
+} BTRFS_DEVICE;
37
+
38
typedef struct btrfs_node {
39
int exists;
40
int logged_error;
44
45
char *label;
46
27
- // unsigned long long int sectorsize;
28
- // unsigned long long int nodesize;
29
- // unsigned long long int quota_override;
30
-
47
#define declare_btrfs_allocation_section_field(SECTION, FIELD) \
48
char *allocation_ ## SECTION ## _ ## FIELD ## _filename; \
49
unsigned long long int allocation_ ## SECTION ## _ ## FIELD;
89
declare_btrfs_allocation_section_field(system, disk_total)
90
declare_btrfs_allocation_section_field(system, disk_used)
91
92
+ // --------------------------------------------------------------------
93
+ // commit stats
94
+
95
+ char *commit_stats_filename;
96
+
97
+ RRDSET *st_commits;
98
+ RRDDIM *rd_commits;
99
+ long long commits_total;
100
+ collected_number commits_new;
101
+
102
+ RRDSET *st_commits_percentage_time;
103
+ RRDDIM *rd_commits_percentage_time;
104
+ long long commit_timings_total;
105
+ long long commits_percentage_time;
106
+
107
+ RRDSET *st_commit_timings;
108
+ RRDDIM *rd_commit_timings_last;
109
+ RRDDIM *rd_commit_timings_max;
110
+ collected_number commit_timings_last;
111
+ collected_number commit_timings_max;
112
+
113
BTRFS_DISK *disks;
114
115
+ BTRFS_DEVICE *devices;
116
+
117
struct btrfs_node *next;
118
} BTRFS_NODE;
119
120
static BTRFS_NODE *nodes = NULL;
121
122
+static inline int collect_btrfs_error_stats(BTRFS_DEVICE *device){
123
+ char buffer[120 + 1];
124
+
125
+ int ret = read_file(device->error_stats_filename, buffer, 120);
126
+ if(unlikely(ret)) {
127
+ collector_error("BTRFS: failed to read '%s'", device->error_stats_filename);
128
+ device->write_errs = 0;
129
+ device->read_errs = 0;
130
+ device->flush_errs = 0;
131
+ device->corruption_errs = 0;
132
+ device->generation_errs = 0;
133
+ return ret;
134
+ }
135
+
136
+ char *p = buffer;
137
+ while(p){
138
+ char *val = mystrsep(&p, "\n");
139
+ if(unlikely(!val || !*val)) break;
140
+ char *key = mystrsep(&val, " ");
141
+
142
+ if(!strcmp(key, "write_errs")) device->write_errs = str2ull(val, NULL);
143
+ else if(!strcmp(key, "read_errs")) device->read_errs = str2ull(val, NULL);
144
+ else if(!strcmp(key, "flush_errs")) device->flush_errs = str2ull(val, NULL);
145
+ else if(!strcmp(key, "corruption_errs")) device->corruption_errs = str2ull(val, NULL);
146
+ else if(!strcmp(key, "generation_errs")) device->generation_errs = str2ull(val, NULL);
147
+ }
148
+ return 0;
149
+}
150
+
151
+static inline int collect_btrfs_commits_stats(BTRFS_NODE *node, int update_every){
152
+ char buffer[120 + 1];
153
+
154
+ int ret = read_file(node->commit_stats_filename, buffer, 120);
155
+ if(unlikely(ret)) {
156
+ collector_error("BTRFS: failed to read '%s'", node->commit_stats_filename);
157
+ node->commits_total = 0;
158
+ node->commits_new = 0;
159
+ node->commit_timings_last = 0;
160
+ node->commit_timings_max = 0;
161
+ node->commit_timings_total = 0;
162
+ node->commits_percentage_time = 0;
163
+
164
+ return ret;
165
+ }
166
+
167
+ char *p = buffer;
168
+ while(p){
169
+ char *val = mystrsep(&p, "\n");
170
+ if(unlikely(!val || !*val)) break;
171
+ char *key = mystrsep(&val, " ");
172
+
173
+ if(!strcmp(key, "commits")){
174
+ long long commits_total_new = str2ull(val, NULL);
175
+ if(likely(node->commits_total)){
176
+ if((node->commits_new = commits_total_new - node->commits_total))
177
+ node->commits_total = commits_total_new;
178
+ } else node->commits_total = commits_total_new;
179
+ }
180
+ else if(!strcmp(key, "last_commit_ms")) node->commit_timings_last = str2ull(val, NULL);
181
+ else if(!strcmp(key, "max_commit_ms")) node->commit_timings_max = str2ull(val, NULL);
182
+ else if(!strcmp(key, "total_commit_ms")) {
183
+ long long commit_timings_total_new = str2ull(val, NULL);
184
+ if(likely(node->commit_timings_total)){
185
+ long time_delta = commit_timings_total_new - node->commit_timings_total;
186
+ if(time_delta){
187
+ node->commits_percentage_time = time_delta * 10 / update_every;
188
+ node->commit_timings_total = commit_timings_total_new;
189
+ } else node->commits_percentage_time = 0;
190
+
191
+ } else node->commit_timings_total = commit_timings_total_new;
192
+ }
193
+ }
194
+ return 0;
195
+}
196
+
197
+static inline void btrfs_free_commits_stats(BTRFS_NODE *node){
198
+ if(node->st_commits){
199
+ rrdset_is_obsolete(node->st_commits);
200
+ rrdset_is_obsolete(node->st_commit_timings);
201
+ }
202
+ freez(node->commit_stats_filename);
203
+ node->commit_stats_filename = NULL;
204
+}
205
+
206
static inline void btrfs_free_disk(BTRFS_DISK *d) {
207
freez(d->name);
208
freez(d->size_filename);
209
freez(d);
210
}
211
212
+static inline void btrfs_free_device(BTRFS_DEVICE *d) {
213
+ if(d->st_error_stats)
214
+ rrdset_is_obsolete(d->st_error_stats);
215
+ freez(d->error_stats_filename);
216
+ freez(d);
217
+}
218
+
219
static inline void btrfs_free_node(BTRFS_NODE *node) {
220
// collector_info("BTRFS: destroying '%s'", node->id);
221
240
freez(node->allocation_system_bytes_used_filename);
241
freez(node->allocation_system_total_bytes_filename);
242
243
+ btrfs_free_commits_stats(node);
244
+
245
while(node->disks) {
246
BTRFS_DISK *d = node->disks;
247
node->disks = node->disks->next;
248
btrfs_free_disk(d);
249
}
250
251
+ while(node->devices) {
252
+ BTRFS_DEVICE *d = node->devices;
253
+ node->devices = node->devices->next;
254
+ btrfs_free_device(d);
255
+ }
256
+
257
freez(node->label);
258
freez(node->id);
259
freez(node);
365
return 0;
366
}
367
368
+static inline int find_btrfs_devices(BTRFS_NODE *node, const char *path) {
369
+ char filename[FILENAME_MAX + 1];
370
+
371
+ BTRFS_DEVICE *d;
372
+ for(d = node->devices ; d ; d = d->next)
373
+ d->exists = 0;
374
+
375
+ DIR *dir = opendir(path);
376
+ if (!dir) {
377
+ if(!node->logged_error) {
378
+ collector_error("BTRFS: Cannot open directory '%s'.", path);
379
+ node->logged_error = 1;
380
+ }
381
+ return 1;
382
+ }
383
+ node->logged_error = 0;
384
+
385
+ struct dirent *de = NULL;
386
+ while ((de = readdir(dir))) {
387
+ if (de->d_type != DT_DIR
388
+ || !strcmp(de->d_name, ".")
389
+ || !strcmp(de->d_name, "..")
390
+ ) {
391
+ // collector_info("BTRFS: ignoring '%s'", de->d_name);
392
+ continue;
393
+ }
394
+
395
+ collector_info("BTRFS: device found '%s'", de->d_name);
396
+
397
+ // --------------------------------------------------------------------
398
+ // search for it
399
+
400
+ for(d = node->devices ; d ; d = d->next) {
401
+ if(str2ll(de->d_name, NULL) == d->id){
402
+ collector_info("BTRFS: existing device id '%d'", d->id);
403
+ break;
404
+ }
405
+ }
406
+
407
+ // --------------------------------------------------------------------
408
+ // did we find it?
409
+
410
+ if(!d) {
411
+ d = callocz(sizeof(BTRFS_DEVICE), 1);
412
+
413
+ d->id = str2ll(de->d_name, NULL);
414
+ collector_info("BTRFS: new device with id '%d'", d->id);
415
+
416
+ snprintfz(filename, FILENAME_MAX, "%s/%d/error_stats", path, d->id);
417
+ d->error_stats_filename = strdupz(filename);
418
+ collector_info("BTRFS: error_stats_filename '%s'", filename);
419
+
420
+ // link it
421
+ d->next = node->devices;
422
+ node->devices = d;
423
+ }
424
+
425
+ d->exists = 1;
426
+
427
+
428
+ // --------------------------------------------------------------------
429
+ // update the values
430
+
431
+ if(unlikely(collect_btrfs_error_stats(d)))
432
+ d->exists = 0; // 'd' will be garbaged collected in loop below
433
+ }
434
+ closedir(dir);
435
+
436
+ // ------------------------------------------------------------------------
437
+ // cleanup
438
+
439
+ BTRFS_DEVICE *last = NULL;
440
+ d = node->devices;
441
+
442
+ while(d) {
443
+ if(unlikely(!d->exists)) {
444
+ if(unlikely(node->devices == d)) {
445
+ node->devices = d->next;
446
+ btrfs_free_device(d);
447
+ d = node->devices;
448
+ last = NULL;
449
+ }
450
+ else {
451
+ last->next = d->next;
452
+ btrfs_free_device(d);
453
+ d = last->next;
454
+ }
455
+
456
+ continue;
457
+ }
458
+
459
+ last = d;
460
+ d = d->next;
461
+ }
462
+
463
+ return 0;
464
+}
465
+
466
231
-static inline int find_all_btrfs_pools(const char *path) {
467
+static inline int find_all_btrfs_pools(const char *path, int update_every) {
468
static int logged_error = 0;
469
char filename[FILENAME_MAX + 1];
470
510
snprintfz(filename, FILENAME_MAX, "%s/%s/devices", path, de->d_name);
511
find_btrfs_disks(node, filename);
512
513
+ // update devices
514
+ snprintfz(filename, FILENAME_MAX, "%s/%s/devinfo", path, de->d_name);
515
+ find_btrfs_devices(node, filename);
516
+
517
continue;
518
}
519
546
node->label = strdupz(node->id);
547
}
548
309
- //snprintfz(filename, FILENAME_MAX, "%s/%s/sectorsize", path, de->d_name);
310
- //if(read_single_number_file(filename, &node->sectorsize) != 0) {
311
- // collector_error("BTRFS: failed to read '%s'", filename);
312
- // btrfs_free_node(node);
313
- // continue;
314
- //}
315
-
316
- //snprintfz(filename, FILENAME_MAX, "%s/%s/nodesize", path, de->d_name);
317
- //if(read_single_number_file(filename, &node->nodesize) != 0) {
318
- // collector_error("BTRFS: failed to read '%s'", filename);
319
- // btrfs_free_node(node);
320
- // continue;
321
- //}
322
-
323
- //snprintfz(filename, FILENAME_MAX, "%s/%s/quota_override", path, de->d_name);
324
- //if(read_single_number_file(filename, &node->quota_override) != 0) {
325
- // collector_error("BTRFS: failed to read '%s'", filename);
326
- // btrfs_free_node(node);
327
- // continue;
328
- //}
329
-
549
// --------------------------------------------------------------------
550
// macros to simplify our life
551
600
init_btrfs_allocation_section_field(system, disk_total);
601
init_btrfs_allocation_section_field(system, disk_used);
602
603
+ // --------------------------------------------------------------------
604
+ // commit stats
605
+
606
+ snprintfz(filename, FILENAME_MAX, "%s/%s/commit_stats", path, de->d_name);
607
+ if(!node->commit_stats_filename) node->commit_stats_filename = strdupz(filename);
608
+ if(unlikely(collect_btrfs_commits_stats(node, update_every))){
609
+ collector_error("BTRFS: failed to collect commit stats for '%s'", node->id);
610
+ btrfs_free_commits_stats(node);
611
+ }
612
613
// --------------------------------------------------------------------
614
// find all disks related to this node
617
snprintfz(filename, FILENAME_MAX, "%s/%s/devices", path, de->d_name);
618
find_btrfs_disks(node, filename);
619
620
+ // --------------------------------------------------------------------
621
+ // find all devices related to this node
622
+
623
+ snprintfz(filename, FILENAME_MAX, "%s/%s/devinfo", path, de->d_name);
624
+ find_btrfs_devices(node, filename);
625
626
// --------------------------------------------------------------------
627
// link it
664
}
665
666
static void add_labels_to_btrfs(BTRFS_NODE *n, RRDSET *st) {
434
- rrdlabels_add(st->rrdlabels, "device", n->id, RRDLABEL_SRC_AUTO);
435
- rrdlabels_add(st->rrdlabels, "device_label", n->label, RRDLABEL_SRC_AUTO);
667
+ rrdlabels_add(st->rrdlabels, "filesystem_uuid", n->id, RRDLABEL_SRC_AUTO);
668
+ rrdlabels_add(st->rrdlabels, "filesystem_label", n->label, RRDLABEL_SRC_AUTO);
669
}
670
671
int do_sys_fs_btrfs(int update_every, usec_t dt) {
673
, do_allocation_disks = CONFIG_BOOLEAN_AUTO
674
, do_allocation_system = CONFIG_BOOLEAN_AUTO
675
, do_allocation_data = CONFIG_BOOLEAN_AUTO
443
- , do_allocation_metadata = CONFIG_BOOLEAN_AUTO;
676
+ , do_allocation_metadata = CONFIG_BOOLEAN_AUTO
677
+ , do_commit_stats = CONFIG_BOOLEAN_AUTO
678
+ , do_error_stats = CONFIG_BOOLEAN_AUTO;
679
680
static usec_t refresh_delta = 0, refresh_every = 60 * USEC_PER_SEC;
681
static char *btrfs_path = NULL;
696
do_allocation_data = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "data allocation", do_allocation_data);
697
do_allocation_metadata = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "metadata allocation", do_allocation_metadata);
698
do_allocation_system = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "system allocation", do_allocation_system);
699
+ do_commit_stats = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "commit stats", do_commit_stats);
700
+ do_error_stats = config_get_boolean_ondemand("plugin:proc:/sys/fs/btrfs", "error stats", do_error_stats);
701
}
702
703
refresh_delta += dt;
704
if(refresh_delta >= refresh_every) {
705
refresh_delta = 0;
469
- find_all_btrfs_pools(btrfs_path);
706
+ find_all_btrfs_pools(btrfs_path, update_every);
707
}
708
709
BTRFS_NODE *node;
763
}
764
}
765
766
+ if(do_commit_stats != CONFIG_BOOLEAN_NO && node->commit_stats_filename) {
767
+ if (unlikely(collect_btrfs_commits_stats(node, update_every))) {
768
+ collector_error("BTRFS: failed to collect commit stats for '%s'", node->id);
769
+ btrfs_free_commits_stats(node);
770
+ }
771
+ }
772
+
773
+ if(do_error_stats != CONFIG_BOOLEAN_NO) {
774
+ for(BTRFS_DEVICE *d = node->devices ; d ; d = d->next) {
775
+ if(unlikely(collect_btrfs_error_stats(d))){
776
+ collector_error("BTRFS: failed to collect error stats for '%s', devid:'%d'", node->id, d->id);
777
+ /* make it refresh btrfs at the next iteration,
778
+ * btrfs_free_device(d) will be called in
779
+ * find_btrfs_devices() as part of the garbage collection */
780
+ refresh_delta = refresh_every;
781
+ }
782
+ }
783
+ }
784
+
785
// --------------------------------------------------------------------
786
// allocation/disks
787
793
if(unlikely(!node->st_allocation_disks)) {
794
char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
795
540
- snprintf(id, RRD_ID_LENGTH_MAX, "disk_%s", node->id);
541
- snprintf(name, RRD_ID_LENGTH_MAX, "disk_%s", node->label);
542
- snprintf(title, 200, "BTRFS Physical Disk Allocation");
796
+ snprintfz(id, RRD_ID_LENGTH_MAX, "disk_%s", node->id);
797
+ snprintfz(name, RRD_ID_LENGTH_MAX, "disk_%s", node->label);
798
+ snprintfz(title, 200, "BTRFS Physical Disk Allocation");
799
800
netdata_fix_chart_id(id);
801
netdata_fix_chart_name(name);
852
if(unlikely(!node->st_allocation_data)) {
853
char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
854
599
- snprintf(id, RRD_ID_LENGTH_MAX, "data_%s", node->id);
600
- snprintf(name, RRD_ID_LENGTH_MAX, "data_%s", node->label);
601
- snprintf(title, 200, "BTRFS Data Allocation");
855
+ snprintfz(id, RRD_ID_LENGTH_MAX, "data_%s", node->id);
856
+ snprintfz(name, RRD_ID_LENGTH_MAX, "data_%s", node->label);
857
+ snprintfz(title, 200, "BTRFS Data Allocation");
858
859
netdata_fix_chart_id(id);
860
netdata_fix_chart_name(name);
896
if(unlikely(!node->st_allocation_metadata)) {
897
char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
898
643
- snprintf(id, RRD_ID_LENGTH_MAX, "metadata_%s", node->id);
644
- snprintf(name, RRD_ID_LENGTH_MAX, "metadata_%s", node->label);
645
- snprintf(title, 200, "BTRFS Metadata Allocation");
899
+ snprintfz(id, RRD_ID_LENGTH_MAX, "metadata_%s", node->id);
900
+ snprintfz(name, RRD_ID_LENGTH_MAX, "metadata_%s", node->label);
901
+ snprintfz(title, 200, "BTRFS Metadata Allocation");
902
903
netdata_fix_chart_id(id);
904
netdata_fix_chart_name(name);
942
if(unlikely(!node->st_allocation_system)) {
943
char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
944
689
- snprintf(id, RRD_ID_LENGTH_MAX, "system_%s", node->id);
690
- snprintf(name, RRD_ID_LENGTH_MAX, "system_%s", node->label);
691
- snprintf(title, 200, "BTRFS System Allocation");
945
+ snprintfz(id, RRD_ID_LENGTH_MAX, "system_%s", node->id);
946
+ snprintfz(name, RRD_ID_LENGTH_MAX, "system_%s", node->label);
947
+ snprintfz(title, 200, "BTRFS System Allocation");
948
949
netdata_fix_chart_id(id);
950
netdata_fix_chart_name(name);
974
rrddim_set_by_pointer(node->st_allocation_system, node->rd_allocation_system_used, node->allocation_system_bytes_used);
975
rrdset_done(node->st_allocation_system);
976
}
977
+
978
+ // --------------------------------------------------------------------
979
+ // commit_stats
980
+
981
+ if(do_commit_stats == CONFIG_BOOLEAN_YES || (do_commit_stats == CONFIG_BOOLEAN_AUTO &&
982
+ (node->commits_total ||
983
+ netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
984
+ do_commit_stats = CONFIG_BOOLEAN_YES;
985
+
986
+ if(unlikely(!node->st_commits)) {
987
+ char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
988
+
989
+ snprintfz(id, RRD_ID_LENGTH_MAX, "commits_%s", node->id);
990
+ snprintfz(name, RRD_ID_LENGTH_MAX, "commits_%s", node->label);
991
+ snprintfz(title, 200, "BTRFS Commits");
992
+
993
+ netdata_fix_chart_id(id);
994
+ netdata_fix_chart_name(name);
995
+
996
+ node->st_commits = rrdset_create_localhost(
997
+ "btrfs"
998
+ , id
999
+ , name
1000
+ , node->label
1001
+ , "btrfs.commits"
1002
+ , title
1003
+ , "commits"
1004
+ , PLUGIN_PROC_NAME
1005
+ , PLUGIN_PROC_MODULE_BTRFS_NAME
1006
+ , NETDATA_CHART_PRIO_BTRFS_COMMITS
1007
+ , update_every
1008
+ , RRDSET_TYPE_LINE
1009
+ );
1010
+
1011
+ node->rd_commits = rrddim_add(node->st_commits, "commits", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1012
+
1013
+ add_labels_to_btrfs(node, node->st_commits);
1014
+ }
1015
+
1016
+ rrddim_set_by_pointer(node->st_commits, node->rd_commits, node->commits_new);
1017
+ rrdset_done(node->st_commits);
1018
+
1019
+ if(unlikely(!node->st_commits_percentage_time)) {
1020
+ char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
1021
+
1022
+ snprintfz(id, RRD_ID_LENGTH_MAX, "commits_perc_time_%s", node->id);
1023
+ snprintfz(name, RRD_ID_LENGTH_MAX, "commits_perc_time_%s", node->label);
1024
+ snprintfz(title, 200, "BTRFS Commits Time Share");
1025
+
1026
+ netdata_fix_chart_id(id);
1027
+ netdata_fix_chart_name(name);
1028
+
1029
+ node->st_commits_percentage_time = rrdset_create_localhost(
1030
+ "btrfs"
1031
+ , id
1032
+ , name
1033
+ , node->label
1034
+ , "btrfs.commits_perc_time"
1035
+ , title
1036
+ , "percentage"
1037
+ , PLUGIN_PROC_NAME
1038
+ , PLUGIN_PROC_MODULE_BTRFS_NAME
1039
+ , NETDATA_CHART_PRIO_BTRFS_COMMITS_PERC_TIME
1040
+ , update_every
1041
+ , RRDSET_TYPE_LINE
1042
+ );
1043
+
1044
+ node->rd_commits_percentage_time = rrddim_add(node->st_commits_percentage_time, "commits", NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE);
1045
+
1046
+ add_labels_to_btrfs(node, node->st_commits_percentage_time);
1047
+ }
1048
+
1049
+ rrddim_set_by_pointer(node->st_commits_percentage_time, node->rd_commits_percentage_time, node->commits_percentage_time);
1050
+ rrdset_done(node->st_commits_percentage_time);
1051
+
1052
+
1053
+ if(unlikely(!node->st_commit_timings)) {
1054
+ char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
1055
+
1056
+ snprintfz(id, RRD_ID_LENGTH_MAX, "commit_timings_%s", node->id);
1057
+ snprintfz(name, RRD_ID_LENGTH_MAX, "commit_timings_%s", node->label);
1058
+ snprintfz(title, 200, "BTRFS Commit Timings");
1059
+
1060
+ netdata_fix_chart_id(id);
1061
+ netdata_fix_chart_name(name);
1062
+
1063
+ node->st_commit_timings = rrdset_create_localhost(
1064
+ "btrfs"
1065
+ , id
1066
+ , name
1067
+ , node->label
1068
+ , "btrfs.commit_timings"
1069
+ , title
1070
+ , "ms"
1071
+ , PLUGIN_PROC_NAME
1072
+ , PLUGIN_PROC_MODULE_BTRFS_NAME
1073
+ , NETDATA_CHART_PRIO_BTRFS_COMMIT_TIMINGS
1074
+ , update_every
1075
+ , RRDSET_TYPE_LINE
1076
+ );
1077
+
1078
+ node->rd_commit_timings_last = rrddim_add(node->st_commit_timings, "last", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1079
+ node->rd_commit_timings_max = rrddim_add(node->st_commit_timings, "max", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1080
+
1081
+ add_labels_to_btrfs(node, node->st_commit_timings);
1082
+ }
1083
+
1084
+ rrddim_set_by_pointer(node->st_commit_timings, node->rd_commit_timings_last, node->commit_timings_last);
1085
+ rrddim_set_by_pointer(node->st_commit_timings, node->rd_commit_timings_max, node->commit_timings_max);
1086
+ rrdset_done(node->st_commit_timings);
1087
+ }
1088
+
1089
+ // --------------------------------------------------------------------
1090
+ // error_stats per device
1091
+
1092
+ if(do_error_stats == CONFIG_BOOLEAN_YES || (do_error_stats == CONFIG_BOOLEAN_AUTO &&
1093
+ (node->devices ||
1094
+ netdata_zero_metrics_enabled == CONFIG_BOOLEAN_YES))) {
1095
+ do_error_stats = CONFIG_BOOLEAN_YES;
1096
+
1097
+ for(BTRFS_DEVICE *d = node->devices ; d ; d = d->next) {
1098
+
1099
+ if(unlikely(!d->st_error_stats)) {
1100
+ char id[RRD_ID_LENGTH_MAX + 1], name[RRD_ID_LENGTH_MAX + 1], title[200 + 1];
1101
+
1102
+ snprintfz(id, RRD_ID_LENGTH_MAX, "device_errors_dev%d_%s", d->id, node->id);
1103
+ snprintfz(name, RRD_ID_LENGTH_MAX, "device_errors_dev%d_%s", d->id, node->label);
1104
+ snprintfz(title, 200, "BTRFS Device Errors");
1105
+
1106
+ netdata_fix_chart_id(id);
1107
+ netdata_fix_chart_name(name);
1108
+
1109
+ d->st_error_stats = rrdset_create_localhost(
1110
+ "btrfs"
1111
+ , id
1112
+ , name
1113
+ , node->label
1114
+ , "btrfs.device_errors"
1115
+ , title
1116
+ , "errors"
1117
+ , PLUGIN_PROC_NAME
1118
+ , PLUGIN_PROC_MODULE_BTRFS_NAME
1119
+ , NETDATA_CHART_PRIO_BTRFS_ERRORS
1120
+ , update_every
1121
+ , RRDSET_TYPE_LINE
1122
+ );
1123
+
1124
+ char rd_id[RRD_ID_LENGTH_MAX + 1];
1125
+ snprintfz(rd_id, RRD_ID_LENGTH_MAX, "write_errs");
1126
+ d->rd_write_errs = rrddim_add(d->st_error_stats, rd_id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1127
+ snprintfz(rd_id, RRD_ID_LENGTH_MAX, "read_errs");
1128
+ d->rd_read_errs = rrddim_add(d->st_error_stats, rd_id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1129
+ snprintfz(rd_id, RRD_ID_LENGTH_MAX, "flush_errs");
1130
+ d->rd_flush_errs = rrddim_add(d->st_error_stats, rd_id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1131
+ snprintfz(rd_id, RRD_ID_LENGTH_MAX, "corruption_errs");
1132
+ d->rd_corruption_errs = rrddim_add(d->st_error_stats, rd_id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1133
+ snprintfz(rd_id, RRD_ID_LENGTH_MAX, "generation_errs");
1134
+ d->rd_generation_errs = rrddim_add(d->st_error_stats, rd_id, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1135
+
1136
+ char dev_id[5];
1137
+ snprintfz(dev_id, 4, "%d", d->id);
1138
+ rrdlabels_add(d->st_error_stats->rrdlabels, "device_id", dev_id, RRDLABEL_SRC_AUTO);
1139
+ add_labels_to_btrfs(node, d->st_error_stats);
1140
+ }
1141
+
1142
+ rrddim_set_by_pointer(d->st_error_stats, d->rd_write_errs, d->write_errs);
1143
+ rrddim_set_by_pointer(d->st_error_stats, d->rd_read_errs, d->read_errs);
1144
+ rrddim_set_by_pointer(d->st_error_stats, d->rd_flush_errs, d->flush_errs);
1145
+ rrddim_set_by_pointer(d->st_error_stats, d->rd_corruption_errs, d->corruption_errs);
1146
+ rrddim_set_by_pointer(d->st_error_stats, d->rd_generation_errs, d->generation_errs);
1147
+
1148
+ rrdset_done(d->st_error_stats);
1149
+ }
1150
+ }
1151
}
1152
1153
return 0;