monitor bcache; fixes #3482
Costa Tsaousis (ktsaou) committed
Mar 5, 2018 at 09:04 UTC
a133e33b3de3c9e24614e8bf8de7d4bbeb106626
1 file changed
+463
-143
src/proc_diskstats.c
+463
-143
@@ -21,7 +21,6 @@ static struct disk {
21
char *mount_point;
22
23
// disk options caching
24
- int configured;
24
int do_io;
25
int do_ops;
26
int do_mops;
@@ -29,9 +28,21 @@ static struct disk {
28
int do_qops;
29
int do_util;
30
int do_backlog;
31
+ int do_bcache;
32
33
int updated;
34
35
+ int device_is_bcache;
36
+
37
+ char *bcache_filename_dirty_data;
38
+ char *bcache_filename_cache_available_percent;
39
+ char *bcache_filename_cache_hits;
40
+ char *bcache_filename_cache_misses;
41
+ char *bcache_filename_cache_miss_collisions;
42
+ char *bcache_filename_cache_bypass_hits;
43
+ char *bcache_filename_cache_bypass_misses;
44
+ char *bcache_filename_cache_readaheads;
45
+
46
RRDSET *st_io;
47
RRDDIM *rd_io_reads;
48
RRDDIM *rd_io_writes;
@@ -68,21 +79,84 @@ static struct disk {
79
RRDSET *st_svctm;
80
RRDDIM *rd_svctm_svctm;
81
82
+ RRDSET *st_bcache_size;
83
+ RRDDIM *rd_bcache_dirty_size;
84
+
85
+ RRDSET *st_bcache_usage;
86
+ RRDDIM *rd_bcache_available_percent;
87
+
88
+ RRDSET *st_bcache;
89
+ RRDDIM *rd_bcache_hits;
90
+ RRDDIM *rd_bcache_misses;
91
+ RRDDIM *rd_bcache_miss_collisions;
92
+
93
+ RRDSET *st_bcache_bypass;
94
+ RRDDIM *rd_bcache_bypass_hits;
95
+ RRDDIM *rd_bcache_bypass_misses;
96
+
97
+ RRDSET *st_bcache_readaheads;
98
+ RRDDIM *rd_bcache_readaheads;
99
+
100
struct disk *next;
101
} *disk_root = NULL;
102
103
#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_is_obsolete(st); (st) = NULL; } } while(st)
104
76
-static char *path_to_get_hw_sector_size = NULL;
77
-static char *path_to_get_hw_sector_size_partitions = NULL;
105
+// static char *path_to_get_hw_sector_size = NULL;
106
+// static char *path_to_get_hw_sector_size_partitions = NULL;
107
static char *path_to_sys_dev_block_major_minor_string = NULL;
108
static char *path_to_sys_block_device = NULL;
109
+static char *path_to_sys_block_device_bcache = NULL;
110
static char *path_to_sys_devices_virtual_block_device = NULL;
111
static char *path_to_device_mapper = NULL;
112
static char *path_to_device_label = NULL;
113
static char *path_to_device_id = NULL;
114
static int name_disks_by_id = CONFIG_BOOLEAN_NO;
115
116
+static int global_enable_new_disks_detected_at_runtime = CONFIG_BOOLEAN_YES,
117
+ global_enable_performance_for_physical_disks = CONFIG_BOOLEAN_AUTO,
118
+ global_enable_performance_for_virtual_disks = CONFIG_BOOLEAN_AUTO,
119
+ global_enable_performance_for_partitions = CONFIG_BOOLEAN_NO,
120
+ global_do_io = CONFIG_BOOLEAN_AUTO,
121
+ global_do_ops = CONFIG_BOOLEAN_AUTO,
122
+ global_do_mops = CONFIG_BOOLEAN_AUTO,
123
+ global_do_iotime = CONFIG_BOOLEAN_AUTO,
124
+ global_do_qops = CONFIG_BOOLEAN_AUTO,
125
+ global_do_util = CONFIG_BOOLEAN_AUTO,
126
+ global_do_backlog = CONFIG_BOOLEAN_AUTO,
127
+ global_do_bcache = CONFIG_BOOLEAN_AUTO,
128
+ globals_initialized = 0,
129
+ global_cleanup_removed_disks = 1;
130
+
131
+static SIMPLE_PATTERN *excluded_disks = NULL;
132
+
133
+static inline int is_major_enabled(int major) {
134
+ static int8_t *major_configs = NULL;
135
+ static size_t major_size = 0;
136
+
137
+ if(major < 0) return 1;
138
+
139
+ size_t wanted_size = (size_t)major + 1;
140
+
141
+ if(major_size < wanted_size) {
142
+ major_configs = reallocz(major_configs, wanted_size * sizeof(int8_t));
143
+
144
+ size_t i;
145
+ for(i = major_size; i < wanted_size ; i++)
146
+ major_configs[i] = -1;
147
+
148
+ major_size = wanted_size;
149
+ }
150
+
151
+ if(major_configs[major] == -1) {
152
+ char buffer[CONFIG_MAX_NAME + 1];
153
+ snprintfz(buffer, CONFIG_MAX_NAME, "performance metrics for disks with major %d", major);
154
+ major_configs[major] = (char)config_get_boolean(CONFIG_SECTION_DISKSTATS, buffer, 1);
155
+ }
156
+
157
+ return (int)major_configs[major];
158
+}
159
+
160
static inline int get_disk_name_from_path(const char *path, char *result, size_t result_size, unsigned long major, unsigned long minor, char *disk) {
161
char filename[FILENAME_MAX + 1];
162
int found = 0;
@@ -160,6 +234,103 @@ static inline char *get_disk_name(unsigned long major, unsigned long minor, char
234
return strdup(result);
235
}
236
237
+static void get_disk_config(struct disk *d) {
238
+ int def_enable = global_enable_new_disks_detected_at_runtime;
239
+
240
+ if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk)))
241
+ def_enable = CONFIG_BOOLEAN_NO;
242
+
243
+ char var_name[4096 + 1];
244
+ snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", d->disk);
245
+
246
+ def_enable = config_get_boolean_ondemand(var_name, "enable", def_enable);
247
+ if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) {
248
+ // the user does not want any metrics for this disk
249
+ d->do_io = CONFIG_BOOLEAN_NO;
250
+ d->do_ops = CONFIG_BOOLEAN_NO;
251
+ d->do_mops = CONFIG_BOOLEAN_NO;
252
+ d->do_iotime = CONFIG_BOOLEAN_NO;
253
+ d->do_qops = CONFIG_BOOLEAN_NO;
254
+ d->do_util = CONFIG_BOOLEAN_NO;
255
+ d->do_backlog = CONFIG_BOOLEAN_NO;
256
+ d->do_bcache = CONFIG_BOOLEAN_NO;
257
+ }
258
+ else {
259
+ // this disk is enabled
260
+ // check its direct settings
261
+
262
+ int def_performance = CONFIG_BOOLEAN_AUTO;
263
+
264
+ // since this is 'on demand' we can figure the performance settings
265
+ // based on the type of disk
266
+
267
+ if(!d->device_is_bcache) {
268
+ switch(d->type) {
269
+ default:
270
+ case DISK_TYPE_UNKNOWN:
271
+ break;
272
+
273
+ case DISK_TYPE_PHYSICAL:
274
+ def_performance = global_enable_performance_for_physical_disks;
275
+ break;
276
+
277
+ case DISK_TYPE_PARTITION:
278
+ def_performance = global_enable_performance_for_partitions;
279
+ break;
280
+
281
+ case DISK_TYPE_VIRTUAL:
282
+ def_performance = global_enable_performance_for_virtual_disks;
283
+ break;
284
+ }
285
+ }
286
+
287
+ // check if we have to disable performance for this disk
288
+ if(def_performance)
289
+ def_performance = is_major_enabled((int)d->major);
290
+
291
+ // ------------------------------------------------------------
292
+ // now we have def_performance and def_space
293
+ // to work further
294
+
295
+ // def_performance
296
+ // check the user configuration (this will also show our 'on demand' decision)
297
+ def_performance = config_get_boolean_ondemand(var_name, "enable performance metrics", def_performance);
298
+
299
+ int ddo_io = CONFIG_BOOLEAN_NO,
300
+ ddo_ops = CONFIG_BOOLEAN_NO,
301
+ ddo_mops = CONFIG_BOOLEAN_NO,
302
+ ddo_iotime = CONFIG_BOOLEAN_NO,
303
+ ddo_qops = CONFIG_BOOLEAN_NO,
304
+ ddo_util = CONFIG_BOOLEAN_NO,
305
+ ddo_backlog = CONFIG_BOOLEAN_NO,
306
+ ddo_bcache = CONFIG_BOOLEAN_NO;
307
+
308
+ // we enable individual performance charts only when def_performance is not disabled
309
+ if(unlikely(def_performance != CONFIG_BOOLEAN_NO)) {
310
+ ddo_io = global_do_io,
311
+ ddo_ops = global_do_ops,
312
+ ddo_mops = global_do_mops,
313
+ ddo_iotime = global_do_iotime,
314
+ ddo_qops = global_do_qops,
315
+ ddo_util = global_do_util,
316
+ ddo_backlog = global_do_backlog,
317
+ ddo_bcache = global_do_bcache;
318
+ }
319
+
320
+ d->do_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
321
+ d->do_ops = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
322
+ d->do_mops = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
323
+ d->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
324
+ d->do_qops = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
325
+ d->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
326
+ d->do_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
327
+
328
+ if(d->device_is_bcache)
329
+ d->do_bcache = config_get_boolean_ondemand(var_name, "bcache", ddo_bcache);
330
+ else
331
+ d->do_bcache = 0;
332
+ }
333
+}
334
335
static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) {
336
static struct mountinfo *disk_mountinfo_root = NULL;
@@ -183,7 +354,6 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
354
d->major = major;
355
d->minor = minor;
356
d->type = DISK_TYPE_UNKNOWN; // Default type. Changed later if not correct.
186
- d->configured = 0;
357
d->sector_size = 512; // the default, will be changed below
358
d->next = NULL;
359
@@ -299,51 +469,72 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
469
}
470
*/
471
302
- return d;
303
-}
472
+ // ------------------------------------------------------------------------
473
+ // check if the device is a bcache
474
305
-static inline int is_major_enabled(int major) {
306
- static int8_t *major_configs = NULL;
307
- static size_t major_size = 0;
475
+ struct stat bcache;
476
+ snprintfz(buffer, FILENAME_MAX, path_to_sys_block_device_bcache, disk);
477
+ if(unlikely(stat(buffer, &bcache) == 0 && (bcache.st_mode & S_IFMT) == S_IFDIR)) {
478
+ // we have the 'bcache' directory
479
+ d->device_is_bcache = 1;
480
309
- if(major < 0) return 1;
481
+ char buffer2[FILENAME_MAX + 1];
482
311
- size_t wanted_size = (size_t)major + 1;
483
+ snprintfz(buffer2, FILENAME_MAX, "%s/dirty_data", buffer);
484
+ if(access(buffer2, R_OK) == 0)
485
+ d->bcache_filename_dirty_data = strdupz(buffer2);
486
+ else
487
+ error("bcache file '%s' cannot be read.", buffer2);
488
313
- if(major_size < wanted_size) {
314
- major_configs = reallocz(major_configs, wanted_size * sizeof(int8_t));
489
+ snprintfz(buffer2, FILENAME_MAX, "%s/cache/cache_available_percent", buffer);
490
+ if(access(buffer2, R_OK) == 0)
491
+ d->bcache_filename_cache_available_percent = strdupz(buffer2);
492
+ else
493
+ error("bcache file '%s' cannot be read.", buffer2);
494
316
- size_t i;
317
- for(i = major_size; i < wanted_size ; i++)
318
- major_configs[i] = -1;
495
+ snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_hits", buffer);
496
+ if(access(buffer2, R_OK) == 0)
497
+ d->bcache_filename_cache_hits = strdupz(buffer2);
498
+ else
499
+ error("bcache file '%s' cannot be read.", buffer2);
500
320
- major_size = wanted_size;
321
- }
501
+ snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_misses", buffer);
502
+ if(access(buffer2, R_OK) == 0)
503
+ d->bcache_filename_cache_misses = strdupz(buffer2);
504
+ else
505
+ error("bcache file '%s' cannot be read.", buffer2);
506
323
- if(major_configs[major] == -1) {
324
- char buffer[CONFIG_MAX_NAME + 1];
325
- snprintfz(buffer, CONFIG_MAX_NAME, "performance metrics for disks with major %d", major);
326
- major_configs[major] = (char)config_get_boolean(CONFIG_SECTION_DISKSTATS, buffer, 1);
507
+ snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_bypass_hits", buffer);
508
+ if(access(buffer2, R_OK) == 0)
509
+ d->bcache_filename_cache_bypass_hits = strdupz(buffer2);
510
+ else
511
+ error("bcache file '%s' cannot be read.", buffer2);
512
+
513
+ snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_bypass_misses", buffer);
514
+ if(access(buffer2, R_OK) == 0)
515
+ d->bcache_filename_cache_bypass_misses = strdupz(buffer2);
516
+ else
517
+ error("bcache file '%s' cannot be read.", buffer2);
518
+
519
+ snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_miss_collisions", buffer);
520
+ if(access(buffer2, R_OK) == 0)
521
+ d->bcache_filename_cache_miss_collisions = strdupz(buffer2);
522
+ else
523
+ error("bcache file '%s' cannot be read.", buffer2);
524
+
525
+ snprintfz(buffer2, FILENAME_MAX, "%s/stats_total/cache_readaheads", buffer);
526
+ if(access(buffer2, R_OK) == 0)
527
+ d->bcache_filename_cache_readaheads = strdupz(buffer2);
528
+ else
529
+ error("bcache file '%s' cannot be read.", buffer2);
530
}
531
329
- return (int)major_configs[major];
532
+ get_disk_config(d);
533
+ return d;
534
}
535
536
int do_proc_diskstats(int update_every, usec_t dt) {
537
static procfile *ff = NULL;
334
- static int global_enable_new_disks_detected_at_runtime = CONFIG_BOOLEAN_YES,
335
- global_enable_performance_for_physical_disks = CONFIG_BOOLEAN_AUTO,
336
- global_enable_performance_for_virtual_disks = CONFIG_BOOLEAN_AUTO,
337
- global_enable_performance_for_partitions = CONFIG_BOOLEAN_NO,
338
- global_do_io = CONFIG_BOOLEAN_AUTO,
339
- global_do_ops = CONFIG_BOOLEAN_AUTO,
340
- global_do_mops = CONFIG_BOOLEAN_AUTO,
341
- global_do_iotime = CONFIG_BOOLEAN_AUTO,
342
- global_do_qops = CONFIG_BOOLEAN_AUTO,
343
- global_do_util = CONFIG_BOOLEAN_AUTO,
344
- global_do_backlog = CONFIG_BOOLEAN_AUTO,
345
- globals_initialized = 0,
346
- global_cleanup_removed_disks = 1;
538
539
if(unlikely(!globals_initialized)) {
540
globals_initialized = 1;
@@ -360,6 +551,7 @@ int do_proc_diskstats(int update_every, usec_t dt) {
551
global_do_qops = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "queued operations for all disks", global_do_qops);
552
global_do_util = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "utilization percentage for all disks", global_do_util);
553
global_do_backlog = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "backlog for all disks", global_do_backlog);
554
+ global_do_bcache = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "bcache for all disks", global_do_bcache);
555
556
global_cleanup_removed_disks = config_get_boolean(CONFIG_SECTION_DISKSTATS, "remove charts of removed disks" , global_cleanup_removed_disks);
557
@@ -368,17 +560,20 @@ int do_proc_diskstats(int update_every, usec_t dt) {
560
snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s");
561
path_to_sys_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device", buffer);
562
563
+ snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/bcache");
564
+ path_to_sys_block_device_bcache = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device bcache", buffer);
565
+
566
snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/virtual/block/%s");
567
path_to_sys_devices_virtual_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get virtual block device", buffer);
568
569
snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s");
570
path_to_sys_dev_block_major_minor_string = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer);
571
377
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
378
- path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer);
572
+ //snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
573
+ //path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer);
574
380
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
381
- path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer);
575
+ //snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
576
+ //path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer);
577
578
snprintfz(buffer, FILENAME_MAX, "%s/dev/mapper", netdata_configured_host_prefix);
579
path_to_device_mapper = config_get(CONFIG_SECTION_DISKSTATS, "path to device mapper", buffer);
@@ -390,6 +585,12 @@ int do_proc_diskstats(int update_every, usec_t dt) {
585
path_to_device_id = config_get(CONFIG_SECTION_DISKSTATS, "path to /dev/disk/by-id", buffer);
586
587
name_disks_by_id = config_get_boolean(CONFIG_SECTION_DISKSTATS, "name disks by id", name_disks_by_id);
588
+
589
+ excluded_disks = simple_pattern_create(
590
+ config_get(CONFIG_SECTION_DISKSTATS, "exclude disks", DEFAULT_EXCLUDED_DISKS)
591
+ , NULL
592
+ , SIMPLE_PATTERN_EXACT
593
+ );
594
}
595
596
// --------------------------------------------------------------------------
@@ -483,6 +684,9 @@ int do_proc_diskstats(int update_every, usec_t dt) {
684
struct disk *d = get_disk(major, minor, disk);
685
d->updated = 1;
686
687
+ // --------------------------------------------------------------------------
688
+ // count the global system disk I/O of physical disks
689
+
690
if(unlikely(d->type == DISK_TYPE_PHYSICAL)) {
691
system_read_kb += readsectors * d->sector_size / 1024;
692
system_write_kb += writesectors * d->sector_size / 1024;
@@ -495,109 +699,6 @@ int do_proc_diskstats(int update_every, usec_t dt) {
699
if(!family) family = d->disk;
700
701
498
- // --------------------------------------------------------------------------
499
- // Check the configuration for the device
500
-
501
- if(unlikely(!d->configured)) {
502
- d->configured = 1;
503
-
504
- static SIMPLE_PATTERN *excluded_disks = NULL;
505
-
506
- if(unlikely(!excluded_disks)) {
507
- excluded_disks = simple_pattern_create(
508
- config_get(CONFIG_SECTION_DISKSTATS, "exclude disks", DEFAULT_EXCLUDED_DISKS)
509
- , NULL
510
- , SIMPLE_PATTERN_EXACT
511
- );
512
- }
513
-
514
- int def_enable = global_enable_new_disks_detected_at_runtime;
515
-
516
- if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk)))
517
- def_enable = CONFIG_BOOLEAN_NO;
518
-
519
- char var_name[4096 + 1];
520
- snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", d->disk);
521
-
522
- def_enable = config_get_boolean_ondemand(var_name, "enable", def_enable);
523
- if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) {
524
- // the user does not want any metrics for this disk
525
- d->do_io = CONFIG_BOOLEAN_NO;
526
- d->do_ops = CONFIG_BOOLEAN_NO;
527
- d->do_mops = CONFIG_BOOLEAN_NO;
528
- d->do_iotime = CONFIG_BOOLEAN_NO;
529
- d->do_qops = CONFIG_BOOLEAN_NO;
530
- d->do_util = CONFIG_BOOLEAN_NO;
531
- d->do_backlog = CONFIG_BOOLEAN_NO;
532
- }
533
- else {
534
- // this disk is enabled
535
- // check its direct settings
536
-
537
- int def_performance = CONFIG_BOOLEAN_AUTO;
538
-
539
- // since this is 'on demand' we can figure the performance settings
540
- // based on the type of disk
541
-
542
- switch(d->type) {
543
- default:
544
- case DISK_TYPE_UNKNOWN:
545
- break;
546
-
547
- case DISK_TYPE_PHYSICAL:
548
- def_performance = global_enable_performance_for_physical_disks;
549
- break;
550
-
551
- case DISK_TYPE_PARTITION:
552
- def_performance = global_enable_performance_for_partitions;
553
- break;
554
-
555
- case DISK_TYPE_VIRTUAL:
556
- def_performance = global_enable_performance_for_virtual_disks;
557
- break;
558
- }
559
-
560
- // check if we have to disable performance for this disk
561
- if(def_performance)
562
- def_performance = is_major_enabled((int)major);
563
-
564
- // ------------------------------------------------------------
565
- // now we have def_performance and def_space
566
- // to work further
567
-
568
- // def_performance
569
- // check the user configuration (this will also show our 'on demand' decision)
570
- def_performance = config_get_boolean_ondemand(var_name, "enable performance metrics", def_performance);
571
-
572
- int ddo_io = CONFIG_BOOLEAN_NO,
573
- ddo_ops = CONFIG_BOOLEAN_NO,
574
- ddo_mops = CONFIG_BOOLEAN_NO,
575
- ddo_iotime = CONFIG_BOOLEAN_NO,
576
- ddo_qops = CONFIG_BOOLEAN_NO,
577
- ddo_util = CONFIG_BOOLEAN_NO,
578
- ddo_backlog = CONFIG_BOOLEAN_NO;
579
-
580
- // we enable individual performance charts only when def_performance is not disabled
581
- if(unlikely(def_performance != CONFIG_BOOLEAN_NO)) {
582
- ddo_io = global_do_io,
583
- ddo_ops = global_do_ops,
584
- ddo_mops = global_do_mops,
585
- ddo_iotime = global_do_iotime,
586
- ddo_qops = global_do_qops,
587
- ddo_util = global_do_util,
588
- ddo_backlog = global_do_backlog;
589
- }
590
-
591
- d->do_io = config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
592
- d->do_ops = config_get_boolean_ondemand(var_name, "operations", ddo_ops);
593
- d->do_mops = config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
594
- d->do_iotime = config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
595
- d->do_qops = config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
596
- d->do_util = config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
597
- d->do_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);
598
- }
599
- }
600
-
702
// --------------------------------------------------------------------------
703
// Do performance metrics
704
@@ -918,6 +1019,211 @@ int do_proc_diskstats(int update_every, usec_t dt) {
1019
rrdset_done(d->st_svctm);
1020
}
1021
}
1022
+
1023
+ // --------------------------------------------------------------------------
1024
+ // read bcache metrics and generate the bcache charts
1025
+
1026
+ if(d->device_is_bcache && d->do_bcache != CONFIG_BOOLEAN_NO) {
1027
+ unsigned long long int
1028
+ cache_bypass_hits = 0,
1029
+ cache_bypass_misses = 0,
1030
+ cache_hits = 0,
1031
+ cache_miss_collisions = 0,
1032
+ cache_misses = 0,
1033
+ cache_readaheads = 0,
1034
+ dirty_size = 0,
1035
+ cache_available_percent = 0;
1036
+
1037
+ // read the bcache values
1038
+
1039
+ if(d->bcache_filename_dirty_data) {
1040
+ char buffer[50 + 1];
1041
+ if(read_file(d->bcache_filename_dirty_data, buffer, 50) == 0) {
1042
+ static int unknown_units_error = 10;
1043
+
1044
+ char *end = NULL;
1045
+ long double value = str2ld(buffer, &end);
1046
+ if(end && *end) {
1047
+ if(*end == 'k' || *end == 'K')
1048
+ dirty_size = (unsigned long long int)(value * 1024.0);
1049
+ else if(*end == 'M')
1050
+ dirty_size = (unsigned long long int)(value * 1024.0 * 1024.0);
1051
+ else if(*end == 'G' || *end == 'g')
1052
+ dirty_size = (unsigned long long int)(value * 1024.0 * 1024.0 * 1024.0);
1053
+ else if(unknown_units_error > 0) {
1054
+ error("bcache provides value '%s' with unknown units '%s'", buffer, end);
1055
+ unknown_units_error--;
1056
+ }
1057
+ }
1058
+ }
1059
+ }
1060
+
1061
+ if(d->bcache_filename_cache_available_percent)
1062
+ read_single_number_file(d->bcache_filename_cache_available_percent, &cache_available_percent);
1063
+
1064
+ if(d->bcache_filename_cache_hits)
1065
+ read_single_number_file(d->bcache_filename_cache_hits, &cache_hits);
1066
+
1067
+ if(d->bcache_filename_cache_misses)
1068
+ read_single_number_file(d->bcache_filename_cache_misses, &cache_misses);
1069
+
1070
+ if(d->bcache_filename_cache_miss_collisions)
1071
+ read_single_number_file(d->bcache_filename_cache_miss_collisions, &cache_miss_collisions);
1072
+
1073
+ if(d->bcache_filename_cache_bypass_hits)
1074
+ read_single_number_file(d->bcache_filename_cache_bypass_hits, &cache_bypass_hits);
1075
+
1076
+ if(d->bcache_filename_cache_bypass_misses)
1077
+ read_single_number_file(d->bcache_filename_cache_bypass_misses, &cache_bypass_misses);
1078
+
1079
+ if(d->bcache_filename_cache_readaheads)
1080
+ read_single_number_file(d->bcache_filename_cache_readaheads, &cache_readaheads);
1081
+
1082
+
1083
+ // update the charts
1084
+
1085
+ {
1086
+ if(unlikely(!d->st_bcache_size)) {
1087
+ d->st_bcache_size = rrdset_create_localhost(
1088
+ "disk_bcache_size"
1089
+ , d->device
1090
+ , d->disk
1091
+ , family
1092
+ , "disk.bcache_size"
1093
+ , "Block Cache Sizes"
1094
+ , "MB"
1095
+ , "proc"
1096
+ , "diskstats"
1097
+ , 2120
1098
+ , update_every
1099
+ , RRDSET_TYPE_AREA
1100
+ );
1101
+
1102
+ d->rd_bcache_dirty_size = rrddim_add(d->st_bcache_size, "dirty", NULL, 1, 1024 * 1024, RRD_ALGORITHM_ABSOLUTE);
1103
+ }
1104
+ else rrdset_next(d->st_bcache_size);
1105
+
1106
+ rrddim_set_by_pointer(d->st_bcache_size, d->rd_bcache_dirty_size, dirty_size);
1107
+ rrdset_done(d->st_bcache_size);
1108
+ }
1109
+
1110
+ {
1111
+ if(unlikely(!d->st_bcache_usage)) {
1112
+ d->st_bcache_usage = rrdset_create_localhost(
1113
+ "disk_bcache_usage"
1114
+ , d->device
1115
+ , d->disk
1116
+ , family
1117
+ , "disk.bcache_usage"
1118
+ , "Block Cache Usage"
1119
+ , "percent"
1120
+ , "proc"
1121
+ , "diskstats"
1122
+ , 2121
1123
+ , update_every
1124
+ , RRDSET_TYPE_AREA
1125
+ );
1126
+
1127
+ d->rd_bcache_available_percent = rrddim_add(d->st_bcache_usage, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1128
+ }
1129
+ else rrdset_next(d->st_bcache_usage);
1130
+
1131
+ rrddim_set_by_pointer(d->st_bcache_usage, d->rd_bcache_available_percent, cache_available_percent);
1132
+ rrdset_done(d->st_bcache_usage);
1133
+ }
1134
+
1135
+ if(d->do_bcache == CONFIG_BOOLEAN_YES || (d->do_bcache == CONFIG_BOOLEAN_AUTO && (cache_hits != 0 || cache_misses != 0 || cache_miss_collisions != 0))) {
1136
+
1137
+ cache_misses -= cache_miss_collisions;
1138
+
1139
+ if(unlikely(!d->st_bcache)) {
1140
+ d->st_bcache = rrdset_create_localhost(
1141
+ "disk_bcache"
1142
+ , d->device
1143
+ , d->disk
1144
+ , family
1145
+ , "disk.bcache"
1146
+ , "Block Cache I/O"
1147
+ , "operations/s"
1148
+ , "proc"
1149
+ , "diskstats"
1150
+ , 2122
1151
+ , update_every
1152
+ , RRDSET_TYPE_LINE
1153
+ );
1154
+
1155
+ rrdset_flag_set(d->st_bcache, RRDSET_FLAG_DETAIL);
1156
+
1157
+ d->rd_bcache_hits = rrddim_add(d->st_bcache, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1158
+ d->rd_bcache_misses = rrddim_add(d->st_bcache, "misses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1159
+ d->rd_bcache_miss_collisions = rrddim_add(d->st_bcache, "collisions", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1160
+ }
1161
+ else rrdset_next(d->st_bcache);
1162
+
1163
+ rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_hits, cache_hits);
1164
+ rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_misses, cache_misses);
1165
+ rrddim_set_by_pointer(d->st_bcache, d->rd_bcache_miss_collisions, cache_miss_collisions);
1166
+ rrdset_done(d->st_bcache);
1167
+ }
1168
+
1169
+ if(d->do_bcache == CONFIG_BOOLEAN_YES || (d->do_bcache == CONFIG_BOOLEAN_AUTO && (cache_bypass_hits != 0 || cache_bypass_misses != 0))) {
1170
+
1171
+ if(unlikely(!d->st_bcache_bypass)) {
1172
+ d->st_bcache_bypass = rrdset_create_localhost(
1173
+ "disk_bcache_bypass"
1174
+ , d->device
1175
+ , d->disk
1176
+ , family
1177
+ , "disk.bcache_bypass"
1178
+ , "Block Cache Bypass I/O"
1179
+ , "operations/s"
1180
+ , "proc"
1181
+ , "diskstats"
1182
+ , 2123
1183
+ , update_every
1184
+ , RRDSET_TYPE_LINE
1185
+ );
1186
+
1187
+ rrdset_flag_set(d->st_bcache_bypass, RRDSET_FLAG_DETAIL);
1188
+
1189
+ d->rd_bcache_bypass_hits = rrddim_add(d->st_bcache_bypass, "hits", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1190
+ d->rd_bcache_bypass_misses = rrddim_add(d->st_bcache_bypass, "misses", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1191
+ }
1192
+ else rrdset_next(d->st_bcache_bypass);
1193
+
1194
+ rrddim_set_by_pointer(d->st_bcache_bypass, d->rd_bcache_bypass_hits, cache_bypass_hits);
1195
+ rrddim_set_by_pointer(d->st_bcache_bypass, d->rd_bcache_bypass_misses, cache_bypass_misses);
1196
+ rrdset_done(d->st_bcache_bypass);
1197
+ }
1198
+
1199
+ if(d->do_bcache == CONFIG_BOOLEAN_YES || (d->do_bcache == CONFIG_BOOLEAN_AUTO && cache_readaheads != 0)) {
1200
+
1201
+ if(unlikely(!d->st_bcache_readaheads)) {
1202
+ d->st_bcache_readaheads = rrdset_create_localhost(
1203
+ "disk_bcache_readahead"
1204
+ , d->device
1205
+ , d->disk
1206
+ , family
1207
+ , "disk.bcache_readahead"
1208
+ , "Block Cache Readaheads"
1209
+ , "events/s"
1210
+ , "proc"
1211
+ , "diskstats"
1212
+ , 2124
1213
+ , update_every
1214
+ , RRDSET_TYPE_LINE
1215
+ );
1216
+
1217
+ rrdset_flag_set(d->st_bcache_readaheads, RRDSET_FLAG_DETAIL);
1218
+
1219
+ d->rd_bcache_readaheads = rrddim_add(d->st_bcache_readaheads, "readaheads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1220
+ }
1221
+ else rrdset_next(d->st_bcache_readaheads);
1222
+
1223
+ rrddim_set_by_pointer(d->st_bcache_readaheads, d->rd_bcache_readaheads, cache_readaheads);
1224
+ rrdset_done(d->st_bcache_readaheads);
1225
+ }
1226
+ }
1227
}
1228
1229
@@ -973,6 +1279,11 @@ int do_proc_diskstats(int update_every, usec_t dt) {
1279
rrdset_obsolete_and_pointer_null(d->st_qops);
1280
rrdset_obsolete_and_pointer_null(d->st_svctm);
1281
rrdset_obsolete_and_pointer_null(d->st_util);
1282
+ rrdset_obsolete_and_pointer_null(d->st_bcache);
1283
+ rrdset_obsolete_and_pointer_null(d->st_bcache_bypass);
1284
+ rrdset_obsolete_and_pointer_null(d->st_bcache_readaheads);
1285
+ rrdset_obsolete_and_pointer_null(d->st_bcache_size);
1286
+ rrdset_obsolete_and_pointer_null(d->st_bcache_usage);
1287
1288
if(d == disk_root) {
1289
disk_root = d = d->next;
@@ -982,6 +1293,15 @@ int do_proc_diskstats(int update_every, usec_t dt) {
1293
last->next = d = d->next;
1294
}
1295
1296
+ freez(t->bcache_filename_dirty_data);
1297
+ freez(t->bcache_filename_cache_available_percent);
1298
+ freez(t->bcache_filename_cache_hits);
1299
+ freez(t->bcache_filename_cache_misses);
1300
+ freez(t->bcache_filename_cache_miss_collisions);
1301
+ freez(t->bcache_filename_cache_bypass_hits);
1302
+ freez(t->bcache_filename_cache_bypass_misses);
1303
+ freez(t->bcache_filename_cache_readaheads);
1304
+
1305
freez(t->disk);
1306
freez(t->device);
1307
freez(t->mount_point);