11 #include "plugin_proc.h"
13 #define RRD_TYPE_DISK "disk"
14 #define RRD_TYPE_DISK_LEN strlen(RRD_TYPE_DISK)
16 #define MAX_PROC_DISKSTATS_LINE 4096
18 int do_proc_diskstats(int update_every, unsigned long long dt) {
19 static procfile *ff = NULL;
20 static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
21 static int enable_new_disks = -1;
22 static int do_io = -1, do_ops = -1, do_merged_ops = -1, do_iotime = -1, do_cur_ops = -1;
24 if(enable_new_disks == -1) enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
26 if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
27 if(do_ops == -1) do_ops = config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
28 if(do_merged_ops == -1) do_merged_ops = config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
29 if(do_iotime == -1) do_iotime = config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
30 if(do_cur_ops == -1) do_cur_ops = config_get_boolean("plugin:proc:/proc/diskstats", "current operations for all disks", 1);
35 char filename[FILENAME_MAX + 1];
36 snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/diskstats");
37 ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
41 if(!path_to_get_hw_sector_size[0]) {
42 char filename[FILENAME_MAX + 1];
43 snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
44 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));
47 ff = procfile_readall(ff);
48 if(!ff) return 0; // we return 0, so that we will retry to open it next time
50 uint32_t lines = procfile_lines(ff), l;
53 for(l = 0; l < lines ;l++) {
55 unsigned long long major = 0, minor = 0,
56 reads = 0, reads_merged = 0, readsectors = 0, readms = 0,
57 writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
58 currentios = 0, iosms = 0, wiosms = 0;
60 words = procfile_linewords(ff, l);
61 if(words < 14) continue;
63 major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
64 minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
65 disk = procfile_lineword(ff, l, 2);
66 reads = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
67 reads_merged = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
68 readsectors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
69 readms = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
70 writes = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
71 writes_merged = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
72 writesectors = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
73 writems = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
74 currentios = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
75 iosms = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
76 wiosms = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
80 // remove slashes from disk names
82 for(s = disk; *s ;s++) if(*s == '/') *s = '_';
86 case 43: // network block
93 def_enabled = enable_new_disks;
115 if(minor % 8) def_enabled = 0; // partitions
116 else def_enabled = enable_new_disks;
119 case 8: // scsi disks
120 case 65: // scsi disks
121 case 66: // scsi disks
122 case 67: // scsi disks
123 case 68: // scsi disks
124 case 69: // scsi disks
125 case 70: // scsi disks
126 case 71: // scsi disks
127 case 72: // scsi disks
128 case 73: // scsi disks
129 case 74: // scsi disks
130 case 75: // scsi disks
131 case 76: // scsi disks
132 case 77: // scsi disks
133 case 78: // scsi disks
134 case 79: // scsi disks
143 case 101: // hyperdisk
144 case 102: // compressed
153 case 114: // bios raid
154 case 116: // ram board
167 if(minor % 16) def_enabled = 0; // partitions
168 else def_enabled = enable_new_disks;
173 if(minor % 32) def_enabled = 0; // partitions
174 else def_enabled = enable_new_disks;
188 if(minor % 64) def_enabled = 0; // partitions
189 else def_enabled = enable_new_disks;
197 // check if it is enabled
199 char var_name[4096 + 1];
200 snprintf(var_name, 4096, "disk %s", disk);
201 if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
206 // --------------------------------------------------------------------
209 st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
211 char tf[FILENAME_MAX + 1], *t;
212 char ssfilename[FILENAME_MAX + 1];
213 int sector_size = 512;
215 strncpy(tf, disk, FILENAME_MAX);
216 tf[FILENAME_MAX] = '\0';
218 // replace all / with !
219 while((t = strchr(tf, '/'))) *t = '!';
221 snprintf(ssfilename, FILENAME_MAX, path_to_get_hw_sector_size, tf);
222 FILE *fpss = fopen(ssfilename, "r");
225 char *tmp = fgets(ssbuffer, 1024, fpss);
228 sector_size = atoi(tmp);
229 if(sector_size <= 0) {
230 error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
234 else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
238 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
240 st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
242 rrddim_add(st, "reads", NULL, sector_size, 1024 * update_every, RRDDIM_INCREMENTAL);
243 rrddim_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRDDIM_INCREMENTAL);
245 else rrdset_next(st);
247 rrddim_set(st, "reads", readsectors);
248 rrddim_set(st, "writes", writesectors);
252 // --------------------------------------------------------------------
255 st = rrdset_find_bytype("disk_ops", disk);
257 st = rrdset_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
260 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
261 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
263 else rrdset_next(st);
265 rrddim_set(st, "reads", reads);
266 rrddim_set(st, "writes", writes);
270 // --------------------------------------------------------------------
273 st = rrdset_find_bytype("disk_merged_ops", disk);
275 st = rrdset_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, RRDSET_TYPE_LINE);
278 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
279 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
281 else rrdset_next(st);
283 rrddim_set(st, "reads", reads_merged);
284 rrddim_set(st, "writes", writes_merged);
288 // --------------------------------------------------------------------
291 st = rrdset_find_bytype("disk_iotime", disk);
293 st = rrdset_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, RRDSET_TYPE_LINE);
296 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
297 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
298 rrddim_add(st, "latency", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
299 rrddim_add(st, "weighted", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
301 else rrdset_next(st);
303 rrddim_set(st, "reads", readms);
304 rrddim_set(st, "writes", writems);
305 rrddim_set(st, "latency", iosms);
306 rrddim_set(st, "weighted", wiosms);
310 // --------------------------------------------------------------------
313 st = rrdset_find_bytype("disk_cur_ops", disk);
315 st = rrdset_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, RRDSET_TYPE_LINE);
318 rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
320 else rrdset_next(st);
322 rrddim_set(st, "operations", currentios);