@cryptotaxi247 / netdata-1 / commits / c7ab5c1e5

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 }