slstatus-diskio-4bd78c9.patch - sites - public wiki contents of suckless.org
(HTM) git clone git://git.suckless.org/sites
(DIR) Log
(DIR) Files
(DIR) Refs
---
slstatus-diskio-4bd78c9.patch (5402B)
---
1 Author: K. Eugene Carlson <kvngncrlsn@gmail.com>
2 Date: Fri Sep 3 01:09:02 2021 +0900
3
4 Get disk IO stats on Linux (read, write, %)
5
6 This patch lets slstatus report on disk IO on Linux systems: reads
7 from disk, writes to disk and IO percentage.
8
9 diff --git a/Makefile b/Makefile
10 index 3be46cc..1ecc8db 100644
11 --- a/Makefile
12 +++ b/Makefile
13 @@ -12,6 +12,7 @@ COM =\
14 components/disk\
15 components/entropy\
16 components/hostname\
17 + components/iocheck\
18 components/ip\
19 components/kernel_release\
20 components/keyboard_indicators\
21 diff --git a/README b/README
22 index 4da0756..1a64914 100644
23 --- a/README
24 +++ b/README
25 @@ -15,6 +15,7 @@ Features
26 - Available entropy
27 - Username/GID/UID
28 - Hostname
29 +- Disk IO (read, write and percentage) (Linux only)
30 - IP address (IPv4 and IPv6)
31 - Kernel version
32 - Keyboard indicators
33 diff --git a/components/iocheck.c b/components/iocheck.c
34 new file mode 100644
35 index 0000000..7fa102d
36 --- /dev/null
37 +++ b/components/iocheck.c
38 @@ -0,0 +1,170 @@
39 +/* See LICENSE file for copyright and license details. */
40 +#include <stdio.h>
41 +#include <string.h>
42 +#include <stdint.h>
43 +#include <stdlib.h>
44 +#include <dirent.h>
45 +#include <unistd.h>
46 +
47 +#include "../util.h"
48 +
49 +#if defined(__linux__)
50 + static int
51 + get_io(uintmax_t *s_in, uintmax_t *s_out)
52 + {
53 + FILE *fp;
54 + struct {
55 + const char *name;
56 + const size_t len;
57 + uintmax_t *var;
58 + } ent[] = {
59 + { "pgpgin", sizeof("pgpgin") - 1, s_in },
60 + { "pgpgout", sizeof("pgpgout") - 1, s_out },
61 + };
62 + size_t line_len = 0, i, left;
63 + char *line = NULL;
64 +
65 + /* get number of fields we want to extract */
66 + for (i = 0, left = 0; i < LEN(ent); i++) {
67 + if (ent[i].var) {
68 + left++;
69 + }
70 + }
71 +
72 + if (!(fp = fopen("/proc/vmstat", "r"))) {
73 + warn("fopen '/proc/vmstat':");
74 + return 1;
75 + }
76 +
77 + /* read file line by line and extract field information */
78 + while (left > 0 && getline(&line, &line_len, fp) >= 0) {
79 + for (i = 0; i < LEN(ent); i++) {
80 + if (ent[i].var &&
81 + !strncmp(line,ent[i].name, ent[i].len)) {
82 + sscanf(line + ent[i].len + 1,
83 + "%ju\n", ent[i].var);
84 + left--;
85 + break;
86 + }
87 + }
88 + }
89 + free(line);
90 + if(ferror(fp)) {
91 + warn("getline '/proc/vmstat':");
92 + return 1;
93 + }
94 +
95 + fclose(fp);
96 + return 0;
97 + }
98 +
99 + const char *
100 + io_in(void)
101 + {
102 + uintmax_t oldin;
103 + static uintmax_t newin;
104 +
105 + oldin = newin;
106 +
107 + if (get_io(&newin, NULL)) {
108 + return NULL;
109 + }
110 + if (oldin == 0) {
111 + return NULL;
112 + }
113 +
114 + return fmt_human((newin-oldin) * 1024, 1024);
115 + }
116 +
117 + const char *
118 + io_out(void)
119 + {
120 + uintmax_t oldout;
121 + static uintmax_t newout;
122 +
123 + oldout = newout;
124 +
125 + if (get_io(NULL, &newout)) {
126 + return NULL;
127 + }
128 + if (oldout == 0) {
129 + return NULL;
130 + }
131 +
132 + return fmt_human((newout - oldout) * 1024, 1024);
133 + }
134 +
135 + const char *
136 + io_perc(void)
137 + {
138 + struct dirent *dp;
139 + DIR *bd;
140 + uintmax_t oldwait;
141 + static uintmax_t newwait;
142 + extern const unsigned int interval;
143 +
144 + oldwait = newwait;
145 +
146 + if (!(bd = opendir("/sys/block"))) {
147 + warn("opendir '%s':", "/sys/block");
148 + return NULL;
149 + }
150 +
151 + newwait = 0;
152 + /* get IO wait stats from the /sys/block directories */
153 + while ((dp = readdir(bd))) {
154 + if (strstr(dp->d_name, "loop") ||
155 + strstr(dp->d_name, "ram")) {
156 + continue;
157 + }
158 + if (!strcmp(dp->d_name, ".") ||
159 + !strcmp(dp->d_name, "..")) {
160 + continue;
161 + }
162 + /* virtual devices don't count */
163 + char virtpath[50];
164 + strcpy(virtpath, "/sys/devices/virtual/block/");
165 + strcat(virtpath, dp->d_name);
166 + if (access(virtpath, R_OK) == 0) {
167 + continue;
168 + }
169 + char statpath[34];
170 + strcpy(statpath, "/sys/block/");
171 + strcat(statpath, dp->d_name);
172 + strcat(statpath, "/stat");
173 + uintmax_t partwait;
174 + if (pscanf(statpath,
175 + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %ju %*d",
176 + &partwait) != 1) {
177 + continue;
178 + }
179 + newwait += partwait;
180 + }
181 + closedir(bd);
182 + if (oldwait == 0 || newwait < oldwait) {
183 + return NULL;
184 + }
185 +
186 + return bprintf("%0.1f", 100 *
187 + (newwait - oldwait) / (float)interval);
188 + }
189 +
190 +#else
191 + const char *
192 + io_in(void)
193 + {
194 + return NULL;
195 + }
196 +
197 + const char *
198 + io_out(void)
199 + {
200 + return NULL;
201 + }
202 +
203 + const char *
204 + io_perc(void)
205 + {
206 + return NULL;
207 + }
208 +#endif
209 diff --git a/config.def.h b/config.def.h
210 index 5f6c114..4d49881 100644
211 --- a/config.def.h
212 +++ b/config.def.h
213 @@ -28,6 +28,9 @@ static const char unknown_str[] = "n/a";
214 * entropy available entropy NULL
215 * gid GID of current user NULL
216 * hostname hostname NULL
217 + * io_in disk IO (read) NULL
218 + * io_out disk IO (write) NULL
219 + * io_perc disk IO (percentage) NULL
220 * ipv4 IPv4 address interface name (eth0)
221 * ipv6 IPv6 address interface name (eth0)
222 * kernel_release `uname -r` NULL
223 diff --git a/slstatus.h b/slstatus.h
224 index f3b4979..8b14b75 100644
225 --- a/slstatus.h
226 +++ b/slstatus.h
227 @@ -24,6 +24,11 @@ const char *entropy(const char *unused);
228 /* hostname */
229 const char *hostname(const char *unused);
230
231 +/* iocheck */
232 +const char *io_in(void);
233 +const char *io_out(void);
234 +const char *io_perc(void);
235 +
236 /* ip */
237 const char *ipv4(const char *interface);
238 const char *ipv6(const char *interface);