From: Nikos Ntarmos Date: Thu, 14 May 2009 22:52:18 +0000 (+0300) Subject: Integrate FreeBSD diskio support. X-Git-Url: http://git.maemo.org/git/?p=monky;a=commitdiff_plain;h=12d0d1477f12a0669dfcff48d2533fbb93bddc3d 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 --- diff --git a/src/Makefile.am b/src/Makefile.am index 794b351..53bcfd5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,7 +77,7 @@ endif #endif if BUILD_FREEBSD -freebsd = freebsd.c +freebsd = freebsd.c diskio.c PTHREAD_LIBS = -pthread endif diff --git a/src/diskio.c b/src/diskio.c index 6a53a07..ce4b22b 100644 --- a/src/diskio.c +++ b/src/diskio.c @@ -33,24 +33,11 @@ #include "common.h" #include #include -/* The following ifdefs were adapted from gkrellm */ -#include - -#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 /* 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); -} - diff --git a/src/diskio.h b/src/diskio.h index 0cc9003..373f5d5 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -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_ */ diff --git a/src/freebsd.c b/src/freebsd.c index b170a67..20c4e27 100644 --- a/src/freebsd.c +++ b/src/freebsd.c @@ -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) diff --git a/src/linux.c b/src/linux.c index eb90895..74fceb3 100644 --- a/src/linux.c +++ b/src/linux.c @@ -30,6 +30,7 @@ #include "logging.h" #include "common.h" #include "linux.h" +#include "diskio.h" #include #include #include @@ -58,6 +59,21 @@ #include #include +/* The following ifdefs were adapted from gkrellm */ +#include + +#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 #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); +}