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