10 #include "plugin_proc.h"
12 #define RRD_TYPE_DISK "disk"
13 #define RRD_TYPE_DISK_LEN strlen(RRD_TYPE_DISK)
15 #define MAX_PROC_DISKSTATS_LINE 4096
17 int do_proc_diskstats(int update_every, unsigned long long dt) {
18 static procfile *ff = NULL;
20 static int enable_new_disks = -1;
21 static int do_io = -1, do_ops = -1, do_merged_ops = -1, do_iotime = -1, do_cur_ops = -1;
23 if(enable_new_disks == -1) enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
25 if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
26 if(do_ops == -1) do_ops = config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
27 if(do_merged_ops == -1) do_merged_ops = config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
28 if(do_iotime == -1) do_iotime = config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
29 if(do_cur_ops == -1) do_cur_ops = config_get_boolean("plugin:proc:/proc/diskstats", "current operations for all disks", 1);
33 if(!ff) ff = procfile_open("/proc/diskstats", " \t", PROCFILE_FLAG_DEFAULT);
36 ff = procfile_readall(ff);
37 if(!ff) return 0; // we return 0, so that we will retry to open it next time
39 uint32_t lines = procfile_lines(ff), l;
42 for(l = 0; l < lines ;l++) {
44 unsigned long long major = 0, minor = 0,
45 reads = 0, reads_merged = 0, readsectors = 0, readms = 0,
46 writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
47 currentios = 0, iosms = 0, wiosms = 0;
49 words = procfile_linewords(ff, l);
50 if(words < 14) continue;
52 major = strtoull(procfile_lineword(ff, l, 0), NULL, 10);
53 minor = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
54 disk = procfile_lineword(ff, l, 2);
55 reads = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
56 reads_merged = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
57 readsectors = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
58 readms = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
59 writes = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
60 writes_merged = strtoull(procfile_lineword(ff, l, 8), NULL, 10);
61 writesectors = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
62 writems = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
63 currentios = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
64 iosms = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
65 wiosms = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
69 // remove slashes from disk names
71 for(s = disk; *s ;s++) if(*s == '/') *s = '_';
75 case 43: // network block
82 def_enabled = enable_new_disks;
104 if(minor % 8) def_enabled = 0; // partitions
105 else def_enabled = enable_new_disks;
108 case 8: // scsi disks
109 case 65: // scsi disks
110 case 66: // scsi disks
111 case 67: // scsi disks
112 case 68: // scsi disks
113 case 69: // scsi disks
114 case 70: // scsi disks
115 case 71: // scsi disks
116 case 72: // scsi disks
117 case 73: // scsi disks
118 case 74: // scsi disks
119 case 75: // scsi disks
120 case 76: // scsi disks
121 case 77: // scsi disks
122 case 78: // scsi disks
123 case 79: // scsi disks
132 case 101: // hyperdisk
133 case 102: // compressed
142 case 114: // bios raid
143 case 116: // ram board
156 if(minor % 16) def_enabled = 0; // partitions
157 else def_enabled = enable_new_disks;
162 if(minor % 32) def_enabled = 0; // partitions
163 else def_enabled = enable_new_disks;
177 if(minor % 64) def_enabled = 0; // partitions
178 else def_enabled = enable_new_disks;
186 // check if it is enabled
188 char var_name[4096 + 1];
189 snprintf(var_name, 4096, "disk %s", disk);
190 if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
195 // --------------------------------------------------------------------
198 st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
200 char tf[FILENAME_MAX + 1], *t;
201 char ssfilename[FILENAME_MAX + 1];
202 int sector_size = 512;
204 strncpy(tf, disk, FILENAME_MAX);
205 tf[FILENAME_MAX] = '\0';
207 // replace all / with !
208 while((t = strchr(tf, '/'))) *t = '!';
210 snprintf(ssfilename, FILENAME_MAX, "/sys/block/%s/queue/hw_sector_size", tf);
211 FILE *fpss = fopen(ssfilename, "r");
214 char *tmp = fgets(ssbuffer, 1024, fpss);
217 sector_size = atoi(tmp);
218 if(sector_size <= 0) {
219 error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
223 else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
227 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
229 st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
231 rrddim_add(st, "reads", NULL, sector_size, 1024 * update_every, RRDDIM_INCREMENTAL);
232 rrddim_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRDDIM_INCREMENTAL);
234 else rrdset_next(st);
236 rrddim_set(st, "reads", readsectors);
237 rrddim_set(st, "writes", writesectors);
241 // --------------------------------------------------------------------
244 st = rrdset_find_bytype("disk_ops", disk);
246 st = rrdset_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
249 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
250 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
252 else rrdset_next(st);
254 rrddim_set(st, "reads", reads);
255 rrddim_set(st, "writes", writes);
259 // --------------------------------------------------------------------
262 st = rrdset_find_bytype("disk_merged_ops", disk);
264 st = rrdset_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, RRDSET_TYPE_LINE);
267 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
268 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
270 else rrdset_next(st);
272 rrddim_set(st, "reads", reads_merged);
273 rrddim_set(st, "writes", writes_merged);
277 // --------------------------------------------------------------------
280 st = rrdset_find_bytype("disk_iotime", disk);
282 st = rrdset_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, RRDSET_TYPE_LINE);
285 rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
286 rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
287 rrddim_add(st, "latency", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
288 rrddim_add(st, "weighted", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
290 else rrdset_next(st);
292 rrddim_set(st, "reads", readms);
293 rrddim_set(st, "writes", writems);
294 rrddim_set(st, "latency", iosms);
295 rrddim_set(st, "weighted", wiosms);
299 // --------------------------------------------------------------------
302 st = rrdset_find_bytype("disk_cur_ops", disk);
304 st = rrdset_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, RRDSET_TYPE_LINE);
307 rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
309 else rrdset_next(st);
311 rrddim_set(st, "operations", currentios);