X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=procps%2Fiostat.c;h=c290c594b8ada48c8a1a5e7189da390fcb6c8001;hb=5f7c82b32f548b5a1d6a4186630e8ef496a9d5e6;hp=573419e1c1c3ccd0fc9202bb568b8c6ff47e70cf;hpb=733f26f40708e0a4a2eb2475c446ae6a8e31f477;p=oweals%2Fbusybox.git diff --git a/procps/iostat.c b/procps/iostat.c index 573419e1c..c290c594b 100644 --- a/procps/iostat.c +++ b/procps/iostat.c @@ -4,28 +4,27 @@ * * Copyright (C) 2010 Marek Polacek * - * Licensed under GPLv2, see file License in this tarball for details. + * Licensed under GPLv2, see file LICENSE in this source tree. */ -//applet:IF_IOSTAT(APPLET(iostat, _BB_DIR_BIN, _BB_SUID_DROP)) - -//kbuild:lib-$(CONFIG_IOSTAT) += iostat.o - //config:config IOSTAT //config: bool "iostat" //config: default y //config: help //config: Report CPU and I/O statistics +//applet:IF_IOSTAT(APPLET(iostat, BB_DIR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_IOSTAT) += iostat.o + #include "libbb.h" -#include /* Need struct utsname */ +#include /* struct utsname */ -#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) -//#define debug(fmt, ...) ((void)0) +//#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) +#define debug(fmt, ...) ((void)0) -#define MAX_DEVICE_NAME 12 -#define CURRENT 0 -#define LAST 1 +#define MAX_DEVICE_NAME 12 +#define MAX_DEVICE_NAME_STR "12" #if 1 typedef unsigned long long cputime_t; @@ -39,44 +38,65 @@ typedef long icputime_t; # define CPUTIME_MAX (~0UL) #endif -struct stats_cpu { - cputime_t cpu_user; - cputime_t cpu_nice; - cputime_t cpu_system; - cputime_t cpu_idle; - cputime_t cpu_iowait; - cputime_t cpu_steal; - cputime_t cpu_irq; - cputime_t cpu_softirq; - cputime_t cpu_guest; +enum { + STATS_CPU_USER, + STATS_CPU_NICE, + STATS_CPU_SYSTEM, + STATS_CPU_IDLE, + STATS_CPU_IOWAIT, + STATS_CPU_IRQ, + STATS_CPU_SOFTIRQ, + STATS_CPU_STEAL, + STATS_CPU_GUEST, + + GLOBAL_UPTIME, + SMP_UPTIME, + + N_STATS_CPU, }; -struct stats_dev { - char dname[MAX_DEVICE_NAME]; +typedef struct { + cputime_t vector[N_STATS_CPU]; +} stats_cpu_t; + +typedef struct { + stats_cpu_t *prev; + stats_cpu_t *curr; + cputime_t itv; +} stats_cpu_pair_t; + +typedef struct { unsigned long long rd_sectors; unsigned long long wr_sectors; unsigned long rd_ops; unsigned long wr_ops; -}; +} stats_dev_data_t; -/* List of devices entered on the command line */ -struct device_list { - char dname[MAX_DEVICE_NAME]; -}; +typedef struct stats_dev { + struct stats_dev *next; + char dname[MAX_DEVICE_NAME + 1]; + stats_dev_data_t prev_data; + stats_dev_data_t curr_data; +} stats_dev_t; /* Globals. Sort by size and access frequency. */ struct globals { smallint show_all; - unsigned devlist_i; /* Index to the list of devices */ unsigned total_cpus; /* Number of CPUs */ unsigned clk_tck; /* Number of clock ticks per second */ - struct device_list *dlist; - struct stats_dev *saved_stats_dev; + llist_t *dev_name_list; /* List of devices entered on the command line */ + stats_dev_t *stats_dev_list; struct tm tmtime; + struct { + const char *str; + unsigned div; + } unit; }; #define G (*ptr_to_globals) #define INIT_G() do { \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ + G.unit.str = "Blk"; \ + G.unit.div = 1; \ } while (0) /* Must match option string! */ @@ -89,11 +109,6 @@ enum { OPT_m = 1 << 5, }; -static ALWAYS_INLINE unsigned get_user_hz(void) -{ - return sysconf(_SC_CLK_TCK); -} - static ALWAYS_INLINE int this_is_smp(void) { return (G.total_cpus > 1); @@ -101,39 +116,19 @@ static ALWAYS_INLINE int this_is_smp(void) static void print_header(void) { - char buf[16]; + char buf[32]; struct utsname uts; - if (uname(&uts) < 0) - bb_perror_msg_and_die("uname"); + uname(&uts); /* never fails */ + /* Date representation for the current locale */ strftime(buf, sizeof(buf), "%x", &G.tmtime); - printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n\n", + printf("%s %s (%s) \t%s \t_%s_\t(%u CPU)\n\n", uts.sysname, uts.release, uts.nodename, buf, uts.machine, G.total_cpus); } -static int get_number_of_cpus(void) -{ -#ifdef _SC_NPROCESSORS_CONF - return sysconf(_SC_NPROCESSORS_CONF); -#else - char buf[128]; - int n = 0; - FILE *fp; - - fp = xfopen_for_read("/proc/cpuinfo"); - - while (fgets(buf, sizeof(buf), fp)) - if (strncmp(buf, "processor\t:", 11) == 0) - n++; - - fclose(fp); - return n; -#endif -} - static void get_localtime(struct tm *ptm) { time_t timer; @@ -143,19 +138,30 @@ static void get_localtime(struct tm *ptm) static void print_timestamp(void) { - char buf[20]; + char buf[64]; + /* %x: date representation for the current locale */ + /* %X: time representation for the current locale */ strftime(buf, sizeof(buf), "%x %X", &G.tmtime); - printf("%s\n", buf); + puts(buf); } -/* Does str start with "cpu"? */ -static int starts_with_cpu(const char *str) +static cputime_t get_smp_uptime(void) { - return ((str[0] - 'c') | (str[1] - 'p') | (str[2] - 'u')) == 0; + FILE *fp; + unsigned long sec, dec; + + fp = xfopen_for_read("/proc/uptime"); + + if (fscanf(fp, "%lu.%lu", &sec, &dec) != 2) + bb_error_msg_and_die("can't read '%s'", "/proc/uptime"); + + fclose(fp); + + return (cputime_t)sec * G.clk_tck + dec * G.clk_tck / 100; } /* Fetch CPU statistics from /proc/stat */ -static void get_cpu_statistics(struct stats_cpu *sc) +static void get_cpu_statistics(stats_cpu_t *sc) { FILE *fp; char buf[1024]; @@ -165,46 +171,30 @@ static void get_cpu_statistics(struct stats_cpu *sc) memset(sc, 0, sizeof(*sc)); while (fgets(buf, sizeof(buf), fp)) { - /* Does the line starts with "cpu "? */ - if (starts_with_cpu(buf) && buf[3] == ' ') { - sscanf(buf + 4 + 1, - "%"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %" - FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u", - &sc->cpu_user, &sc->cpu_nice, &sc->cpu_system, - &sc->cpu_idle, &sc->cpu_iowait, &sc->cpu_irq, - &sc->cpu_softirq, &sc->cpu_steal, &sc->cpu_guest); + int i; + char *ibuf; + + /* Does the line start with "cpu "? */ + if (!starts_with_cpu(buf) || buf[3] != ' ') { + continue; + } + ibuf = buf + 4; + for (i = STATS_CPU_USER; i <= STATS_CPU_GUEST; i++) { + ibuf = skip_whitespace(ibuf); + sscanf(ibuf, "%"FMT_DATA"u", &sc->vector[i]); + if (i != STATS_CPU_GUEST) { + sc->vector[GLOBAL_UPTIME] += sc->vector[i]; + } + ibuf = skip_non_whitespace(ibuf); } + break; } - fclose(fp); -} - -static cputime_t get_smp_uptime(void) -{ - FILE *fp; - char buf[sizeof(long)*3 * 2 + 4]; - unsigned long sec, dec; - - fp = xfopen_for_read("/proc/uptime"); - - if (fgets(buf, sizeof(buf), fp)) - if (sscanf(buf, "%lu.%lu", &sec, &dec) != 2) - bb_error_msg_and_die("can't read /proc/uptime"); + if (this_is_smp()) { + sc->vector[SMP_UPTIME] = get_smp_uptime(); + } fclose(fp); - - return (cputime_t)sec * G.clk_tck + dec * G.clk_tck / 100; -} - -/* - * Obtain current uptime in jiffies. - * Uptime is sum of individual CPUs' uptimes. - */ -static cputime_t get_uptime(const struct stats_cpu *sc) -{ - /* NB: Don't include cpu_guest, it is already in cpu_user */ - return sc->cpu_user + sc->cpu_nice + sc->cpu_system + sc->cpu_idle + - + sc->cpu_iowait + sc->cpu_irq + sc->cpu_steal + sc->cpu_softirq; } static ALWAYS_INLINE cputime_t get_interval(cputime_t old, cputime_t new) @@ -245,65 +235,55 @@ static double percent_value(cputime_t prev, cputime_t curr, cputime_t itv) return ((double)overflow_safe_sub(prev, curr)) / itv * 100; } -static void print_stats_cpu_struct(const struct stats_cpu *p, - const struct stats_cpu *c, cputime_t itv) +static void print_stats_cpu_struct(stats_cpu_pair_t *stats) { - printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", - percent_value(p->cpu_user , c->cpu_user , itv), - percent_value(p->cpu_nice , c->cpu_nice , itv), - percent_value(p->cpu_system + p->cpu_softirq + p->cpu_irq, - c->cpu_system + c->cpu_softirq + c->cpu_irq, itv), - percent_value(p->cpu_iowait , c->cpu_iowait , itv), - percent_value(p->cpu_steal , c->cpu_steal , itv), - percent_value(p->cpu_idle , c->cpu_idle , itv) + cputime_t *p = stats->prev->vector; + cputime_t *c = stats->curr->vector; + printf(" %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n", + percent_value(p[STATS_CPU_USER] , c[STATS_CPU_USER] , stats->itv), + percent_value(p[STATS_CPU_NICE] , c[STATS_CPU_NICE] , stats->itv), + percent_value(p[STATS_CPU_SYSTEM] + p[STATS_CPU_SOFTIRQ] + p[STATS_CPU_IRQ], + c[STATS_CPU_SYSTEM] + c[STATS_CPU_SOFTIRQ] + c[STATS_CPU_IRQ], stats->itv), + percent_value(p[STATS_CPU_IOWAIT], c[STATS_CPU_IOWAIT], stats->itv), + percent_value(p[STATS_CPU_STEAL] , c[STATS_CPU_STEAL] , stats->itv), + percent_value(p[STATS_CPU_IDLE] , c[STATS_CPU_IDLE] , stats->itv) ); } -static void print_stats_dev_struct(const struct stats_dev *p, - const struct stats_dev *c, cputime_t itv) +static void cpu_report(stats_cpu_pair_t *stats) { - int unit = 1; + /* Always print a header */ + puts("avg-cpu: %user %nice %system %iowait %steal %idle"); - if (option_mask32 & OPT_k) - unit = 2; - else if (option_mask32 & OPT_m) - unit = 2048; + /* Print current statistics */ + print_stats_cpu_struct(stats); +} +static void print_stats_dev_struct(stats_dev_t *stats_dev, cputime_t itv) +{ + stats_dev_data_t *p = &stats_dev->prev_data; + stats_dev_data_t *c = &stats_dev->curr_data; if (option_mask32 & OPT_z) if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops) return; - printf("%-13s", c->dname); - printf(" %8.2f %12.2f %12.2f %10llu %10llu \n", - percent_value(p->rd_ops + p->wr_ops , - /**/ c->rd_ops + c->wr_ops , itv), - percent_value(p->rd_sectors, c->rd_sectors, itv) / unit, - percent_value(p->wr_sectors, c->wr_sectors, itv) / unit, - (c->rd_sectors - p->rd_sectors) / unit, - (c->wr_sectors - p->wr_sectors) / unit); -} - -static void cpu_report(const struct stats_cpu *last, - const struct stats_cpu *cur, - cputime_t itv) -{ - /* Always print a header */ - puts("avg-cpu: %user %nice %system %iowait %steal %idle"); - - /* Print current statistics */ - print_stats_cpu_struct(last, cur, itv); + printf("%-13s %8.2f %12.2f %12.2f %10llu %10llu\n", + stats_dev->dname, + percent_value(p->rd_ops + p->wr_ops, c->rd_ops + c->wr_ops, itv), + percent_value(p->rd_sectors, c->rd_sectors, itv) / G.unit.div, + percent_value(p->wr_sectors, c->wr_sectors, itv) / G.unit.div, + (c->rd_sectors - p->rd_sectors) / G.unit.div, + (c->wr_sectors - p->wr_sectors) / G.unit.div + ); } static void print_devstat_header(void) { - printf("Device: tps"); - - if (option_mask32 & OPT_m) - puts(" MB_read/s MB_wrtn/s MB_read MB_wrtn"); - else if (option_mask32 & OPT_k) - puts(" kB_read/s kB_wrtn/s kB_read kB_wrtn"); - else - puts(" Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn"); + printf("Device:%15s%6s%s/s%6s%s/s%6s%s%6s%s\n", + "tps", + G.unit.str, "_read", G.unit.str, "_wrtn", + G.unit.str, "_read", G.unit.str, "_wrtn" + ); } /* @@ -315,172 +295,99 @@ static int is_partition(const char *dev) return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]); } -/* - * Return number of numbers on cmdline. - * Reasonable values are only 0 (no interval/count specified), - * 1 (interval specified) and 2 (both interval and count specified) - */ -static int numbers_on_cmdline(int argc, char *argv[]) +static stats_dev_t *stats_dev_find_or_new(const char *dev_name) { - int sum = 0; + stats_dev_t **curr = &G.stats_dev_list; - if (isdigit(argv[argc-1][0])) - sum++; - if (argc > 2 && isdigit(argv[argc-2][0])) - sum++; + while (*curr != NULL) { + if (strcmp((*curr)->dname, dev_name) == 0) + return *curr; + curr = &(*curr)->next; + } - return sum; + *curr = xzalloc(sizeof(stats_dev_t)); + strncpy((*curr)->dname, dev_name, MAX_DEVICE_NAME); + return *curr; } -static int is_dev_in_dlist(const char *dev) +static void stats_dev_free(stats_dev_t *stats_dev) { - int i; - - /* Go through the device list */ - for (i = 0; i < G.devlist_i; i++) - if (strcmp(G.dlist[i].dname, dev) == 0) - /* Found a match */ - return 1; - - /* No match found */ - return 0; + if (stats_dev) { + stats_dev_free(stats_dev->next); + free(stats_dev); + } } static void do_disk_statistics(cputime_t itv) { + char buf[128]; + char dev_name[MAX_DEVICE_NAME + 1]; + unsigned long long rd_sec_or_dummy; + unsigned long long wr_sec_or_dummy; + stats_dev_data_t *curr_data; + stats_dev_t *stats_dev; FILE *fp; int rc; - int i = 0; - char buf[128]; - unsigned major, minor; - unsigned long wr_ops, dummy; /* %*lu for suppres the conversion wouldn't work */ - unsigned long long rd_sec_or_wr_ops; - unsigned long long rd_sec_or_dummy, wr_sec_or_dummy, wr_sec; - struct stats_dev sd; fp = xfopen_for_read("/proc/diskstats"); - /* Read and possibly print stats from /proc/diskstats */ while (fgets(buf, sizeof(buf), fp)) { - rc = sscanf(buf, "%u %u %s %lu %llu %llu %llu %lu %lu %llu %lu %lu %lu %lu", - &major, &minor, sd.dname, &sd.rd_ops, - &rd_sec_or_dummy, &rd_sec_or_wr_ops, &wr_sec_or_dummy, - &wr_ops, &dummy, &wr_sec, &dummy, &dummy, &dummy, &dummy); - - switch (rc) { - case 14: - sd.wr_ops = wr_ops; - sd.rd_sectors = rd_sec_or_wr_ops; - sd.wr_sectors = wr_sec; - break; - case 7: - sd.rd_sectors = rd_sec_or_dummy; - sd.wr_ops = (unsigned long)rd_sec_or_wr_ops; - sd.wr_sectors = wr_sec_or_dummy; - break; - default: - break; - } - - if (!G.devlist_i && !is_partition(sd.dname)) { - /* User didn't specify device */ - if (!G.show_all && !sd.rd_ops && !sd.wr_ops) { - /* Don't print unused device */ - continue; - } - print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); - G.saved_stats_dev[i] = sd; - i++; - } else { - /* Is device in device list? */ - if (is_dev_in_dlist(sd.dname)) { - /* Print current statistics */ - print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); - G.saved_stats_dev[i] = sd; - i++; - } else + sscanf(buf, "%*s %*s %"MAX_DEVICE_NAME_STR"s", dev_name); + if (G.dev_name_list) { + /* Is device name in list? */ + if (!llist_find_str(G.dev_name_list, dev_name)) continue; + } else if (is_partition(dev_name)) { + continue; } - } -} - -static void dev_report(cputime_t itv) -{ - /* Always print a header */ - print_devstat_header(); - - /* Fetch current disk statistics */ - do_disk_statistics(itv); -} - -static void save_to_devlist(const char *dname) -{ - int i; - struct device_list *tmp = G.dlist; - - if (strncmp(dname, "/dev/", 5) == 0) - /* We'll ignore prefix '/dev/' */ - dname += 5; - - /* Go through the list */ - for (i = 0; i < G.devlist_i; i++, tmp++) - if (strcmp(tmp->dname, dname) == 0) - /* Already in the list */ - return; - - /* Add device name to the list */ - strncpy(tmp->dname, dname, MAX_DEVICE_NAME - 1); - /* Update device list index */ - G.devlist_i++; -} - -static unsigned get_number_of_devices(void) -{ - FILE *fp; - char buf[128]; - int rv; - unsigned n = 0; - unsigned long rd_ops, wr_ops; - char dname[MAX_DEVICE_NAME]; - - fp = xfopen_for_read("/proc/diskstats"); + stats_dev = stats_dev_find_or_new(dev_name); + curr_data = &stats_dev->curr_data; + + rc = sscanf(buf, "%*s %*s %*s %lu %llu %llu %llu %lu %*s %llu", + &curr_data->rd_ops, + &rd_sec_or_dummy, + &curr_data->rd_sectors, + &wr_sec_or_dummy, + &curr_data->wr_ops, + &curr_data->wr_sectors); + if (rc != 6) { + curr_data->rd_sectors = rd_sec_or_dummy; + curr_data->wr_sectors = wr_sec_or_dummy; + //curr_data->rd_ops = ; + curr_data->wr_ops = (unsigned long)curr_data->rd_sectors; + } - while (fgets(buf, sizeof(buf), fp)) { - rv = sscanf(buf, "%*d %*d %s %lu %*u %*u %*u %lu", - dname, &rd_ops, &wr_ops); - if (rv == 2 || is_partition(dname)) - /* A partition */ + if (!G.dev_name_list /* User didn't specify device */ + && !G.show_all + && curr_data->rd_ops == 0 + && curr_data->wr_ops == 0 + ) { + /* Don't print unused device */ continue; - if (!rd_ops && !wr_ops) { - /* Unused device */ - if (!G.show_all) - continue; } - n++; + + /* Print current statistics */ + print_stats_dev_struct(stats_dev, itv); + stats_dev->prev_data = *curr_data; } fclose(fp); - return n; } -static int number_of_ALL_on_cmdline(char **argv) +static void dev_report(cputime_t itv) { - int alls = 0; - - /* Iterate over cmd line arguments, count "ALL" */ - while (*argv) - if (strcmp(*argv++, "ALL") == 0) - alls++; + /* Always print a header */ + print_devstat_header(); - return alls; + /* Fetch current disk statistics */ + do_disk_statistics(itv); } //usage:#define iostat_trivial_usage //usage: "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]" //usage:#define iostat_full_usage "\n\n" //usage: "Report CPU and I/O statistics\n" -//usage: "\nOptions:" //usage: "\n -c Show CPU utilization" //usage: "\n -d Show device utilization" //usage: "\n -t Print current time" @@ -489,25 +396,25 @@ static int number_of_ALL_on_cmdline(char **argv) //usage: "\n -m Use Mb/s" int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; -int iostat_main(int argc, char **argv) +int iostat_main(int argc UNUSED_PARAM, char **argv) { - int opt, dev_num; - unsigned interval = 0; - int count = 0; - cputime_t global_uptime[2] = { 0 }; - cputime_t smp_uptime[2] = { 0 }; - cputime_t itv; - struct stats_cpu stats_cur, stats_last; + int opt; + unsigned interval; + int count; + stats_cpu_t stats_data[2]; + smallint current_stats; INIT_G(); - memset(&stats_last, 0, sizeof(stats_last)); + memset(&stats_data, 0, sizeof(stats_data)); /* Get number of clock ticks per sec */ - G.clk_tck = get_user_hz(); + G.clk_tck = bb_clk_tck(); /* Determine number of CPUs */ - G.total_cpus = get_number_of_cpus(); + G.total_cpus = get_cpu_count(); + if (G.total_cpus == 0) + G.total_cpus = 1; /* Parse and process arguments */ /* -k and -m are mutually exclusive */ @@ -518,64 +425,73 @@ int iostat_main(int argc, char **argv) opt |= OPT_c + OPT_d; argv += optind; - argc -= optind; - - dev_num = argc - numbers_on_cmdline(argc, argv); - /* We don't want to allocate space for 'ALL' */ - dev_num -= number_of_ALL_on_cmdline(argv); - if (dev_num > 0) - /* Make space for device list */ - G.dlist = xzalloc(sizeof(G.dlist[0]) * dev_num); /* Store device names into device list */ while (*argv && !isdigit(*argv[0])) { - if (strcmp(*argv, "ALL") != 0) + if (strcmp(*argv, "ALL") != 0) { /* If not ALL, save device name */ - save_to_devlist(*argv); - else + char *dev_name = skip_dev_pfx(*argv); + if (!llist_find_str(G.dev_name_list, dev_name)) { + llist_add_to(&G.dev_name_list, dev_name); + } + } else { G.show_all = 1; + } argv++; } + interval = 0; + count = 1; if (*argv) { /* Get interval */ - interval = xatoi_u(*argv); - count = interval ? -1 : 1; + interval = xatoi_positive(*argv); + count = (interval != 0 ? -1 : 1); argv++; if (*argv) /* Get count value */ - count = xatoi_u(*argv); + count = xatoi_positive(*argv); } - /* Allocate space for device stats */ - if (opt & OPT_d) { - G.saved_stats_dev = xzalloc(sizeof(G.saved_stats_dev[0]) * - (dev_num ? dev_num : get_number_of_devices()) - ); + if (opt & OPT_m) { + G.unit.str = " MB"; + G.unit.div = 2048; + } + + if (opt & OPT_k) { + G.unit.str = " kB"; + G.unit.div = 2; } + get_localtime(&G.tmtime); + /* Display header */ print_header(); + current_stats = 0; /* Main loop */ for (;;) { + stats_cpu_pair_t stats; + + stats.prev = &stats_data[current_stats ^ 1]; + stats.curr = &stats_data[current_stats]; + /* Fill the time structure */ get_localtime(&G.tmtime); /* Fetch current CPU statistics */ - get_cpu_statistics(&stats_cur); - - /* Fetch current uptime */ - global_uptime[CURRENT] = get_uptime(&stats_cur); + get_cpu_statistics(stats.curr); /* Get interval */ - itv = get_interval(global_uptime[LAST], global_uptime[CURRENT]); + stats.itv = get_interval( + stats.prev->vector[GLOBAL_UPTIME], + stats.curr->vector[GLOBAL_UPTIME] + ); if (opt & OPT_t) print_timestamp(); if (opt & OPT_c) { - cpu_report(&stats_last, &stats_cur, itv); + cpu_report(&stats); if (opt & OPT_d) /* Separate outputs by a newline */ bb_putchar('\n'); @@ -583,32 +499,31 @@ int iostat_main(int argc, char **argv) if (opt & OPT_d) { if (this_is_smp()) { - smp_uptime[CURRENT] = get_smp_uptime(); - itv = get_interval(smp_uptime[LAST], smp_uptime[CURRENT]); - smp_uptime[LAST] = smp_uptime[CURRENT]; + stats.itv = get_interval( + stats.prev->vector[SMP_UPTIME], + stats.curr->vector[SMP_UPTIME] + ); } - dev_report(itv); + dev_report(stats.itv); } + bb_putchar('\n'); + if (count > 0) { if (--count == 0) break; } - /* Backup current stats */ - global_uptime[LAST] = global_uptime[CURRENT]; - stats_last = stats_cur; + /* Swap stats */ + current_stats ^= 1; - bb_putchar('\n'); sleep(interval); } - bb_putchar('\n'); - if (ENABLE_FEATURE_CLEAN_UP) { + llist_free(G.dev_name_list, NULL); + stats_dev_free(G.stats_dev_list); free(&G); - free(G.dlist); - free(G.saved_stats_dev); } return EXIT_SUCCESS;