mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-17 02:25:09 +00:00
rewrite linux diskio code
Instead of using a hardcoded maximum number of slots for stats of different disks, use a linked list. Also since the algorithm to update each device's counters is the same for updating the totals, share equal code, which in my eyes not only saves a bunch of LoC, but also drastically increases readability.
This commit is contained in:
parent
a619cb3e3c
commit
4161f90c6f
@ -33,6 +33,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include "diskio.h"
|
||||||
|
|
||||||
/* check for OS and include appropriate headers */
|
/* check for OS and include appropriate headers */
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
int check_mount(char *s);
|
int check_mount(char *s);
|
||||||
void update_diskio(void);
|
|
||||||
void prepare_update(void);
|
void prepare_update(void);
|
||||||
void update_uptime(void);
|
void update_uptime(void);
|
||||||
void update_meminfo(void);
|
void update_meminfo(void);
|
||||||
@ -83,7 +82,6 @@ double get_sysfs_info(int *fd, int arg, char *devtype, char *type);
|
|||||||
|
|
||||||
void get_adt746x_cpu(char *, size_t);
|
void get_adt746x_cpu(char *, size_t);
|
||||||
void get_adt746x_fan(char *, size_t);
|
void get_adt746x_fan(char *, size_t);
|
||||||
unsigned int get_diskio(void);
|
|
||||||
|
|
||||||
int open_acpi_temperature(const char *name);
|
int open_acpi_temperature(const char *name);
|
||||||
double get_acpi_temperature(int fd);
|
double get_acpi_temperature(int fd);
|
||||||
|
173
src/diskio.c
173
src/diskio.c
@ -48,79 +48,91 @@
|
|||||||
#define NBD_MAJOR 43
|
#define NBD_MAJOR 43
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct diskio_stat diskio_stats_[MAX_DISKIO_STATS];
|
/* this is the root of all per disk stats,
|
||||||
struct diskio_stat *diskio_stats = diskio_stats_;
|
* also containing the totals. */
|
||||||
|
static struct diskio_stat stats = {
|
||||||
|
.next = NULL,
|
||||||
|
.current = 0,
|
||||||
|
.current_read = 0,
|
||||||
|
.current_write = 0,
|
||||||
|
.last = UINT_MAX,
|
||||||
|
.last_read = UINT_MAX,
|
||||||
|
.last_write = UINT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
void clear_diskio_stats(void)
|
void clear_diskio_stats(void)
|
||||||
{
|
{
|
||||||
unsigned i;
|
struct diskio_stat *cur;
|
||||||
for(i = 1; i < MAX_DISKIO_STATS; i++) {
|
while (stats.next) {
|
||||||
if (diskio_stats[i].dev) {
|
cur = stats.next;
|
||||||
free(diskio_stats[i].dev);
|
stats.next = stats.next->next;
|
||||||
diskio_stats[i].dev = 0;
|
free(cur);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct diskio_stat *prepare_diskio_stat(const char *s)
|
struct diskio_stat *prepare_diskio_stat(const char *s)
|
||||||
{
|
{
|
||||||
struct diskio_stat *new = 0;
|
struct diskio_stat *cur = &stats;
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
if (!s)
|
if (!s)
|
||||||
return &diskio_stats[0];
|
return &stats;
|
||||||
|
|
||||||
/* lookup existing or get new */
|
/* lookup existing */
|
||||||
for (i = 1; i < MAX_DISKIO_STATS; i++) {
|
while (cur->next) {
|
||||||
if (diskio_stats[i].dev) {
|
cur = cur->next;
|
||||||
if (strcmp(diskio_stats[i].dev, s) == 0) {
|
if (!strcmp(cur->dev, s))
|
||||||
return &diskio_stats[i];
|
return cur;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
new = &diskio_stats[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* new dev */
|
|
||||||
if (!new) {
|
/* no existing found, make a new one */
|
||||||
ERR("too many diskio stats");
|
cur->next = malloc(sizeof(struct diskio_stat));
|
||||||
return 0;
|
cur = cur->next;
|
||||||
|
memset(cur, 0, sizeof(struct diskio_stat));
|
||||||
|
cur->dev = strndup(s, text_buffer_size);
|
||||||
|
cur->last = UINT_MAX;
|
||||||
|
cur->last_read = UINT_MAX;
|
||||||
|
cur->last_write = UINT_MAX;
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_diskio_values(struct diskio_stat *ds,
|
||||||
|
unsigned int reads, unsigned int writes)
|
||||||
|
{
|
||||||
|
if (reads < ds->last_read || writes < ds->last_write) {
|
||||||
|
/* counter overflow or reset - rebase to sane values */
|
||||||
|
ds->last = 0;
|
||||||
|
ds->last_read = 0;
|
||||||
|
ds->last_write = 0;
|
||||||
}
|
}
|
||||||
if (new->dev) {
|
/* since the values in /proc/diskstats are absolute, we have to substract
|
||||||
free(new->dev);
|
* our last reading. The numbers stand for "sectors read", and we therefore
|
||||||
new->dev = 0;
|
* have to divide by two to get KB */
|
||||||
}
|
ds->current_read = (reads - ds->last_read) / 2;
|
||||||
new->dev = strndup(s, text_buffer_size);
|
ds->current_write = (writes - ds->last_write) / 2;
|
||||||
new->current = 0;
|
ds->current = ds->current_read + ds->current_write;
|
||||||
new->current_read = 0;
|
|
||||||
new ->current_write = 0;
|
ds->last_read = reads;
|
||||||
new->last = UINT_MAX;
|
ds->last_write = writes;
|
||||||
new->last_read = UINT_MAX;
|
ds->last = ds->last_read + ds->last_write;
|
||||||
new->last_write = UINT_MAX;
|
|
||||||
return new;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_diskio(void)
|
void update_diskio(void)
|
||||||
{
|
{
|
||||||
static unsigned int last = UINT_MAX;
|
|
||||||
static unsigned int last_read = UINT_MAX;
|
|
||||||
static unsigned int last_write = UINT_MAX;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
static int rep = 0;
|
static int rep = 0;
|
||||||
|
|
||||||
|
struct diskio_stat *cur;
|
||||||
char buf[512], devbuf[64];
|
char buf[512], devbuf[64];
|
||||||
int i;
|
|
||||||
unsigned int major, minor;
|
unsigned int major, minor;
|
||||||
unsigned int current = 0;
|
unsigned int reads, writes;
|
||||||
unsigned int current_read = 0;
|
unsigned int total_reads, total_writes;
|
||||||
unsigned int current_write = 0;
|
|
||||||
unsigned int reads, writes = 0;
|
|
||||||
int col_count = 0;
|
int col_count = 0;
|
||||||
int tot, tot_read, tot_write;
|
|
||||||
|
stats.current = 0;
|
||||||
|
stats.current_read = 0;
|
||||||
|
stats.current_write = 0;
|
||||||
|
|
||||||
if (!(fp = open_file("/proc/diskstats", &rep))) {
|
if (!(fp = open_file("/proc/diskstats", &rep))) {
|
||||||
|
|
||||||
diskio_stats[0].current = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +147,8 @@ void update_diskio(void)
|
|||||||
* XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */
|
* XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */
|
||||||
if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR
|
if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR
|
||||||
&& major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
|
&& major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
|
||||||
current += reads + writes;
|
total_reads += reads;
|
||||||
current_read += reads;
|
total_writes += writes;
|
||||||
current_write += writes;
|
|
||||||
} else {
|
} else {
|
||||||
col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
|
col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
|
||||||
&major, &minor, devbuf, &reads, &writes);
|
&major, &minor, devbuf, &reads, &writes);
|
||||||
@ -145,60 +156,14 @@ void update_diskio(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 1; i < MAX_DISKIO_STATS; i++) {
|
cur = stats.next;
|
||||||
if (diskio_stats[i].dev && !strcmp(devbuf, diskio_stats[i].dev)) {
|
while (cur && strcmp(devbuf, cur->dev))
|
||||||
diskio_stats[i].current =
|
cur = cur->next;
|
||||||
(reads + writes - diskio_stats[i].last) / 2;
|
|
||||||
diskio_stats[i].current_read =
|
if (cur)
|
||||||
(reads - diskio_stats[i].last_read) / 2;
|
update_diskio_values(cur, reads, writes);
|
||||||
diskio_stats[i].current_write =
|
|
||||||
(writes - diskio_stats[i].last_write) / 2;
|
|
||||||
if (reads + writes < diskio_stats[i].last) {
|
|
||||||
diskio_stats[i].current = 0;
|
|
||||||
}
|
|
||||||
if (reads < diskio_stats[i].last_read) {
|
|
||||||
diskio_stats[i].current_read = 0;
|
|
||||||
diskio_stats[i].current = diskio_stats[i].current_write;
|
|
||||||
}
|
|
||||||
if (writes < diskio_stats[i].last_write) {
|
|
||||||
diskio_stats[i].current_write = 0;
|
|
||||||
diskio_stats[i].current = diskio_stats[i].current_read;
|
|
||||||
}
|
|
||||||
diskio_stats[i].last = reads + writes;
|
|
||||||
diskio_stats[i].last_read = reads;
|
|
||||||
diskio_stats[i].last_write = writes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
update_diskio_values(&stats, total_reads, total_writes);
|
||||||
/* since the values in /proc/diststats are absolute, we have to substract
|
|
||||||
* our last reading. The numbers stand for "sectors read", and we therefore
|
|
||||||
* have to divide by two to get KB */
|
|
||||||
tot = ((double) (current - last) / 2);
|
|
||||||
tot_read = ((double) (current_read - last_read) / 2);
|
|
||||||
tot_write = ((double) (current_write - last_write) / 2);
|
|
||||||
|
|
||||||
if (last_read > current_read) {
|
|
||||||
tot_read = 0;
|
|
||||||
}
|
|
||||||
if (last_write > current_write) {
|
|
||||||
tot_write = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last > current) {
|
|
||||||
/* we hit this either if it's the very first time we run this, or
|
|
||||||
* when /proc/diskstats overflows; while 0 is not correct, it's at
|
|
||||||
* least not way off */
|
|
||||||
tot = 0;
|
|
||||||
}
|
|
||||||
last = current;
|
|
||||||
last_read = current_read;
|
|
||||||
last_write = current_write;
|
|
||||||
|
|
||||||
diskio_stats[0].current = tot;
|
|
||||||
diskio_stats[0].current_read = tot_read;
|
|
||||||
diskio_stats[0].current_write = tot_write;
|
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/diskio.h
14
src/diskio.h
@ -30,16 +30,18 @@
|
|||||||
#define DISKIO_H_
|
#define DISKIO_H_
|
||||||
|
|
||||||
struct diskio_stat {
|
struct diskio_stat {
|
||||||
|
struct diskio_stat *next;
|
||||||
char *dev;
|
char *dev;
|
||||||
unsigned int current, current_read, current_write, last, last_read,
|
unsigned int current;
|
||||||
last_write;
|
unsigned int current_read;
|
||||||
|
unsigned int current_write;
|
||||||
|
unsigned int last;
|
||||||
|
unsigned int last_read;
|
||||||
|
unsigned int last_write;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_DISKIO_STATS 64
|
|
||||||
|
|
||||||
struct diskio_stat *diskio_stats;
|
|
||||||
|
|
||||||
struct diskio_stat *prepare_diskio_stat(const char *s);
|
struct diskio_stat *prepare_diskio_stat(const char *s);
|
||||||
|
void update_diskio(void);
|
||||||
void clear_diskio_stats(void);
|
void clear_diskio_stats(void);
|
||||||
|
|
||||||
#endif /* DISKIO_H_ */
|
#endif /* DISKIO_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user