summaryrefslogtreecommitdiffstats
path: root/src/proc_diskstats.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/proc_diskstats.c')
-rw-r--r--[-rwxr-xr-x]src/proc_diskstats.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/src/proc_diskstats.c b/src/proc_diskstats.c
index f404118f..c2b84aae 100755..100644
--- a/src/proc_diskstats.c
+++ b/src/proc_diskstats.c
@@ -4,6 +4,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include "common.h"
#include "log.h"
@@ -14,6 +17,73 @@
#define RRD_TYPE_DISK "disk"
+struct disk {
+ unsigned long major;
+ unsigned long minor;
+ int partition_id; // -1 = this is not a partition
+ struct disk *next;
+} *disk_root = NULL;
+
+struct disk *get_disk(unsigned long major, unsigned long minor) {
+ static char path_find_block_device_partition[FILENAME_MAX + 1] = "";
+ struct disk *d;
+
+ // search for it in our RAM list.
+ // this is sequential, but since we just walk through
+ // and the number of disks / partitions in a system
+ // should not be that many, it should be acceptable
+ for(d = disk_root; d ; d = d->next)
+ if(unlikely(d->major == major && d->minor == minor))
+ break;
+
+ // if we found it, return it
+ if(likely(d))
+ return d;
+
+ if(unlikely(!path_find_block_device_partition[0])) {
+ char filename[FILENAME_MAX + 1];
+ snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/partition");
+ snprintf(path_find_block_device_partition, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device partition", filename));
+ }
+
+ // not found
+ // create a new disk structure
+ d = (struct disk *)malloc(sizeof(struct disk));
+ if(!d) fatal("Cannot allocate memory for struct disk in proc_diskstats.");
+
+ d->major = major;
+ d->minor = minor;
+ d->partition_id = -1;
+ d->next = NULL;
+
+ // append it to the list
+ if(!disk_root)
+ disk_root = d;
+ else {
+ struct disk *last;
+ for(last = disk_root; last->next ;last = last->next);
+ last->next = d;
+ }
+
+ // find if it is a partition
+ // by reading /sys/dev/block/MAJOR:MINOR/partition
+ char buffer[FILENAME_MAX + 1];
+ snprintf(buffer, FILENAME_MAX, path_find_block_device_partition, major, minor);
+
+ int fd = open(buffer, O_RDONLY, 0666);
+ if(likely(fd != -1)) {
+ // we opened it
+ int bytes = read(fd, buffer, FILENAME_MAX);
+ close(fd);
+
+ if(bytes > 0)
+ d->partition_id = strtoul(buffer, NULL, 10);
+ }
+ // if the /partition file does not exist, it is a disk, not a partition
+
+ return d;
+}
+
int do_proc_diskstats(int update_every, unsigned long long dt) {
static procfile *ff = NULL;
static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
@@ -40,7 +110,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
if(!path_to_get_hw_sector_size[0]) {
char filename[FILENAME_MAX + 1];
snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
- snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s%s", global_host_prefix, config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
+ snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
}
ff = procfile_readall(ff);
@@ -107,13 +177,19 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
// I/O completion time and the backlog that may be accumulating.
backlog_ms = strtoull(procfile_lineword(ff, l, 13), NULL, 10); // rq_ticks
-
int def_enabled = 0;
// remove slashes from disk names
char *s;
for(s = disk; *s ;s++) if(*s == '/') *s = '_';
+ struct disk *d = get_disk(major, minor);
+ if(d->partition_id == -1)
+ def_enabled = enable_new_disks;
+ else
+ def_enabled = 0;
+
+/*
switch(major) {
case 9: // MDs
case 43: // network block
@@ -123,6 +199,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
case 199: // veritas
case 201: // veritas
case 251: // dm
+ case 253: // virtio
def_enabled = enable_new_disks;
break;
@@ -195,8 +272,10 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
case 135: // scsi
case 153: // raid
case 202: // xen
+ case 254: // virtio3
case 256: // flash
case 257: // flash
+ case 259: // nvme0n1 issue #119
if(minor % 16) def_enabled = 0; // partitions
else def_enabled = enable_new_disks;
break;
@@ -230,6 +309,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
def_enabled = 0;
break;
}
+*/
int ddo_io = do_io, ddo_ops = do_ops, ddo_mops = do_mops, ddo_iotime = do_iotime, ddo_qops = do_qops, ddo_util = do_util, ddo_backlog = do_backlog;