@cryptotaxi247 / netdata-1 / commits / af20533fb

diskstats: Change default behaviour

Display statistics for physical disks and mounted disks by default. Prevent alloc/free statvfs on each iteration. Minor perormance and readability changes.

Simon Nagl committed May 1, 2016 at 15:57 UTC af20533fbaac680e74205d7d1e6a7918c7eb2873
1 file changed +76 -62
src/proc_diskstats.c
+76 -62
@@ -1,13 +1,15 @@
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 +#include <dirent.h>
5 +#include <fcntl.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
7 -#include <sys/types.h>
8 -#include <sys/stat.h>
9 #include <sys/statvfs.h>
10 -#include <fcntl.h>
10 +#include <sys/types.h>
11 +#include <unistd.h>
12 +
13
14 #include "common.h"
15 #include "log.h"
@@ -20,17 +22,20 @@
22
23 #define RRD_TYPE_DISK "disk"
24
25 +#define DISK_TYPE_PHYSICAL 1
26 +#define DISK_TYPE_PARTITION 2
27 +#define DISK_TYPE_CONTAINER 3
28 +
29 struct disk {
30 unsigned long major;
31 unsigned long minor;
26 - int partition_id; // -1 = this is not a partition
32 + int type;
33 char *mount_point;
28 - char *family;
34 struct disk *next;
35 } *disk_root = NULL;
36
37 struct disk *get_disk(unsigned long major, unsigned long minor) {
33 - static char path_find_block_device_partition[FILENAME_MAX + 1] = "";
38 + static char path_find_block_device[FILENAME_MAX + 1] = "";
39 static struct mountinfo *mountinfo_root = NULL;
40 struct disk *d;
41
@@ -46,10 +51,10 @@ struct disk *get_disk(unsigned long major, unsigned long minor) {
51 if(likely(d))
52 return d;
53
49 - if(unlikely(!path_find_block_device_partition[0])) {
50 - char filename[FILENAME_MAX + 1];
51 - snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/partition");
52 - snprintfz(path_find_block_device_partition, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device partition", filename));
54 + if(unlikely(!path_find_block_device[0])) {
55 + char dirname[FILENAME_MAX + 1];
56 + snprintfz(dirname, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/%s");
57 + snprintfz(path_find_block_device, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device infos", dirname));
58 }
59
60 // not found
@@ -59,7 +64,7 @@ struct disk *get_disk(unsigned long major, unsigned long minor) {
64
65 d->major = major;
66 d->minor = minor;
62 - d->partition_id = -1;
67 + d->type = DISK_TYPE_PHYSICAL; // Default type. Changed later if not correct.
68 d->next = NULL;
69
70 // append it to the list
@@ -71,21 +76,36 @@ struct disk *get_disk(unsigned long major, unsigned long minor) {
76 last->next = d;
77 }
78
79 + // ------------------------------------------------------------------------
80 + // find the type of the device
81 +
82 // find if it is a partition
75 - // by reading /sys/dev/block/MAJOR:MINOR/partition
83 + // by checking if /sys/dev/block/MAJOR:MINOR/partition is readable.
84 char buffer[FILENAME_MAX + 1];
77 - snprintfz(buffer, FILENAME_MAX, path_find_block_device_partition, major, minor);
78 -
79 - int fd = open(buffer, O_RDONLY, 0666);
80 - if(likely(fd != -1)) {
81 - // we opened it
82 - int bytes = read(fd, buffer, FILENAME_MAX);
83 - close(fd);
84 -
85 - if(bytes > 0)
86 - d->partition_id = strtoul(buffer, NULL, 10);
85 + snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "partition");
86 + if(access(buffer, R_OK) == 0) {
87 + d->type = DISK_TYPE_PARTITION;
88 + } else {
89 + // find if it is a container
90 + // by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries
91 + int is_container = 0;
92 + snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "slaves/");
93 + DIR *dirp = opendir(buffer);
94 + if (dirp != NULL) {
95 + struct dirent *dp;
96 + while(dp = readdir(dirp)) {
97 + // . and .. are also files in empty folders.
98 + if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) {
99 + continue;
100 + }
101 + d->type = DISK_TYPE_CONTAINER;
102 + // Stop the loop after we found one file.
103 + break;
104 + }
105 + if(closedir(dirp) == -1)
106 + error("Unable to close dir %s", buffer);
107 + }
108 }
88 - // if the /partition file does not exist, it is a disk, not a partition
109
110 // ------------------------------------------------------------------------
111 // check if we can find its mount point
@@ -117,6 +137,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
137 static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
138 static int enable_new_disks = -1;
139 static int do_io = -1, do_ops = -1, do_mops = -1, do_iotime = -1, do_qops = -1, do_util = -1, do_backlog = -1, do_space = -1;
140 + static struct statvfs buff_statvfs;
141
142 if(enable_new_disks == -1) enable_new_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
143
@@ -145,12 +166,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
166 ff = procfile_readall(ff);
167 if(!ff) return 0; // we return 0, so that we will retry to open it next time
168
148 - struct statvfs * buff_statvfs;
149 - if ( !(buff_statvfs = (struct statvfs *)
150 - malloc(sizeof(struct statvfs)))) {
151 - error("Failed to allocate memory to buffer.");
152 - }
153 -
169 uint32_t lines = procfile_lines(ff), l;
170 uint32_t words;
171
@@ -221,16 +236,17 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
236
237 struct disk *d = get_disk(major, minor);
238
224 - /*
225 - if(d->partition_id == -1)
239 + // Enable statistics for physical disks and mount points by default.
240 + if( (d->type == DISK_TYPE_PHYSICAL) || (d->mount_point != NULL) ) {
241 def_enabled = enable_new_disks;
227 - else
228 - def_enabled = 0;
229 - */
242 + }
243
231 - // Enable real disks by default.
244 + /*
245 + // Enable physical disks by default.
246 // To fine out if it is a harddrive we use
247 // Linux Assigned Names and Numbers Authority (http://www.lanana.org/)
248 + // We can't do that because proprietary disk drivers do not stick to
249 + // the standard. To detect re
250 switch(major) {
251 case 8: // SCSI disk devices (0-15)
252 if(!(minor % 16)) {
@@ -461,6 +477,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
477 def_enabled = 0;
478 break;
479 }
480 + */
481
482 char *mount_point = d->mount_point;
483 char *family = d->mount_point;
@@ -651,35 +668,33 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
668 // --------------------------------------------------------------------
669
670 if(ddo_space) {
654 - if(mount_point) {
655 - st = rrdset_find_bytype("disk_space", disk);
656 - if(!st) {
657 - st = rrdset_create("disk_space", disk, NULL, family, "disk.space", "Disk Space Usage", "Megabyte", 2023, update_every, RRDSET_TYPE_AREA);
658 - st->isdetail = 1;
659 -
660 - rrddim_add(st, "avail", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
661 - rrddim_add(st, "reserved for root", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
662 - rrddim_add(st, "used" , NULL, 1, 1045576, RRDDIM_ABSOLUTE);
671 + if(!mount_point) {
672 + if(ddo_space != CONFIG_ONDEMAND_ONDEMAND) {
673 + error("Cannot find space usage for disk %s. It does not have a mount point.", family);
674 }
664 - else rrdset_next_usec(st, dt);
665 -
666 -
667 -
668 - if (statvfs(family, buff_statvfs) < 0) {
669 - error("Faild checking disk space usage of %s", family);
675 + } else {
676 + if (statvfs(family, &buff_statvfs) < 0) {
677 + error("Failed checking disk space usage of %s", family);
678 } else {
671 - space_avail = buff_statvfs->f_bavail * buff_statvfs->f_bsize;
672 - space_avail_root = (buff_statvfs->f_bfree - buff_statvfs->f_bavail) * buff_statvfs->f_bsize;
673 - space_used = (buff_statvfs->f_blocks - buff_statvfs->f_bfree) * buff_statvfs->f_bsize;
674 - }
679 + space_avail = buff_statvfs.f_bavail * buff_statvfs.f_bsize;
680 + space_avail_root = (buff_statvfs.f_bfree - buff_statvfs.f_bavail) * buff_statvfs.f_bsize;
681 + space_used = (buff_statvfs.f_blocks - buff_statvfs.f_bfree) * buff_statvfs.f_bsize;
682 +
683 + st = rrdset_find_bytype("disk_space", disk);
684 + if(!st) {
685 + st = rrdset_create("disk_space", disk, NULL, family, "disk.space", "Disk Space Usage", "GB", 2023, update_every, RRDSET_TYPE_STACKED);
686 + st->isdetail = 1;
687 +
688 + rrddim_add(st, "avail", NULL, 1, 1000*1000*1000, RRDDIM_ABSOLUTE);
689 + rrddim_add(st, "reserved_for_root", "reserved for root", 1, 1000*1000*1000, RRDDIM_ABSOLUTE);
690 + rrddim_add(st, "used" , NULL, 1, 1000*1000*1000, RRDDIM_ABSOLUTE);
691 + }
692 + else rrdset_next_usec(st, dt);
693
676 - rrddim_set(st, "avail", space_avail);
677 - rrddim_set(st, "reserved for root", space_avail_root);
678 - rrddim_set(st, "used", space_used);
679 - rrdset_done(st);
680 - } else {
681 - if(ddo_space != CONFIG_ONDEMAND_ONDEMAND) {
682 - error("Cannot find space usage for disk %s. It does not have a mount point.", family);
694 + rrddim_set(st, "avail", space_avail);
695 + rrddim_set(st, "reserved_for_root", space_avail_root);
696 + rrddim_set(st, "used", space_used);
697 + rrdset_done(st);
698 }
699 }
700 }
@@ -736,7 +751,6 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
751 }
752 }
753 }
739 - free(buff_statvfs);
754
755 return 0;
756 }