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;
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("/proc/diskstats", " \t", PROCFILE_FLAG_DEFAULT);
37 ff = procfile_readall(ff);
38 if(!ff) return 0; // we return 0, so that we will retry to open it next time
40 uint32_t lines = procfile_lines(ff), l;
43 for(l = 0; l < lines ;l++) {
45 unsigned long long major = 0, minor = 0,
46 reads = 0, reads_merged = 0, readsectors = 0, readms = 0,
47 writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
48 currentios = 0, iosms = 0, wiosms = 0;
50 words = procfile_linewords(ff, l);
51 if(words < 14) continue;
53 major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
54 minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
55 disk = procfile_lineword(ff, l, 2);
56 reads = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
57 reads_merged = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
58 readsectors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
59 readms = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
60 writes = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
61 writes_merged = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
62 writesectors = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
63 writems = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
64 currentios = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
65 iosms = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
66 wiosms = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
70 // remove slashes from disk names
72 for(s = disk; *s ;s++) if(*s == '/') *s = '_';
76 case 43: // network block
83 def_enabled = enable_new_disks;
105 if(minor % 8) def_enabled = 0; // partitions
106 else def_enabled = enable_new_disks;
109 case 8: // scsi disks
110 case 65: // scsi disks
111 case 66: // scsi disks
112 case 67: // scsi disks
113 case 68: // scsi disks
114 case 69: // scsi disks
115 case 70: // scsi disks
116 case 71: // scsi disks
117 case 72: // scsi disks
118 case 73: // scsi disks
119 case 74: // scsi disks
120 case 75: // scsi disks
121 case 76: // scsi disks
122 case 77: // scsi disks
123 case 78: // scsi disks
124 case 79: // scsi disks
133 case 101: // hyperdisk
134 case 102: // compressed
143 case 114: // bios raid
144 case 116: // ram board
157 if(minor % 16) def_enabled = 0; // partitions
158 else def_enabled = enable_new_disks;
163 if(minor % 32) def_enabled = 0; // partitions
164 else def_enabled = enable_new_disks;
178 if(minor % 64) def_enabled = 0; // partitions
179 else def_enabled = enable_new_disks;
187 // check if it is enabled
189 char var_name[4096 + 1];
190 snprintf(var_name, 4096, "disk %s", disk);
191 if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
196 // --------------------------------------------------------------------
199 st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
201 char tf[FILENAME_MAX + 1], *t;
202 char ssfilename[FILENAME_MAX + 1];
203 int sector_size = 512;
205 strncpy(tf, disk, FILENAME_MAX);
206 tf[FILENAME_MAX] = '\0';
208 // replace all / with !
209 while((t = strchr(tf, '/'))) *t = '!';
211 snprintf(ssfilename, FILENAME_MAX, "/sys/block/%s/queue/hw_sector_size", tf);
212 FILE *fpss = fopen(ssfilename, "r");
215 char *tmp = fgets(ssbuffer, 1024, fpss);
218 sector_size = atoi(tmp);
219 if(sector_size <= 0) {
220 error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
224 else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
228 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
230 st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
232 rrddim_add(st, "reads", NULL, sector_size, 1024 * update_every, RRDDIM_INCREMENTAL);
233 rrddim_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRDDIM_INCREMENTAL);
235 else rrdset_next(st);
237 rrddim_set(st, "reads", readsectors);
238 rrddim_set(st, "writes", writesectors);
242 // --------------------------------------------------------------------
245 st = rrdset_find_bytype("disk_ops", disk);
247 st = rrdset_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
250 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
251 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
253 else rrdset_next(st);
255 rrddim_set(st, "reads", reads);
256 rrddim_set(st, "writes", writes);
260 // --------------------------------------------------------------------
263 st = rrdset_find_bytype("disk_merged_ops", disk);
265 st = rrdset_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, RRDSET_TYPE_LINE);
268 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
269 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
271 else rrdset_next(st);
273 rrddim_set(st, "reads", reads_merged);
274 rrddim_set(st, "writes", writes_merged);
278 // --------------------------------------------------------------------
281 st = rrdset_find_bytype("disk_iotime", disk);
283 st = rrdset_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, RRDSET_TYPE_LINE);
286 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
287 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
288 rrddim_add(st, "latency", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
289 rrddim_add(st, "weighted", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
291 else rrdset_next(st);
293 rrddim_set(st, "reads", readms);
294 rrddim_set(st, "writes", writems);
295 rrddim_set(st, "latency", iosms);
296 rrddim_set(st, "weighted", wiosms);
300 // --------------------------------------------------------------------
303 st = rrdset_find_bytype("disk_cur_ops", disk);
305 st = rrdset_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, RRDSET_TYPE_LINE);
308 rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
310 else rrdset_next(st);
312 rrddim_set(st, "operations", currentios);