2 * Conky, a system monitor, based on torsmo
4 * Any original torsmo code is licensed under the BSD license
6 * All code written since the fork of torsmo is licensed under the GPL
8 * Please see COPYING for details
10 * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
11 * Copyright (c) 2005-2009 Brenden Matthews, Philip Kovacs, et. al.
13 * All rights reserved.
15 * This program is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include "conky.h" /* text_buffer_size */
36 /* The following ifdefs were adapted from gkrellm */
37 #include <linux/major.h>
39 #if !defined(MD_MAJOR)
43 #if !defined(LVM_BLK_MAJOR)
44 #define LVM_BLK_MAJOR 58
47 #if !defined(NBD_MAJOR)
51 /* this is the root of all per disk stats,
52 * also containing the totals. */
53 static struct diskio_stat stats = {
55 .sample = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
56 .sample_read = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
57 .sample_write = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
62 .last_read = UINT_MAX,
63 .last_write = UINT_MAX,
66 void clear_diskio_stats(void)
68 struct diskio_stat *cur;
71 stats.next = stats.next->next;
76 struct diskio_stat *prepare_diskio_stat(const char *s)
78 struct diskio_stat *cur = &stats;
86 if (!strcmp(cur->dev, s))
90 /* no existing found, make a new one */
91 cur->next = malloc(sizeof(struct diskio_stat));
93 memset(cur, 0, sizeof(struct diskio_stat));
94 cur->dev = strndup(s, text_buffer_size);
96 cur->last_read = UINT_MAX;
97 cur->last_write = UINT_MAX;
101 static void update_diskio_values(struct diskio_stat *ds,
102 unsigned int reads, unsigned int writes)
105 double sum=0, sum_r=0, sum_w=0;
107 if (reads < ds->last_read || writes < ds->last_write) {
108 /* counter overflow or reset - rebase to sane values */
109 ds->last = reads+writes;
110 ds->last_read = reads;
111 ds->last_write = writes;
113 /* since the values in /proc/diskstats are absolute, we have to substract
114 * our last reading. The numbers stand for "sectors read", and we therefore
115 * have to divide by two to get KB */
116 ds->sample_read[0] = (reads - ds->last_read) / 2;
117 ds->sample_write[0] = (writes - ds->last_write) / 2;
118 ds->sample[0] = ds->sample_read[0] + ds->sample_write[0];
120 /* compute averages */
121 for (i = 0; i < (signed) info.diskio_avg_samples; i++) {
122 sum += ds->sample[i];
123 sum_r += ds->sample_read[i];
124 sum_w += ds->sample_write[i];
126 ds->current = sum / (double) info.diskio_avg_samples;
127 ds->current_read = sum_r / (double) info.diskio_avg_samples;
128 ds->current_write = sum_w / (double) info.diskio_avg_samples;
130 /* shift sample history */
131 for (i = info.diskio_avg_samples-1; i > 0; i--) {
132 ds->sample[i] = ds->sample[i-1];
133 ds->sample_read[i] = ds->sample_read[i-1];
134 ds->sample_write[i] = ds->sample_write[i-1];
138 ds->last_read = reads;
139 ds->last_write = writes;
140 ds->last = ds->last_read + ds->last_write;
143 void update_diskio(void)
148 struct diskio_stat *cur;
149 char buf[512], devbuf[64];
150 unsigned int major, minor;
151 unsigned int reads, writes;
152 unsigned int total_reads=0, total_writes=0;
156 stats.current_read = 0;
157 stats.current_write = 0;
159 if (!(fp = open_file("/proc/diskstats", &rep))) {
163 /* read reads and writes from all disks (minor = 0), including cd-roms
164 * and floppies, and sum them up */
165 while (fgets(buf, 512, fp)) {
166 col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u", &major,
167 &minor, devbuf, &reads, &writes);
168 /* ignore subdevices (they have only 3 matching entries in their line)
169 * and virtual devices (LVM, network block devices, RAM disks, Loopback)
171 * XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */
172 if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR
173 && major != RAMDISK_MAJOR && major != LOOP_MAJOR && minor==0) {
174 total_reads += reads;
175 total_writes += writes;
177 col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
178 &major, &minor, devbuf, &reads, &writes);
179 if (col_count != 5) {
184 while (cur && strcmp(devbuf, cur->dev))
188 update_diskio_values(cur, reads, writes);
190 update_diskio_values(&stats, total_reads, total_writes);