#endif
if BUILD_FREEBSD
-freebsd = freebsd.c
+freebsd = freebsd.c diskio.c
PTHREAD_LIBS = -pthread
endif
#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},
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;
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);
-}
-
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_ */
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)
{
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);
}
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)
#include "logging.h"
#include "common.h"
#include "linux.h"
+#include "diskio.h"
#include <dirent.h>
#include <ctype.h>
#include <errno.h>
#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
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);
+}