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 = NULL;
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);
34 if(!ff) ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", "/proc/diskstats"), " \t", PROCFILE_FLAG_DEFAULT);
37 if(!path_to_get_hw_sector_size) path_to_get_hw_sector_size = config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", "/sys/block/%s/queue/hw_sector_size");
39 ff = procfile_readall(ff);
40 if(!ff) return 0; // we return 0, so that we will retry to open it next time
42 uint32_t lines = procfile_lines(ff), l;
45 for(l = 0; l < lines ;l++) {
47 unsigned long long major = 0, minor = 0,
48 reads = 0, reads_merged = 0, readsectors = 0, readms = 0,
49 writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
50 currentios = 0, iosms = 0, wiosms = 0;
52 words = procfile_linewords(ff, l);
53 if(words < 14) continue;
55 major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
56 minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
57 disk = procfile_lineword(ff, l, 2);
58 reads = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
59 reads_merged = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
60 readsectors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
61 readms = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
62 writes = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
63 writes_merged = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
64 writesectors = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
65 writems = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
66 currentios = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
67 iosms = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
68 wiosms = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
72 // remove slashes from disk names
74 for(s = disk; *s ;s++) if(*s == '/') *s = '_';
78 case 43: // network block
85 def_enabled = enable_new_disks;
107 if(minor % 8) def_enabled = 0; // partitions
108 else def_enabled = enable_new_disks;
111 case 8: // scsi disks
112 case 65: // scsi disks
113 case 66: // scsi disks
114 case 67: // scsi disks
115 case 68: // scsi disks
116 case 69: // scsi disks
117 case 70: // scsi disks
118 case 71: // scsi disks
119 case 72: // scsi disks
120 case 73: // scsi disks
121 case 74: // scsi disks
122 case 75: // scsi disks
123 case 76: // scsi disks
124 case 77: // scsi disks
125 case 78: // scsi disks
126 case 79: // scsi disks
135 case 101: // hyperdisk
136 case 102: // compressed
145 case 114: // bios raid
146 case 116: // ram board
159 if(minor % 16) def_enabled = 0; // partitions
160 else def_enabled = enable_new_disks;
165 if(minor % 32) def_enabled = 0; // partitions
166 else def_enabled = enable_new_disks;
180 if(minor % 64) def_enabled = 0; // partitions
181 else def_enabled = enable_new_disks;
189 // check if it is enabled
191 char var_name[4096 + 1];
192 snprintf(var_name, 4096, "disk %s", disk);
193 if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
198 // --------------------------------------------------------------------
201 st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
203 char tf[FILENAME_MAX + 1], *t;
204 char ssfilename[FILENAME_MAX + 1];
205 int sector_size = 512;
207 strncpy(tf, disk, FILENAME_MAX);
208 tf[FILENAME_MAX] = '\0';
210 // replace all / with !
211 while((t = strchr(tf, '/'))) *t = '!';
213 snprintf(ssfilename, FILENAME_MAX, path_to_get_hw_sector_size, tf);
214 FILE *fpss = fopen(ssfilename, "r");
217 char *tmp = fgets(ssbuffer, 1024, fpss);
220 sector_size = atoi(tmp);
221 if(sector_size <= 0) {
222 error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
226 else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
230 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
232 st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
234 rrddim_add(st, "reads", NULL, sector_size, 1024 * update_every, RRDDIM_INCREMENTAL);
235 rrddim_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRDDIM_INCREMENTAL);
237 else rrdset_next(st);
239 rrddim_set(st, "reads", readsectors);
240 rrddim_set(st, "writes", writesectors);
244 // --------------------------------------------------------------------
247 st = rrdset_find_bytype("disk_ops", disk);
249 st = rrdset_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
252 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
253 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
255 else rrdset_next(st);
257 rrddim_set(st, "reads", reads);
258 rrddim_set(st, "writes", writes);
262 // --------------------------------------------------------------------
265 st = rrdset_find_bytype("disk_merged_ops", disk);
267 st = rrdset_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, RRDSET_TYPE_LINE);
270 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
271 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
273 else rrdset_next(st);
275 rrddim_set(st, "reads", reads_merged);
276 rrddim_set(st, "writes", writes_merged);
280 // --------------------------------------------------------------------
283 st = rrdset_find_bytype("disk_iotime", disk);
285 st = rrdset_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, RRDSET_TYPE_LINE);
288 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
289 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
290 rrddim_add(st, "latency", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
291 rrddim_add(st, "weighted", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
293 else rrdset_next(st);
295 rrddim_set(st, "reads", readms);
296 rrddim_set(st, "writes", writems);
297 rrddim_set(st, "latency", iosms);
298 rrddim_set(st, "weighted", wiosms);
302 // --------------------------------------------------------------------
305 st = rrdset_find_bytype("disk_cur_ops", disk);
307 st = rrdset_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, RRDSET_TYPE_LINE);
310 rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
312 else rrdset_next(st);
314 rrddim_set(st, "operations", currentios);