diskstats now lookup /dev/mapper names; fixes #2414
Costa Tsaousis (ktsaou) committed
Jul 6, 2017 at 00:59 UTC
c7ab5c1e546b014840ddff256a7605078e99ce00
1 file changed
+101
-45
src/proc_diskstats.c
+101
-45
@@ -10,7 +10,8 @@
10
#define DELAULT_EXLUDED_DISKS "loop* ram*"
11
12
static struct disk {
13
- char *disk; // the name of the disk (sda, sdb, etc)
13
+ char *disk; // the name of the disk (sda, sdb, etc, after being looked up)
14
+ char *device; // the device of the disk (before being looked up)
15
unsigned long major;
16
unsigned long minor;
17
int sector_size;
@@ -46,10 +47,63 @@ static struct disk {
47
48
#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_is_obsolete(st); st = NULL; } } while(st)
49
50
+static char *path_to_get_hw_sector_size = NULL;
51
+static char *path_to_get_hw_sector_size_partitions = NULL;
52
+static char *path_to_find_block_device = NULL;
53
+static char *path_to_device_mapper = NULL;
54
+
55
+static inline char *get_disk_name(unsigned long major, unsigned long minor, char *disk) {
56
+ (void)minor;
57
+
58
+ static int enabled = 1;
59
+
60
+ // we can find names only for device mapper (253)
61
+ if(!enabled || major != 253) goto cleanup;
62
+
63
+ char filename[FILENAME_MAX + 1];
64
+ char link[FILENAME_MAX + 1];
65
+
66
+ DIR *dir = opendir(path_to_device_mapper);
67
+ if (!dir) {
68
+ error("Cannot open directory '%s'.", path_to_device_mapper);
69
+ enabled = 0;
70
+ goto cleanup;
71
+ }
72
+
73
+ ssize_t dlen = strlen(disk);
74
+ struct dirent *de = NULL;
75
+ while ((de = readdir(dir))) {
76
+
77
+ if((de->d_type == DT_LNK)) {
78
+ snprintfz(filename, FILENAME_MAX, "%s/%s", path_to_device_mapper, de->d_name);
79
+ ssize_t len = readlink(filename, link, FILENAME_MAX);
80
+
81
+ if(len > 0) {
82
+ link[len] = '\0';
83
+
84
+ if(len > dlen && link[len-dlen-1] == '/' && !strcmp(&link[len - dlen], disk)) {
85
+ // we have a match
86
+ // info("Disk '%s': filename '%s' ('%s') is linked to '%s'. MATCHED", disk, filename, de->d_name, link);
87
+ strncpy(link, de->d_name, FILENAME_MAX);
88
+ netdata_fix_chart_id(link);
89
+ closedir(dir);
90
+
91
+ return strdupz(link);
92
+ }
93
+ //else
94
+ // info("Disk '%s': filename '%s' ('%s') is linked to '%s'. NOT MATCHED", disk, filename, de->d_name, link);
95
+ }
96
+ //else
97
+ // error("Cannot read link '%s'", filename);
98
+ }
99
+ }
100
+ closedir(dir);
101
+
102
+cleanup:
103
+ return strdupz(disk);
104
+}
105
+
106
static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) {
50
- static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
51
- static char path_to_get_hw_sector_size_partitions[FILENAME_MAX + 1] = "";
52
- static char path_find_block_device[FILENAME_MAX + 1] = "";
107
static struct mountinfo *disk_mountinfo_root = NULL;
108
109
struct disk *d;
@@ -66,7 +120,8 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
120
// create a new disk structure
121
d = (struct disk *)callocz(1, sizeof(struct disk));
122
69
- d->disk = strdupz(disk);
123
+ d->disk = get_disk_name(major, minor, disk);
124
+ d->device = strdupz(disk);
125
d->major = major;
126
d->minor = minor;
127
d->type = DISK_TYPE_PHYSICAL; // Default type. Changed later if not correct.
@@ -89,21 +144,30 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
144
char buffer[FILENAME_MAX + 1];
145
146
// get the default path for finding info about the block device
92
- if(unlikely(!path_find_block_device[0])) {
147
+ if(unlikely(!path_to_find_block_device)) {
148
snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s");
94
- snprintfz(path_find_block_device, FILENAME_MAX, "%s", config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer));
149
+ path_to_find_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer);
150
+
151
+ snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
152
+ path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer);
153
+
154
+ snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
155
+ path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer);
156
+
157
+ snprintfz(buffer, FILENAME_MAX, "%s/dev/mapper", netdata_configured_host_prefix);
158
+ path_to_device_mapper = config_get(CONFIG_SECTION_DISKSTATS, "path to device mapper", buffer);
159
}
160
161
// find if it is a partition
162
// by checking if /sys/dev/block/MAJOR:MINOR/partition is readable.
99
- snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "partition");
163
+ snprintfz(buffer, FILENAME_MAX, path_to_find_block_device, major, minor, "partition");
164
if(likely(access(buffer, R_OK) == 0)) {
165
d->type = DISK_TYPE_PARTITION;
166
}
167
else {
168
// find if it is a container
169
// by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries
106
- snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "slaves/");
170
+ snprintfz(buffer, FILENAME_MAX, path_to_find_block_device, major, minor, "slaves/");
171
DIR *dirp = opendir(buffer);
172
if(likely(dirp != NULL)) {
173
struct dirent *dp;
@@ -143,18 +207,9 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
207
// ------------------------------------------------------------------------
208
// find the disk sector size
209
146
- if(unlikely(!path_to_get_hw_sector_size[0])) {
147
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
148
- snprintfz(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer));
149
- }
150
- if(unlikely(!path_to_get_hw_sector_size_partitions[0])) {
151
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
152
- snprintfz(path_to_get_hw_sector_size_partitions, FILENAME_MAX, "%s", config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer));
153
- }
154
-
210
{
211
char tf[FILENAME_MAX + 1], *t;
157
- strncpyz(tf, d->disk, FILENAME_MAX);
212
+ strncpyz(tf, d->device, FILENAME_MAX);
213
214
// replace all / with !
215
for(t = tf; *t ;t++)
@@ -173,15 +228,15 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
228
if(likely(tmp)) {
229
d->sector_size = str2i(tmp);
230
if(unlikely(d->sector_size <= 0)) {
176
- error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->disk, buffer);
231
+ error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->device, buffer);
232
d->sector_size = 512;
233
}
234
}
180
- else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->disk, buffer);
235
+ else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->device, buffer);
236
237
fclose(fpss);
238
}
184
- else error("Cannot read sector size for device %s from %s. Assuming 512.", d->disk, buffer);
239
+ else error("Cannot read sector size for device %s from %s. Assuming 512.", d->device, buffer);
240
}
241
242
return d;
@@ -339,7 +394,7 @@ int do_proc_diskstats(int update_every, usec_t dt) {
394
// Set its family based on mount point
395
396
char *family = d->mount_point;
342
- if(!family) family = disk;
397
+ if(!family) family = d->disk;
398
399
400
// --------------------------------------------------------------------------
@@ -359,11 +414,11 @@ int do_proc_diskstats(int update_every, usec_t dt) {
414
415
int def_enable = global_enable_new_disks_detected_at_runtime;
416
362
- if(def_enable != CONFIG_BOOLEAN_NO && simple_pattern_matches(excluded_disks, disk))
417
+ if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk)))
418
def_enable = CONFIG_BOOLEAN_NO;
419
420
char var_name[4096 + 1];
366
- snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
421
+ snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", d->disk);
422
423
def_enable = config_get_boolean_ondemand(var_name, "enable", def_enable);
424
if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) {
@@ -449,8 +504,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
504
if(unlikely(!d->st_io)) {
505
d->st_io = rrdset_create_localhost(
506
RRD_TYPE_DISK
452
- , disk
453
- , NULL
507
+ , d->device
508
+ , d->disk
509
, family
510
, "disk.io"
511
, "Disk I/O Bandwidth"
@@ -478,8 +533,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
533
if(unlikely(!d->st_ops)) {
534
d->st_ops = rrdset_create_localhost(
535
"disk_ops"
481
- , disk
482
- , NULL
536
+ , d->device
537
+ , d->disk
538
, family
539
, "disk.ops"
540
, "Disk Completed I/O Operations"
@@ -509,8 +564,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
564
if(unlikely(!d->st_qops)) {
565
d->st_qops = rrdset_create_localhost(
566
"disk_qops"
512
- , disk
513
- , NULL
567
+ , d->device
568
+ , d->disk
569
, family
570
, "disk.qops"
571
, "Disk Current I/O Operations"
@@ -538,8 +593,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
593
if(unlikely(!d->st_backlog)) {
594
d->st_backlog = rrdset_create_localhost(
595
"disk_backlog"
541
- , disk
542
- , NULL
596
+ , d->device
597
+ , d->disk
598
, family
599
, "disk.backlog"
600
, "Disk Backlog"
@@ -567,8 +622,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
622
if(unlikely(!d->st_util)) {
623
d->st_util = rrdset_create_localhost(
624
"disk_util"
570
- , disk
571
- , NULL
625
+ , d->device
626
+ , d->disk
627
, family
628
, "disk.util"
629
, "Disk Utilization Time"
@@ -596,8 +651,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
651
if(unlikely(!d->st_mops)) {
652
d->st_mops = rrdset_create_localhost(
653
"disk_mops"
599
- , disk
600
- , NULL
654
+ , d->device
655
+ , d->disk
656
, family
657
, "disk.mops"
658
, "Disk Merged Operations"
@@ -627,8 +682,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
682
if(unlikely(!d->st_iotime)) {
683
d->st_iotime = rrdset_create_localhost(
684
"disk_iotime"
630
- , disk
631
- , NULL
685
+ , d->device
686
+ , d->disk
687
, family
688
, "disk.iotime"
689
, "Disk Total I/O Time"
@@ -661,8 +716,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
716
if(unlikely(!d->st_await)) {
717
d->st_await = rrdset_create_localhost(
718
"disk_await"
664
- , disk
665
- , NULL
719
+ , d->device
720
+ , d->disk
721
, family
722
, "disk.await"
723
, "Average Completed I/O Operation Time"
@@ -690,8 +745,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
745
if(unlikely(!d->st_avgsz)) {
746
d->st_avgsz = rrdset_create_localhost(
747
"disk_avgsz"
693
- , disk
694
- , NULL
748
+ , d->device
749
+ , d->disk
750
, family
751
, "disk.avgsz"
752
, "Average Completed I/O Operation Bandwidth"
@@ -719,8 +774,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
774
if(unlikely(!d->st_svctm)) {
775
d->st_svctm = rrdset_create_localhost(
776
"disk_svctm"
722
- , disk
723
- , NULL
777
+ , d->device
778
+ , d->disk
779
, family
780
, "disk.svctm"
781
, "Average Service Time"
@@ -769,6 +824,7 @@ int do_proc_diskstats(int update_every, usec_t dt) {
824
}
825
826
freez(t->disk);
827
+ freez(t->device);
828
freez(t->mount_point);
829
freez(t);
830
}