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 <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);