| slstatus-diskio-4bd78c9.patch - sites - public wiki contents of suckless.org | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| slstatus-diskio-4bd78c9.patch (5402B) | |
| --- | |
| 1 Author: K. Eugene Carlson <[email protected]> | |
| 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 %j… | |
| 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 (… | |
| 221 * ipv6 IPv6 address interface name (… | |
| 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); |