1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-12-27 04:32:55 +00:00

Integrate FreeBSD diskio support.

This diff moves Linux-specific parts of diskio.c into linux.c and uses
the remaining diskio functions to correctly implement this functionality
for FreeBSD. It also hooks diskio.c to the FreeBSD build.

Signed-off-by: Brenden Matthews <brenden@rty.ca>
This commit is contained in:
Nikos Ntarmos 2009-05-15 01:52:18 +03:00 committed by Brenden Matthews
parent ec2597f944
commit 12d0d1477f
5 changed files with 113 additions and 164 deletions

View File

@ -77,7 +77,7 @@ endif
#endif
if BUILD_FREEBSD
freebsd = freebsd.c
freebsd = freebsd.c diskio.c
PTHREAD_LIBS = -pthread
endif

View File

@ -33,24 +33,11 @@
#include "common.h"
#include <stdlib.h>
#include <limits.h>
/* The following ifdefs were adapted from gkrellm */
#include <linux/major.h>
#if !defined(MD_MAJOR)
#define MD_MAJOR 9
#endif
#if !defined(LVM_BLK_MAJOR)
#define LVM_BLK_MAJOR 58
#endif
#if !defined(NBD_MAJOR)
#define NBD_MAJOR 43
#endif
#include <sys/stat.h>
/* this is the root of all per disk stats,
* also containing the totals. */
static struct diskio_stat stats = {
struct diskio_stat stats = {
.next = NULL,
.sample = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
.sample_read = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
@ -75,30 +62,48 @@ void clear_diskio_stats(void)
struct diskio_stat *prepare_diskio_stat(const char *s)
{
struct stat sb;
char stat_name[text_buffer_size], device_name[text_buffer_size];
struct diskio_stat *cur = &stats;
if (!s)
return &stats;
#if defined(__FreeBSD__)
if (strncmp(s, "/dev/", 5) == 0) {
// supplied a /dev/device arg, so cut off the /dev part
strncpy(device_name, s + 5, text_buffer_size);
} else
#endif
strncpy(device_name, s, text_buffer_size);
snprintf(stat_name, text_buffer_size, "/dev/%s", device_name);
if (stat(stat_name, &sb)) {
ERR("diskio device '%s' does not exist", s);
return 0;
}
/* lookup existing */
while (cur->next) {
cur = cur->next;
if (!strcmp(cur->dev, s))
if (!strcmp(cur->dev, device_name)) {
return cur;
}
}
/* no existing found, make a new one */
cur->next = malloc(sizeof(struct diskio_stat));
cur->next = calloc(1, sizeof(struct diskio_stat));
cur = cur->next;
memset(cur, 0, sizeof(struct diskio_stat));
cur->dev = strndup(s, text_buffer_size);
cur->dev = strndup(device_name, 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,
void update_diskio_values(struct diskio_stat *ds,
unsigned int reads, unsigned int writes)
{
int i;
@ -140,54 +145,3 @@ static void update_diskio_values(struct diskio_stat *ds,
ds->last = ds->last_read + ds->last_write;
}
void update_diskio(void)
{
FILE *fp;
static int rep = 0;
struct diskio_stat *cur;
char buf[512], devbuf[64];
unsigned int major, minor;
unsigned int reads, writes;
unsigned int total_reads=0, total_writes=0;
int col_count = 0;
stats.current = 0;
stats.current_read = 0;
stats.current_write = 0;
if (!(fp = open_file("/proc/diskstats", &rep))) {
return;
}
/* read reads and writes from all disks (minor = 0), including cd-roms
* and floppies, and sum them up */
while (fgets(buf, 512, fp)) {
col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u", &major,
&minor, devbuf, &reads, &writes);
/* ignore subdevices (they have only 3 matching entries in their line)
* and virtual devices (LVM, network block devices, RAM disks, Loopback)
*
* XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */
if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR
&& major != RAMDISK_MAJOR && major != LOOP_MAJOR && minor==0) {
total_reads += reads;
total_writes += writes;
} else {
col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
&major, &minor, devbuf, &reads, &writes);
if (col_count != 5) {
continue;
}
}
cur = stats.next;
while (cur && strcmp(devbuf, cur->dev))
cur = cur->next;
if (cur)
update_diskio_values(cur, reads, writes);
}
update_diskio_values(&stats, total_reads, total_writes);
fclose(fp);
}

View File

@ -43,8 +43,11 @@ struct diskio_stat {
double last_write;
};
struct diskio_stat *prepare_diskio_stat(const char *s);
extern struct diskio_stat stats;
struct diskio_stat *prepare_diskio_stat(const char *);
void update_diskio(void);
void clear_diskio_stats(void);
void update_diskio_values(struct diskio_stat *, unsigned int, unsigned int);
#endif /* DISKIO_H_ */

View File

@ -65,15 +65,6 @@
inline void proc_find_top(struct process **cpu, struct process **mem);
static short cpu_setup = 0;
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,
};
static int getsysctl(char *name, void *ptr, size_t len)
{
@ -658,59 +649,49 @@ cleanup:
void update_diskio()
{
int devs_count, num_selected, num_selections;
int devs_count, num_selected, num_selections, dn;
struct device_selection *dev_select = NULL;
long select_generation;
int dn;
static struct statinfo statinfo_cur;
char device_name[text_buffer_size];
struct diskio_stat *cur;
unsigned int reads, writes;
unsigned int total_reads = 0, total_writes = 0;
bzero(&statinfo_cur, sizeof(statinfo_cur));
memset(&statinfo_cur, 0, sizeof(statinfo_cur));
statinfo_cur.dinfo = (struct devinfo *)calloc(1, sizeof(struct devinfo));
stats.current = stats.current_read = stats.current_write = 0;
if (devstat_getdevs(NULL, &statinfo_cur) < 0)
if (devstat_getdevs(NULL, &statinfo_cur) < 0) {
free(statinfo_cur.dinfo);
return;
}
devs_count = statinfo_cur.dinfo->numdevs;
if (devstat_selectdevs(&dev_select, &num_selected, &num_selections,
&select_generation, statinfo_cur.dinfo->generation,
statinfo_cur.dinfo->devices, devs_count, NULL, 0, NULL, 0,
DS_SELECT_ONLY, MAXSHOWDEVS, 1) >= 0) {
for (dn = 0; dn < devs_count; ++dn) {
for (dn = 0; dn < devs_count; dn++) {
int di;
struct devstat *dev;
di = dev_select[dn].position;
dev = &statinfo_cur.dinfo->devices[di];
snprintf(device_name, text_buffer_size, "%s%d",
dev_select[dn].device_name, dev_select[dn].unit_number);
total_reads += (reads = dev->bytes[DEVSTAT_READ] / 512);
total_writes += (writes = dev->bytes[DEVSTAT_WRITE] / 512);
for (cur = stats.next; cur; cur = cur->next) {
if (cur->dev && !strcmp(dev_select[dn].device_name, cur->dev)) {
cur->current = (dev->bytes[DEVSTAT_READ] +
dev->bytes[DEVSTAT_WRITE] - cur->last) / 1024;
cur->current_read = (dev->bytes[DEVSTAT_READ] -
cur->last_read) / 1024;
cur->current_write = (dev->bytes[DEVSTAT_WRITE] -
cur->last_write) / 1024;
if (dev->bytes[DEVSTAT_READ] + dev->bytes[DEVSTAT_WRITE] <
cur->last) {
cur->current = 0;
}
if (dev->bytes[DEVSTAT_READ] < cur->last_read) {
cur->current_read = 0;
cur->current = cur->current_write;
}
if (dev->bytes[DEVSTAT_WRITE] < cur->last_write) {
cur->current_write = 0;
cur->current = cur->current_read;
}
cur->last = dev->bytes[DEVSTAT_READ] +
dev->bytes[DEVSTAT_WRITE];
cur->last_read = dev->bytes[DEVSTAT_READ];
cur->last_write = dev->bytes[DEVSTAT_WRITE];
if (cur->dev && !strcmp(device_name, cur->dev)) {
update_diskio_values(cur, reads, writes);
break;
}
}
}
update_diskio_values(&stats, total_reads, total_writes);
free(dev_select);
}
@ -718,60 +699,6 @@ void update_diskio()
free(statinfo_cur.dinfo);
}
void clear_diskio_stats()
{
struct diskio_stat *cur;
while (stats.next) {
cur = stats.next;
stats.next = stats.next->next;
free(cur);
}
}
struct diskio_stat *prepare_diskio_stat(const char *s)
{
struct diskio_stat *new = 0;
struct stat sb;
int found = 0;
char device[text_buffer_size], fbuf[text_buffer_size];
static int rep = 0;
/* lookup existing or get new */
struct diskio_stat *cur = &stats;
if (!s)
return cur;
while (cur->next) {
cur = cur->next;
if (!strcmp(cur->dev, s))
return cur;
}
/* new dev */
if (!(cur->next = calloc(1, sizeof(struct diskio_stat)))) {
ERR("out of memory allocating new disk stats struct");
return NULL;
}
cur = cur->next;
cur->last = cur->last_read = cur->last_write = UINT_MAX;
if (strncmp(s, "/dev/", 5) == 0) {
// supplied a /dev/device arg, so cut off the /dev part
cur->dev = strndup(s + 5, text_buffer_size);
} else {
cur->dev = strndup(s, text_buffer_size);
}
/*
* check that device actually exists
*/
snprintf(device, text_buffer_size, "/dev/%s", new->dev);
if (stat(device, &sb)) {
ERR("diskio device '%s' does not exist", s);
return 0;
}
return cur;
}
/* While topless is obviously better, top is also not bad. */
int comparecpu(const void *a, const void *b)

View File

@ -30,6 +30,7 @@
#include "logging.h"
#include "common.h"
#include "linux.h"
#include "diskio.h"
#include <dirent.h>
#include <ctype.h>
#include <errno.h>
@ -58,6 +59,21 @@
#include <linux/route.h>
#include <math.h>
/* The following ifdefs were adapted from gkrellm */
#include <linux/major.h>
#if !defined(MD_MAJOR)
#define MD_MAJOR 9
#endif
#if !defined(LVM_BLK_MAJOR)
#define LVM_BLK_MAJOR 58
#endif
#if !defined(NBD_MAJOR)
#define NBD_MAJOR 43
#endif
#ifdef HAVE_IWLIB
#include <iwlib.h>
#endif
@ -2131,3 +2147,52 @@ const char *get_disk_protect_queue(const char *disk)
return (state > 0) ? "frozen" : "free ";
}
void update_diskio(void)
{
FILE *fp;
static int rep = 0;
char buf[512], devbuf[64];
unsigned int major, minor;
int col_count = 0;
struct diskio_stat *cur;
unsigned int reads, writes;
unsigned int total_reads = 0, total_writes = 0;
stats.current = 0;
stats.current_read = 0;
stats.current_write = 0;
if (!(fp = open_file("/proc/diskstats", &rep))) {
return;
}
/* read reads and writes from all disks (minor = 0), including cd-roms
* and floppies, and sum them up */
while (fgets(buf, 512, fp)) {
col_count = sscanf(buf, "%u %u %s %*u %*u %u %*u %*u %*u %u", &major,
&minor, devbuf, &reads, &writes);
/* ignore subdevices (they have only 3 matching entries in their line)
* and virtual devices (LVM, network block devices, RAM disks, Loopback)
*
* XXX: ignore devices which are part of a SW RAID (MD_MAJOR) */
if (col_count == 5 && major != LVM_BLK_MAJOR && major != NBD_MAJOR
&& major != RAMDISK_MAJOR && major != LOOP_MAJOR) {
total_reads += reads;
total_writes += writes;
} else {
col_count = sscanf(buf, "%u %u %s %*u %u %*u %u",
&major, &minor, devbuf, &reads, &writes);
if (col_count != 5) {
continue;
}
}
cur = stats.next;
while (cur && strcmp(devbuf, cur->dev))
cur = cur->next;
if (cur)
update_diskio_values(cur, reads, writes);
}
update_diskio_values(&stats, total_reads, total_writes);
fclose(fp);
}