summaryrefslogtreecommitdiffstats
path: root/src/proc_diskstats.c
diff options
context:
space:
mode:
authorLennart Weller <lhw@ring0.de>2017-07-27 09:55:47 +0000
committerLennart Weller <lhw@ring0.de>2017-07-27 09:55:47 +0000
commita133c9c3b637b1dbe7b5b053f7e2572c1950cead (patch)
tree2207939a88e96bca329457f40a9d9d18ab659dc1 /src/proc_diskstats.c
parentNew upstream version 1.6.0+dfsg (diff)
downloadnetdata-a133c9c3b637b1dbe7b5b053f7e2572c1950cead.tar.xz
netdata-a133c9c3b637b1dbe7b5b053f7e2572c1950cead.zip
New upstream version 1.7.0+dfsgupstream/1.7.0+dfsg
Diffstat (limited to 'src/proc_diskstats.c')
-rw-r--r--src/proc_diskstats.c173
1 files changed, 117 insertions, 56 deletions
diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c
index a1b4072d..d3fed5a6 100644
--- a/src/proc_diskstats.c
+++ b/src/proc_diskstats.c
@@ -10,7 +10,8 @@
#define DELAULT_EXLUDED_DISKS "loop* ram*"
static struct disk {
- char *disk; // the name of the disk (sda, sdb, etc)
+ char *disk; // the name of the disk (sda, sdb, etc, after being looked up)
+ char *device; // the device of the disk (before being looked up)
unsigned long major;
unsigned long minor;
int sector_size;
@@ -44,12 +45,75 @@ static struct disk {
struct disk *next;
} *disk_root = NULL;
-#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_flag_set(st, RRDSET_FLAG_OBSOLETE); st = NULL; } } while(st)
+#define rrdset_obsolete_and_pointer_null(st) do { if(st) { rrdset_is_obsolete(st); st = NULL; } } while(st)
+
+static char *path_to_get_hw_sector_size = NULL;
+static char *path_to_get_hw_sector_size_partitions = NULL;
+static char *path_to_find_block_device = NULL;
+static char *path_to_device_mapper = NULL;
+
+static inline char *get_disk_name(unsigned long major, unsigned long minor, char *disk) {
+ static int enabled = 1;
+
+ if(!enabled) goto cleanup;
+
+ char filename[FILENAME_MAX + 1];
+ char link[FILENAME_MAX + 1];
+
+ DIR *dir = opendir(path_to_device_mapper);
+ if (!dir) {
+ error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot open directory '%s'. Disabling device-mapper support.", disk, major, minor, path_to_device_mapper);
+ enabled = 0;
+ goto cleanup;
+ }
+
+ struct dirent *de = NULL;
+ while ((de = readdir(dir))) {
+ if(de->d_type != DT_LNK) continue;
+
+ snprintfz(filename, FILENAME_MAX, "%s/%s", path_to_device_mapper, de->d_name);
+ ssize_t len = readlink(filename, link, FILENAME_MAX);
+ if(len <= 0) {
+ error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot read link '%s'.", disk, major, minor, filename);
+ continue;
+ }
+
+ link[len] = '\0';
+ if(link[0] != '/')
+ snprintfz(filename, FILENAME_MAX, "%s/%s", path_to_device_mapper, link);
+ else
+ strncpyz(filename, link, FILENAME_MAX);
+
+ struct stat sb;
+ if(stat(filename, &sb) == -1) {
+ error("DEVICE-MAPPER ('%s', %lu:%lu): Cannot stat() file '%s'.", disk, major, minor, filename);
+ continue;
+ }
+
+ if((sb.st_mode & S_IFMT) != S_IFBLK) {
+ // info("DEVICE-MAPPER ('%s', %lu:%lu): file '%s' is not a block device.", disk, major, minor, filename);
+ continue;
+ }
+
+ if(major(sb.st_rdev) != major || minor(sb.st_rdev) != minor) {
+ // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' does not match %lu:%lu.", disk, major, minor, filename, (unsigned long)major(sb.st_rdev), (unsigned long)minor(sb.st_rdev));
+ continue;
+ }
+
+ // info("DEVICE-MAPPER ('%s', %lu:%lu): filename '%s' matches.", disk, major, minor, filename);
+
+ strncpy(link, de->d_name, FILENAME_MAX);
+ netdata_fix_chart_name(link);
+ disk = link;
+ break;
+ }
+ closedir(dir);
+
+cleanup:
+ return strdupz(disk);
+}
static struct disk *get_disk(unsigned long major, unsigned long minor, char *disk) {
- static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
- static char path_to_get_hw_sector_size_partitions[FILENAME_MAX + 1] = "";
- static char path_find_block_device[FILENAME_MAX + 1] = "";
static struct mountinfo *disk_mountinfo_root = NULL;
struct disk *d;
@@ -66,7 +130,8 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
// create a new disk structure
d = (struct disk *)callocz(1, sizeof(struct disk));
- d->disk = strdupz(disk);
+ d->disk = get_disk_name(major, minor, disk);
+ d->device = strdupz(disk);
d->major = major;
d->minor = minor;
d->type = DISK_TYPE_PHYSICAL; // Default type. Changed later if not correct.
@@ -83,27 +148,17 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
last->next = d;
}
- // ------------------------------------------------------------------------
- // find the type of the device
-
- char buffer[FILENAME_MAX + 1];
-
- // get the default path for finding info about the block device
- if(unlikely(!path_find_block_device[0])) {
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s");
- snprintfz(path_find_block_device, FILENAME_MAX, "%s", config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer));
- }
-
// find if it is a partition
// by checking if /sys/dev/block/MAJOR:MINOR/partition is readable.
- snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "partition");
+ char buffer[FILENAME_MAX + 1];
+ snprintfz(buffer, FILENAME_MAX, path_to_find_block_device, major, minor, "partition");
if(likely(access(buffer, R_OK) == 0)) {
d->type = DISK_TYPE_PARTITION;
}
else {
// find if it is a container
// by checking if /sys/dev/block/MAJOR:MINOR/slaves has entries
- snprintfz(buffer, FILENAME_MAX, path_find_block_device, major, minor, "slaves/");
+ snprintfz(buffer, FILENAME_MAX, path_to_find_block_device, major, minor, "slaves/");
DIR *dirp = opendir(buffer);
if(likely(dirp != NULL)) {
struct dirent *dp;
@@ -143,18 +198,9 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
// ------------------------------------------------------------------------
// find the disk sector size
- if(unlikely(!path_to_get_hw_sector_size[0])) {
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
- snprintfz(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer));
- }
- if(unlikely(!path_to_get_hw_sector_size_partitions[0])) {
- snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
- 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));
- }
-
{
char tf[FILENAME_MAX + 1], *t;
- strncpyz(tf, d->disk, FILENAME_MAX);
+ strncpyz(tf, d->device, FILENAME_MAX);
// replace all / with !
for(t = tf; *t ;t++)
@@ -173,15 +219,15 @@ static struct disk *get_disk(unsigned long major, unsigned long minor, char *dis
if(likely(tmp)) {
d->sector_size = str2i(tmp);
if(unlikely(d->sector_size <= 0)) {
- error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->disk, buffer);
+ error("Invalid sector size %d for device %s in %s. Assuming 512.", d->sector_size, d->device, buffer);
d->sector_size = 512;
}
}
- else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->disk, buffer);
+ else error("Cannot read data for sector size for device %s from %s. Assuming 512.", d->device, buffer);
fclose(fpss);
}
- else error("Cannot read sector size for device %s from %s. Assuming 512.", d->disk, buffer);
+ else error("Cannot read sector size for device %s from %s. Assuming 512.", d->device, buffer);
}
return d;
@@ -230,6 +276,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
globals_initialized = 0;
if(unlikely(!globals_initialized)) {
+ globals_initialized = 1;
+
global_enable_new_disks_detected_at_runtime = config_get_boolean(CONFIG_SECTION_DISKSTATS, "enable new disks detected at runtime", global_enable_new_disks_detected_at_runtime);
global_enable_performance_for_physical_disks = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for physical disks", global_enable_performance_for_physical_disks);
global_enable_performance_for_virtual_disks = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "performance metrics for virtual disks", global_enable_performance_for_virtual_disks);
@@ -243,7 +291,19 @@ int do_proc_diskstats(int update_every, usec_t dt) {
global_do_util = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "utilization percentage for all disks", global_do_util);
global_do_backlog = config_get_boolean_ondemand(CONFIG_SECTION_DISKSTATS, "backlog for all disks", global_do_backlog);
- globals_initialized = 1;
+ char buffer[FILENAME_MAX + 1];
+
+ snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/%s");
+ path_to_find_block_device = config_get(CONFIG_SECTION_DISKSTATS, "path to get block device infos", buffer);
+
+ snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/block/%s/queue/hw_sector_size");
+ path_to_get_hw_sector_size = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size", buffer);
+
+ snprintfz(buffer, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/dev/block/%lu:%lu/subsystem/%s/../queue/hw_sector_size");
+ path_to_get_hw_sector_size_partitions = config_get(CONFIG_SECTION_DISKSTATS, "path to get h/w sector size for partitions", buffer);
+
+ snprintfz(buffer, FILENAME_MAX, "%s/dev/mapper", netdata_configured_host_prefix);
+ path_to_device_mapper = config_get(CONFIG_SECTION_DISKSTATS, "path to device mapper", buffer);
}
// --------------------------------------------------------------------------
@@ -339,7 +399,7 @@ int do_proc_diskstats(int update_every, usec_t dt) {
// Set its family based on mount point
char *family = d->mount_point;
- if(!family) family = disk;
+ if(!family) family = d->disk;
// --------------------------------------------------------------------------
@@ -359,11 +419,11 @@ int do_proc_diskstats(int update_every, usec_t dt) {
int def_enable = global_enable_new_disks_detected_at_runtime;
- if(def_enable != CONFIG_BOOLEAN_NO && simple_pattern_matches(excluded_disks, disk))
+ if(def_enable != CONFIG_BOOLEAN_NO && (simple_pattern_matches(excluded_disks, d->device) || simple_pattern_matches(excluded_disks, d->disk)))
def_enable = CONFIG_BOOLEAN_NO;
char var_name[4096 + 1];
- snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
+ snprintfz(var_name, 4096, "plugin:proc:/proc/diskstats:%s", d->disk);
def_enable = config_get_boolean_ondemand(var_name, "enable", def_enable);
if(unlikely(def_enable == CONFIG_BOOLEAN_NO)) {
@@ -449,8 +509,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_io)) {
d->st_io = rrdset_create_localhost(
RRD_TYPE_DISK
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.io"
, "Disk I/O Bandwidth"
@@ -478,8 +538,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_ops)) {
d->st_ops = rrdset_create_localhost(
"disk_ops"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.ops"
, "Disk Completed I/O Operations"
@@ -509,8 +569,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_qops)) {
d->st_qops = rrdset_create_localhost(
"disk_qops"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.qops"
, "Disk Current I/O Operations"
@@ -538,8 +598,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_backlog)) {
d->st_backlog = rrdset_create_localhost(
"disk_backlog"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.backlog"
, "Disk Backlog"
@@ -567,8 +627,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_util)) {
d->st_util = rrdset_create_localhost(
"disk_util"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.util"
, "Disk Utilization Time"
@@ -596,8 +656,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_mops)) {
d->st_mops = rrdset_create_localhost(
"disk_mops"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.mops"
, "Disk Merged Operations"
@@ -627,8 +687,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_iotime)) {
d->st_iotime = rrdset_create_localhost(
"disk_iotime"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.iotime"
, "Disk Total I/O Time"
@@ -661,8 +721,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_await)) {
d->st_await = rrdset_create_localhost(
"disk_await"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.await"
, "Average Completed I/O Operation Time"
@@ -690,8 +750,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_avgsz)) {
d->st_avgsz = rrdset_create_localhost(
"disk_avgsz"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.avgsz"
, "Average Completed I/O Operation Bandwidth"
@@ -719,8 +779,8 @@ int do_proc_diskstats(int update_every, usec_t dt) {
if(unlikely(!d->st_svctm)) {
d->st_svctm = rrdset_create_localhost(
"disk_svctm"
- , disk
- , NULL
+ , d->device
+ , d->disk
, family
, "disk.svctm"
, "Average Service Time"
@@ -769,6 +829,7 @@ int do_proc_diskstats(int update_every, usec_t dt) {
}
freez(t->disk);
+ freez(t->device);
freez(t->mount_point);
freez(t);
}