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");
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);
71 case 43: // network block
78 def_enabled = enable_new_disks;
100 if(minor % 8) def_enabled = 0; // partitions
101 else def_enabled = enable_new_disks;
104 case 8: // scsi disks
105 case 65: // scsi disks
106 case 66: // scsi disks
107 case 67: // scsi disks
108 case 68: // scsi disks
109 case 69: // scsi disks
110 case 70: // scsi disks
111 case 71: // scsi disks
112 case 72: // scsi disks
113 case 73: // scsi disks
114 case 74: // scsi disks
115 case 75: // scsi disks
116 case 76: // scsi disks
117 case 77: // scsi disks
118 case 78: // scsi disks
119 case 79: // scsi disks
128 case 101: // hyperdisk
129 case 102: // compressed
138 case 114: // bios raid
139 case 116: // ram board
152 if(minor % 16) def_enabled = 0; // partitions
153 else def_enabled = enable_new_disks;
158 if(minor % 32) def_enabled = 0; // partitions
159 else def_enabled = enable_new_disks;
173 if(minor % 64) def_enabled = 0; // partitions
174 else def_enabled = enable_new_disks;
182 // check if it is enabled
184 char var_name[4096 + 1];
185 snprintf(var_name, 4096, "disk %s", disk);
186 if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
191 // --------------------------------------------------------------------
194 st = rrd_stats_find_bytype(RRD_TYPE_DISK, disk);
196 char tf[FILENAME_MAX + 1], *t;
197 char ssfilename[FILENAME_MAX + 1];
198 int sector_size = 512;
200 strncpy(tf, disk, FILENAME_MAX);
201 tf[FILENAME_MAX] = '\0';
203 // replace all / with !
204 while((t = strchr(tf, '/'))) *t = '!';
206 snprintf(ssfilename, FILENAME_MAX, "/sys/block/%s/queue/hw_sector_size", tf);
207 FILE *fpss = fopen(ssfilename, "r");
210 char *tmp = fgets(ssbuffer, 1024, fpss);
213 sector_size = atoi(tmp);
214 if(sector_size <= 0) {
215 error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
219 else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
223 else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
225 st = rrd_stats_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, CHART_TYPE_AREA);
227 rrd_stats_dimension_add(st, "reads", NULL, sector_size, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
228 rrd_stats_dimension_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
230 else rrd_stats_next(st);
232 rrd_stats_dimension_set(st, "reads", readsectors);
233 rrd_stats_dimension_set(st, "writes", writesectors);
237 // --------------------------------------------------------------------
240 st = rrd_stats_find_bytype("disk_ops", disk);
242 st = rrd_stats_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, CHART_TYPE_LINE);
245 rrd_stats_dimension_add(st, "reads", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
246 rrd_stats_dimension_add(st, "writes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
248 else rrd_stats_next(st);
250 rrd_stats_dimension_set(st, "reads", reads);
251 rrd_stats_dimension_set(st, "writes", writes);
255 // --------------------------------------------------------------------
258 st = rrd_stats_find_bytype("disk_merged_ops", disk);
260 st = rrd_stats_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, CHART_TYPE_LINE);
263 rrd_stats_dimension_add(st, "reads", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
264 rrd_stats_dimension_add(st, "writes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
266 else rrd_stats_next(st);
268 rrd_stats_dimension_set(st, "reads", reads_merged);
269 rrd_stats_dimension_set(st, "writes", writes_merged);
273 // --------------------------------------------------------------------
276 st = rrd_stats_find_bytype("disk_iotime", disk);
278 st = rrd_stats_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, CHART_TYPE_LINE);
281 rrd_stats_dimension_add(st, "reads", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
282 rrd_stats_dimension_add(st, "writes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
283 rrd_stats_dimension_add(st, "latency", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
284 rrd_stats_dimension_add(st, "weighted", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
286 else rrd_stats_next(st);
288 rrd_stats_dimension_set(st, "reads", readms);
289 rrd_stats_dimension_set(st, "writes", writems);
290 rrd_stats_dimension_set(st, "latency", iosms);
291 rrd_stats_dimension_set(st, "weighted", wiosms);
295 // --------------------------------------------------------------------
298 st = rrd_stats_find_bytype("disk_cur_ops", disk);
300 st = rrd_stats_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, CHART_TYPE_LINE);
303 rrd_stats_dimension_add(st, "operations", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
305 else rrd_stats_next(st);
307 rrd_stats_dimension_set(st, "operations", currentios);