@cryptotaxi247 / netdata-1 / commits / acdf32e65

auto-detection of partitions based on /sys/dev/block/MAJOR:MINOR/partition #259, #258

Costa Tsaousis (ktsaou) committed Apr 20, 2016 at 02:54 UTC acdf32e652fac961e571d494376be06f0d9db1f0
1 file changed +80 -2
src/proc_diskstats.c
+80 -2
@@ -4,6 +4,9 @@
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 +#include <sys/types.h>
8 +#include <sys/stat.h>
9 +#include <fcntl.h>
10
11 #include "common.h"
12 #include "log.h"
@@ -14,6 +17,73 @@
17
18 #define RRD_TYPE_DISK "disk"
19
20 +struct disk {
21 + unsigned long major;
22 + unsigned long minor;
23 + int partition_id; // -1 = this is not a partition
24 + struct disk *next;
25 +} *disk_root = NULL;
26 +
27 +struct disk *get_disk(unsigned long major, unsigned long minor) {
28 + static char path_find_block_device_partition[FILENAME_MAX + 1] = "";
29 + struct disk *d;
30 +
31 + // search for it in our RAM list.
32 + // this is sequential, but since we just walk through
33 + // and the number of disks / partitions in a system
34 + // should not be that many, it should be acceptable
35 + for(d = disk_root; d ; d = d->next)
36 + if(unlikely(d->major == major && d->minor == minor))
37 + break;
38 +
39 + // if we found it, return it
40 + if(likely(d))
41 + return d;
42 +
43 + if(unlikely(!path_find_block_device_partition[0])) {
44 + char filename[FILENAME_MAX + 1];
45 + snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/dev/block/%lu:%lu/partition");
46 + snprintf(path_find_block_device_partition, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get block device partition", filename));
47 + }
48 +
49 + // not found
50 + // create a new disk structure
51 + d = (struct disk *)malloc(sizeof(struct disk));
52 + if(!d) fatal("Cannot allocate memory for struct disk in proc_diskstats.");
53 +
54 + d->major = major;
55 + d->minor = minor;
56 + d->partition_id = -1;
57 + d->next = NULL;
58 +
59 + // append it to the list
60 + if(!disk_root)
61 + disk_root = d;
62 + else {
63 + struct disk *last;
64 + for(last = disk_root; last->next ;last = last->next);
65 + last->next = d;
66 + }
67 +
68 + // find if it is a partition
69 + // by reading /sys/dev/block/MAJOR:MINOR/partition
70 + char buffer[FILENAME_MAX + 1];
71 + snprintf(buffer, FILENAME_MAX, path_find_block_device_partition, major, minor);
72 +
73 + int fd = open(buffer, O_RDONLY, 0666);
74 + if(likely(fd != -1)) {
75 + // we opened it
76 + int bytes = read(fd, buffer, FILENAME_MAX);
77 + close(fd);
78 +
79 + if(bytes > 0)
80 + d->partition_id = strtoul(buffer, NULL, 10);
81 + }
82 + // if the /partition file does not exist, it is a disk, not a partition
83 +
84 + return d;
85 +}
86 +
87 int do_proc_diskstats(int update_every, unsigned long long dt) {
88 static procfile *ff = NULL;
89 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) {
110 if(!path_to_get_hw_sector_size[0]) {
111 char filename[FILENAME_MAX + 1];
112 snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
43 - 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));
113 + snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s", config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
114 }
115
116 ff = procfile_readall(ff);
@@ -107,13 +177,19 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
177 // I/O completion time and the backlog that may be accumulating.
178 backlog_ms = strtoull(procfile_lineword(ff, l, 13), NULL, 10); // rq_ticks
179
110 -
180 int def_enabled = 0;
181
182 // remove slashes from disk names
183 char *s;
184 for(s = disk; *s ;s++) if(*s == '/') *s = '_';
185
186 + struct disk *d = get_disk(major, minor);
187 + if(d->partition_id == -1)
188 + def_enabled = enable_new_disks;
189 + else
190 + def_enabled = 0;
191 +
192 +/*
193 switch(major) {
194 case 9: // MDs
195 case 43: // network block
@@ -196,6 +272,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
272 case 135: // scsi
273 case 153: // raid
274 case 202: // xen
275 + case 254: // virtio3
276 case 256: // flash
277 case 257: // flash
278 case 259: // nvme0n1 issue #119
@@ -232,6 +309,7 @@ int do_proc_diskstats(int update_every, unsigned long long dt) {
309 def_enabled = 0;
310 break;
311 }
312 +*/
313
314 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;
315