diff options
author | Maksym Kryzhanovskyy <xmaks@email.cz> | 2011-05-07 04:37:22 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-05-07 04:37:22 +0200 |
commit | 29c54aa9f9e8eedf2d227550a790e76661ce63ad (patch) | |
tree | b4c2992f36bd66d6aa2d13b57b7dd4470cf36ed7 /procps/iostat.c | |
parent | c3f8db99bf91e6fb131c8d2240fc4d5a44ed561a (diff) | |
download | busybox-w32-29c54aa9f9e8eedf2d227550a790e76661ce63ad.tar.gz busybox-w32-29c54aa9f9e8eedf2d227550a790e76661ce63ad.tar.bz2 busybox-w32-29c54aa9f9e8eedf2d227550a790e76661ce63ad.zip |
iostat: code shrink ~0.5k
Signed-off-by: Maksym Kryzhanovskyy <xmaks@email.cz>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to '')
-rw-r--r-- | procps/iostat.c | 306 |
1 files changed, 125 insertions, 181 deletions
diff --git a/procps/iostat.c b/procps/iostat.c index 28bf4dec2..cd233c72f 100644 --- a/procps/iostat.c +++ b/procps/iostat.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #define debug(fmt, ...) ((void)0) | 24 | #define debug(fmt, ...) ((void)0) |
25 | 25 | ||
26 | #define MAX_DEVICE_NAME 12 | 26 | #define MAX_DEVICE_NAME 12 |
27 | #define CURRENT 0 | ||
28 | #define LAST 1 | ||
29 | 27 | ||
30 | #if 1 | 28 | #if 1 |
31 | typedef unsigned long long cputime_t; | 29 | typedef unsigned long long cputime_t; |
@@ -39,18 +37,33 @@ typedef long icputime_t; | |||
39 | # define CPUTIME_MAX (~0UL) | 37 | # define CPUTIME_MAX (~0UL) |
40 | #endif | 38 | #endif |
41 | 39 | ||
42 | struct stats_cpu { | 40 | enum { |
43 | cputime_t cpu_user; | 41 | STATS_CPU_USER, |
44 | cputime_t cpu_nice; | 42 | STATS_CPU_NICE, |
45 | cputime_t cpu_system; | 43 | STATS_CPU_SYSTEM, |
46 | cputime_t cpu_idle; | 44 | STATS_CPU_IDLE, |
47 | cputime_t cpu_iowait; | 45 | STATS_CPU_IOWAIT, |
48 | cputime_t cpu_steal; | 46 | STATS_CPU_IRQ, |
49 | cputime_t cpu_irq; | 47 | STATS_CPU_SOFTIRQ, |
50 | cputime_t cpu_softirq; | 48 | STATS_CPU_STEAL, |
51 | cputime_t cpu_guest; | 49 | STATS_CPU_GUEST, |
50 | |||
51 | GLOBAL_UPTIME, | ||
52 | SMP_UPTIME, | ||
53 | |||
54 | N_STATS_CPU, | ||
52 | }; | 55 | }; |
53 | 56 | ||
57 | typedef struct { | ||
58 | cputime_t vector[N_STATS_CPU]; | ||
59 | } stats_cpu_t; | ||
60 | |||
61 | typedef struct { | ||
62 | stats_cpu_t *prev; | ||
63 | stats_cpu_t *curr; | ||
64 | cputime_t itv; | ||
65 | } stats_cpu_pair_t; | ||
66 | |||
54 | struct stats_dev { | 67 | struct stats_dev { |
55 | char dname[MAX_DEVICE_NAME]; | 68 | char dname[MAX_DEVICE_NAME]; |
56 | unsigned long long rd_sectors; | 69 | unsigned long long rd_sectors; |
@@ -59,24 +72,24 @@ struct stats_dev { | |||
59 | unsigned long wr_ops; | 72 | unsigned long wr_ops; |
60 | }; | 73 | }; |
61 | 74 | ||
62 | /* List of devices entered on the command line */ | ||
63 | struct device_list { | ||
64 | char dname[MAX_DEVICE_NAME]; | ||
65 | }; | ||
66 | |||
67 | /* Globals. Sort by size and access frequency. */ | 75 | /* Globals. Sort by size and access frequency. */ |
68 | struct globals { | 76 | struct globals { |
69 | smallint show_all; | 77 | smallint show_all; |
70 | unsigned devlist_i; /* Index to the list of devices */ | ||
71 | unsigned total_cpus; /* Number of CPUs */ | 78 | unsigned total_cpus; /* Number of CPUs */ |
72 | unsigned clk_tck; /* Number of clock ticks per second */ | 79 | unsigned clk_tck; /* Number of clock ticks per second */ |
73 | struct device_list *dlist; | 80 | llist_t *dev_list; /* List of devices entered on the command line */ |
74 | struct stats_dev *saved_stats_dev; | 81 | struct stats_dev *saved_stats_dev; |
75 | struct tm tmtime; | 82 | struct tm tmtime; |
83 | struct { | ||
84 | const char *str; | ||
85 | unsigned div; | ||
86 | } unit; | ||
76 | }; | 87 | }; |
77 | #define G (*ptr_to_globals) | 88 | #define G (*ptr_to_globals) |
78 | #define INIT_G() do { \ | 89 | #define INIT_G() do { \ |
79 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ | 90 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
91 | G.unit.str = "Blk"; \ | ||
92 | G.unit.div = 1; \ | ||
80 | } while (0) | 93 | } while (0) |
81 | 94 | ||
82 | /* Must match option string! */ | 95 | /* Must match option string! */ |
@@ -104,12 +117,12 @@ static void print_header(void) | |||
104 | char buf[16]; | 117 | char buf[16]; |
105 | struct utsname uts; | 118 | struct utsname uts; |
106 | 119 | ||
107 | if (uname(&uts) < 0) | 120 | uname(&uts); /* never fails */ |
108 | bb_perror_msg_and_die("uname"); | ||
109 | 121 | ||
122 | /* Date representation for the current locale */ | ||
110 | strftime(buf, sizeof(buf), "%x", &G.tmtime); | 123 | strftime(buf, sizeof(buf), "%x", &G.tmtime); |
111 | 124 | ||
112 | printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n\n", | 125 | printf("%s %s (%s) \t%s \t_%s_\t(%u CPU)\n\n", |
113 | uts.sysname, uts.release, uts.nodename, | 126 | uts.sysname, uts.release, uts.nodename, |
114 | buf, uts.machine, G.total_cpus); | 127 | buf, uts.machine, G.total_cpus); |
115 | } | 128 | } |
@@ -124,6 +137,8 @@ static void get_localtime(struct tm *ptm) | |||
124 | static void print_timestamp(void) | 137 | static void print_timestamp(void) |
125 | { | 138 | { |
126 | char buf[20]; | 139 | char buf[20]; |
140 | /* %x: date representation for the current locale */ | ||
141 | /* %X: time representation for the current locale */ | ||
127 | strftime(buf, sizeof(buf), "%x %X", &G.tmtime); | 142 | strftime(buf, sizeof(buf), "%x %X", &G.tmtime); |
128 | printf("%s\n", buf); | 143 | printf("%s\n", buf); |
129 | } | 144 | } |
@@ -131,14 +146,12 @@ static void print_timestamp(void) | |||
131 | static cputime_t get_smp_uptime(void) | 146 | static cputime_t get_smp_uptime(void) |
132 | { | 147 | { |
133 | FILE *fp; | 148 | FILE *fp; |
134 | char buf[sizeof(long)*3 * 2 + 4]; | ||
135 | unsigned long sec, dec; | 149 | unsigned long sec, dec; |
136 | 150 | ||
137 | fp = xfopen_for_read("/proc/uptime"); | 151 | fp = xfopen_for_read("/proc/uptime"); |
138 | 152 | ||
139 | if (fgets(buf, sizeof(buf), fp)) | 153 | if (fscanf(fp, "%lu.%lu", &sec, &dec) != 2) |
140 | if (sscanf(buf, "%lu.%lu", &sec, &dec) != 2) | 154 | bb_error_msg_and_die("can't read '%s'", "/proc/uptime"); |
141 | bb_error_msg_and_die("can't read /proc/uptime"); | ||
142 | 155 | ||
143 | fclose(fp); | 156 | fclose(fp); |
144 | 157 | ||
@@ -146,10 +159,10 @@ static cputime_t get_smp_uptime(void) | |||
146 | } | 159 | } |
147 | 160 | ||
148 | /* Fetch CPU statistics from /proc/stat */ | 161 | /* Fetch CPU statistics from /proc/stat */ |
149 | static void get_cpu_statistics(struct stats_cpu *sc) | 162 | static void get_cpu_statistics(stats_cpu_t *sc) |
150 | { | 163 | { |
151 | FILE *fp; | 164 | FILE *fp; |
152 | char buf[1024]; | 165 | char buf[1024], *ibuf = buf + 4; |
153 | 166 | ||
154 | fp = xfopen_for_read("/proc/stat"); | 167 | fp = xfopen_for_read("/proc/stat"); |
155 | 168 | ||
@@ -157,28 +170,25 @@ static void get_cpu_statistics(struct stats_cpu *sc) | |||
157 | 170 | ||
158 | while (fgets(buf, sizeof(buf), fp)) { | 171 | while (fgets(buf, sizeof(buf), fp)) { |
159 | /* Does the line starts with "cpu "? */ | 172 | /* Does the line starts with "cpu "? */ |
160 | if (starts_with_cpu(buf) && buf[3] == ' ') { | 173 | if (!starts_with_cpu(buf) || buf[3] != ' ') { |
161 | sscanf(buf + 4 + 1, | 174 | continue; |
162 | "%"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %" | ||
163 | FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u %"FMT_DATA"u", | ||
164 | &sc->cpu_user, &sc->cpu_nice, &sc->cpu_system, | ||
165 | &sc->cpu_idle, &sc->cpu_iowait, &sc->cpu_irq, | ||
166 | &sc->cpu_softirq, &sc->cpu_steal, &sc->cpu_guest); | ||
167 | } | 175 | } |
176 | for (int i = STATS_CPU_USER; i <= STATS_CPU_GUEST; i++) { | ||
177 | ibuf = skip_whitespace(ibuf); | ||
178 | sscanf(ibuf, "%"FMT_DATA"u", &sc->vector[i]); | ||
179 | if (i != STATS_CPU_GUEST) { | ||
180 | sc->vector[GLOBAL_UPTIME] += sc->vector[i]; | ||
181 | } | ||
182 | ibuf = skip_non_whitespace(ibuf); | ||
183 | } | ||
184 | break; | ||
168 | } | 185 | } |
169 | 186 | ||
170 | fclose(fp); | 187 | if (this_is_smp()) { |
171 | } | 188 | sc->vector[SMP_UPTIME] = get_smp_uptime(); |
189 | } | ||
172 | 190 | ||
173 | /* | 191 | fclose(fp); |
174 | * Obtain current uptime in jiffies. | ||
175 | * Uptime is sum of individual CPUs' uptimes. | ||
176 | */ | ||
177 | static cputime_t get_uptime(const struct stats_cpu *sc) | ||
178 | { | ||
179 | /* NB: Don't include cpu_guest, it is already in cpu_user */ | ||
180 | return sc->cpu_user + sc->cpu_nice + sc->cpu_system + sc->cpu_idle + | ||
181 | + sc->cpu_iowait + sc->cpu_irq + sc->cpu_steal + sc->cpu_softirq; | ||
182 | } | 192 | } |
183 | 193 | ||
184 | static ALWAYS_INLINE cputime_t get_interval(cputime_t old, cputime_t new) | 194 | static ALWAYS_INLINE cputime_t get_interval(cputime_t old, cputime_t new) |
@@ -219,65 +229,51 @@ static double percent_value(cputime_t prev, cputime_t curr, cputime_t itv) | |||
219 | return ((double)overflow_safe_sub(prev, curr)) / itv * 100; | 229 | return ((double)overflow_safe_sub(prev, curr)) / itv * 100; |
220 | } | 230 | } |
221 | 231 | ||
222 | static void print_stats_cpu_struct(const struct stats_cpu *p, | 232 | static void print_stats_cpu_struct(stats_cpu_pair_t *stats) |
223 | const struct stats_cpu *c, cputime_t itv) | ||
224 | { | 233 | { |
234 | cputime_t *p = stats->prev->vector; | ||
235 | cputime_t *c = stats->curr->vector; | ||
225 | printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", | 236 | printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", |
226 | percent_value(p->cpu_user , c->cpu_user , itv), | 237 | percent_value(p[STATS_CPU_USER] , c[STATS_CPU_USER] , stats->itv), |
227 | percent_value(p->cpu_nice , c->cpu_nice , itv), | 238 | percent_value(p[STATS_CPU_NICE] , c[STATS_CPU_NICE] , stats->itv), |
228 | percent_value(p->cpu_system + p->cpu_softirq + p->cpu_irq, | 239 | percent_value(p[STATS_CPU_SYSTEM] + p[STATS_CPU_SOFTIRQ] + p[STATS_CPU_IRQ], |
229 | c->cpu_system + c->cpu_softirq + c->cpu_irq, itv), | 240 | c[STATS_CPU_SYSTEM] + c[STATS_CPU_SOFTIRQ] + c[STATS_CPU_IRQ], stats->itv), |
230 | percent_value(p->cpu_iowait , c->cpu_iowait , itv), | 241 | percent_value(p[STATS_CPU_IOWAIT], c[STATS_CPU_IOWAIT], stats->itv), |
231 | percent_value(p->cpu_steal , c->cpu_steal , itv), | 242 | percent_value(p[STATS_CPU_STEAL] , c[STATS_CPU_STEAL] , stats->itv), |
232 | percent_value(p->cpu_idle , c->cpu_idle , itv) | 243 | percent_value(p[STATS_CPU_IDLE] , c[STATS_CPU_IDLE] , stats->itv) |
233 | ); | 244 | ); |
234 | } | 245 | } |
235 | 246 | ||
236 | static void print_stats_dev_struct(const struct stats_dev *p, | 247 | static void print_stats_dev_struct(const struct stats_dev *p, |
237 | const struct stats_dev *c, cputime_t itv) | 248 | const struct stats_dev *c, cputime_t itv) |
238 | { | 249 | { |
239 | int unit = 1; | ||
240 | |||
241 | if (option_mask32 & OPT_k) | ||
242 | unit = 2; | ||
243 | else if (option_mask32 & OPT_m) | ||
244 | unit = 2048; | ||
245 | |||
246 | if (option_mask32 & OPT_z) | 250 | if (option_mask32 & OPT_z) |
247 | if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops) | 251 | if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops) |
248 | return; | 252 | return; |
249 | 253 | ||
250 | printf("%-13s", c->dname); | 254 | printf("%-13s %8.2f %12.2f %12.2f %10llu %10llu \n", c->dname, |
251 | printf(" %8.2f %12.2f %12.2f %10llu %10llu \n", | ||
252 | percent_value(p->rd_ops + p->wr_ops , | 255 | percent_value(p->rd_ops + p->wr_ops , |
253 | /**/ c->rd_ops + c->wr_ops , itv), | 256 | /**/ c->rd_ops + c->wr_ops , itv), |
254 | percent_value(p->rd_sectors, c->rd_sectors, itv) / unit, | 257 | percent_value(p->rd_sectors, c->rd_sectors, itv) / G.unit.div, |
255 | percent_value(p->wr_sectors, c->wr_sectors, itv) / unit, | 258 | percent_value(p->wr_sectors, c->wr_sectors, itv) / G.unit.div, |
256 | (c->rd_sectors - p->rd_sectors) / unit, | 259 | (c->rd_sectors - p->rd_sectors) / G.unit.div, |
257 | (c->wr_sectors - p->wr_sectors) / unit); | 260 | (c->wr_sectors - p->wr_sectors) / G.unit.div); |
258 | } | 261 | } |
259 | 262 | ||
260 | static void cpu_report(const struct stats_cpu *last, | 263 | static void cpu_report(stats_cpu_pair_t *stats) |
261 | const struct stats_cpu *cur, | ||
262 | cputime_t itv) | ||
263 | { | 264 | { |
264 | /* Always print a header */ | 265 | /* Always print a header */ |
265 | puts("avg-cpu: %user %nice %system %iowait %steal %idle"); | 266 | puts("avg-cpu: %user %nice %system %iowait %steal %idle"); |
266 | 267 | ||
267 | /* Print current statistics */ | 268 | /* Print current statistics */ |
268 | print_stats_cpu_struct(last, cur, itv); | 269 | print_stats_cpu_struct(stats); |
269 | } | 270 | } |
270 | 271 | ||
271 | static void print_devstat_header(void) | 272 | static void print_devstat_header(void) |
272 | { | 273 | { |
273 | printf("Device: tps"); | 274 | printf("Device:%15s%6s%s/s%6s%s/s%6s%s%6s%s\n", "tps", |
274 | 275 | G.unit.str, "_read", G.unit.str, "_wrtn", | |
275 | if (option_mask32 & OPT_m) | 276 | G.unit.str, "_read", G.unit.str, "_wrtn"); |
276 | puts(" MB_read/s MB_wrtn/s MB_read MB_wrtn"); | ||
277 | else if (option_mask32 & OPT_k) | ||
278 | puts(" kB_read/s kB_wrtn/s kB_read kB_wrtn"); | ||
279 | else | ||
280 | puts(" Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn"); | ||
281 | } | 277 | } |
282 | 278 | ||
283 | /* | 279 | /* |
@@ -289,37 +285,6 @@ static int is_partition(const char *dev) | |||
289 | return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]); | 285 | return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]); |
290 | } | 286 | } |
291 | 287 | ||
292 | /* | ||
293 | * Return number of numbers on cmdline. | ||
294 | * Reasonable values are only 0 (no interval/count specified), | ||
295 | * 1 (interval specified) and 2 (both interval and count specified) | ||
296 | */ | ||
297 | static int numbers_on_cmdline(int argc, char *argv[]) | ||
298 | { | ||
299 | int sum = 0; | ||
300 | |||
301 | if (isdigit(argv[argc-1][0])) | ||
302 | sum++; | ||
303 | if (argc > 2 && isdigit(argv[argc-2][0])) | ||
304 | sum++; | ||
305 | |||
306 | return sum; | ||
307 | } | ||
308 | |||
309 | static int is_dev_in_dlist(const char *dev) | ||
310 | { | ||
311 | int i; | ||
312 | |||
313 | /* Go through the device list */ | ||
314 | for (i = 0; i < G.devlist_i; i++) | ||
315 | if (strcmp(G.dlist[i].dname, dev) == 0) | ||
316 | /* Found a match */ | ||
317 | return 1; | ||
318 | |||
319 | /* No match found */ | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static void do_disk_statistics(cputime_t itv) | 288 | static void do_disk_statistics(cputime_t itv) |
324 | { | 289 | { |
325 | FILE *fp; | 290 | FILE *fp; |
@@ -356,7 +321,7 @@ static void do_disk_statistics(cputime_t itv) | |||
356 | break; | 321 | break; |
357 | } | 322 | } |
358 | 323 | ||
359 | if (!G.devlist_i && !is_partition(sd.dname)) { | 324 | if (!G.dev_list && !is_partition(sd.dname)) { |
360 | /* User didn't specify device */ | 325 | /* User didn't specify device */ |
361 | if (!G.show_all && !sd.rd_ops && !sd.wr_ops) { | 326 | if (!G.show_all && !sd.rd_ops && !sd.wr_ops) { |
362 | /* Don't print unused device */ | 327 | /* Don't print unused device */ |
@@ -367,7 +332,7 @@ static void do_disk_statistics(cputime_t itv) | |||
367 | i++; | 332 | i++; |
368 | } else { | 333 | } else { |
369 | /* Is device in device list? */ | 334 | /* Is device in device list? */ |
370 | if (is_dev_in_dlist(sd.dname)) { | 335 | if (llist_find_str(G.dev_list, sd.dname)) { |
371 | /* Print current statistics */ | 336 | /* Print current statistics */ |
372 | print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); | 337 | print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); |
373 | G.saved_stats_dev[i] = sd; | 338 | G.saved_stats_dev[i] = sd; |
@@ -389,28 +354,6 @@ static void dev_report(cputime_t itv) | |||
389 | do_disk_statistics(itv); | 354 | do_disk_statistics(itv); |
390 | } | 355 | } |
391 | 356 | ||
392 | static void save_to_devlist(const char *dname) | ||
393 | { | ||
394 | int i; | ||
395 | struct device_list *tmp = G.dlist; | ||
396 | |||
397 | if (strncmp(dname, "/dev/", 5) == 0) | ||
398 | /* We'll ignore prefix '/dev/' */ | ||
399 | dname += 5; | ||
400 | |||
401 | /* Go through the list */ | ||
402 | for (i = 0; i < G.devlist_i; i++, tmp++) | ||
403 | if (strcmp(tmp->dname, dname) == 0) | ||
404 | /* Already in the list */ | ||
405 | return; | ||
406 | |||
407 | /* Add device name to the list */ | ||
408 | strncpy(tmp->dname, dname, MAX_DEVICE_NAME - 1); | ||
409 | |||
410 | /* Update device list index */ | ||
411 | G.devlist_i++; | ||
412 | } | ||
413 | |||
414 | static unsigned get_number_of_devices(void) | 357 | static unsigned get_number_of_devices(void) |
415 | { | 358 | { |
416 | FILE *fp; | 359 | FILE *fp; |
@@ -440,18 +383,6 @@ static unsigned get_number_of_devices(void) | |||
440 | return n; | 383 | return n; |
441 | } | 384 | } |
442 | 385 | ||
443 | static int number_of_ALL_on_cmdline(char **argv) | ||
444 | { | ||
445 | int alls = 0; | ||
446 | |||
447 | /* Iterate over cmd line arguments, count "ALL" */ | ||
448 | while (*argv) | ||
449 | if (strcmp(*argv++, "ALL") == 0) | ||
450 | alls++; | ||
451 | |||
452 | return alls; | ||
453 | } | ||
454 | |||
455 | //usage:#define iostat_trivial_usage | 386 | //usage:#define iostat_trivial_usage |
456 | //usage: "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]" | 387 | //usage: "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]" |
457 | //usage:#define iostat_full_usage "\n\n" | 388 | //usage:#define iostat_full_usage "\n\n" |
@@ -465,19 +396,17 @@ static int number_of_ALL_on_cmdline(char **argv) | |||
465 | //usage: "\n -m Use Mb/s" | 396 | //usage: "\n -m Use Mb/s" |
466 | 397 | ||
467 | int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 398 | int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
468 | int iostat_main(int argc, char **argv) | 399 | int iostat_main(int argc UNUSED_PARAM, char **argv) |
469 | { | 400 | { |
470 | int opt, dev_num; | 401 | int opt, dev_num; |
471 | unsigned interval = 0; | 402 | unsigned interval; |
472 | int count; | 403 | int count; |
473 | cputime_t global_uptime[2] = { 0 }; | 404 | stats_cpu_t stats_data[2]; |
474 | cputime_t smp_uptime[2] = { 0 }; | 405 | smallint current_stats; |
475 | cputime_t itv; | ||
476 | struct stats_cpu stats_cur, stats_last; | ||
477 | 406 | ||
478 | INIT_G(); | 407 | INIT_G(); |
479 | 408 | ||
480 | memset(&stats_last, 0, sizeof(stats_last)); | 409 | memset(&stats_data, 0, sizeof(stats_data)); |
481 | 410 | ||
482 | /* Get number of clock ticks per sec */ | 411 | /* Get number of clock ticks per sec */ |
483 | G.clk_tck = get_user_hz(); | 412 | G.clk_tck = get_user_hz(); |
@@ -496,26 +425,24 @@ int iostat_main(int argc, char **argv) | |||
496 | opt |= OPT_c + OPT_d; | 425 | opt |= OPT_c + OPT_d; |
497 | 426 | ||
498 | argv += optind; | 427 | argv += optind; |
499 | argc -= optind; | ||
500 | |||
501 | dev_num = argc - numbers_on_cmdline(argc, argv); | ||
502 | /* We don't want to allocate space for 'ALL' */ | ||
503 | dev_num -= number_of_ALL_on_cmdline(argv); | ||
504 | if (dev_num > 0) | ||
505 | /* Make space for device list */ | ||
506 | G.dlist = xzalloc(sizeof(G.dlist[0]) * dev_num); | ||
507 | 428 | ||
508 | /* Store device names into device list */ | 429 | /* Store device names into device list */ |
430 | dev_num = 0; | ||
509 | while (*argv && !isdigit(*argv[0])) { | 431 | while (*argv && !isdigit(*argv[0])) { |
510 | if (strcmp(*argv, "ALL") != 0) { | 432 | if (strcmp(*argv, "ALL") != 0) { |
511 | /* If not ALL, save device name */ | 433 | /* If not ALL, save device name */ |
512 | save_to_devlist(*argv); | 434 | char *dev_name = skip_dev_pfx(*argv); |
435 | if (!llist_find_str(G.dev_list, dev_name)) { | ||
436 | llist_add_to(&G.dev_list, dev_name); | ||
437 | dev_num++; | ||
438 | } | ||
513 | } else { | 439 | } else { |
514 | G.show_all = 1; | 440 | G.show_all = 1; |
515 | } | 441 | } |
516 | argv++; | 442 | argv++; |
517 | } | 443 | } |
518 | 444 | ||
445 | interval = 0; | ||
519 | count = 1; | 446 | count = 1; |
520 | if (*argv) { | 447 | if (*argv) { |
521 | /* Get interval */ | 448 | /* Get interval */ |
@@ -534,28 +461,46 @@ int iostat_main(int argc, char **argv) | |||
534 | ); | 461 | ); |
535 | } | 462 | } |
536 | 463 | ||
464 | if (opt & OPT_m) { | ||
465 | G.unit.str = " MB"; | ||
466 | G.unit.div = 2048; | ||
467 | } | ||
468 | |||
469 | if (opt & OPT_k) { | ||
470 | G.unit.str = " kB"; | ||
471 | G.unit.div = 2; | ||
472 | } | ||
473 | |||
474 | get_localtime(&G.tmtime); | ||
475 | |||
537 | /* Display header */ | 476 | /* Display header */ |
538 | print_header(); | 477 | print_header(); |
539 | 478 | ||
479 | current_stats = 0; | ||
540 | /* Main loop */ | 480 | /* Main loop */ |
541 | for (;;) { | 481 | for (;;) { |
482 | stats_cpu_pair_t stats; | ||
483 | |||
484 | stats.prev = &stats_data[current_stats ^ 1]; | ||
485 | stats.curr = &stats_data[current_stats]; | ||
486 | |||
542 | /* Fill the time structure */ | 487 | /* Fill the time structure */ |
543 | get_localtime(&G.tmtime); | 488 | get_localtime(&G.tmtime); |
544 | 489 | ||
545 | /* Fetch current CPU statistics */ | 490 | /* Fetch current CPU statistics */ |
546 | get_cpu_statistics(&stats_cur); | 491 | get_cpu_statistics(stats.curr); |
547 | |||
548 | /* Fetch current uptime */ | ||
549 | global_uptime[CURRENT] = get_uptime(&stats_cur); | ||
550 | 492 | ||
551 | /* Get interval */ | 493 | /* Get interval */ |
552 | itv = get_interval(global_uptime[LAST], global_uptime[CURRENT]); | 494 | stats.itv = get_interval( |
495 | stats.prev->vector[GLOBAL_UPTIME], | ||
496 | stats.curr->vector[GLOBAL_UPTIME] | ||
497 | ); | ||
553 | 498 | ||
554 | if (opt & OPT_t) | 499 | if (opt & OPT_t) |
555 | print_timestamp(); | 500 | print_timestamp(); |
556 | 501 | ||
557 | if (opt & OPT_c) { | 502 | if (opt & OPT_c) { |
558 | cpu_report(&stats_last, &stats_cur, itv); | 503 | cpu_report(&stats); |
559 | if (opt & OPT_d) | 504 | if (opt & OPT_d) |
560 | /* Separate outputs by a newline */ | 505 | /* Separate outputs by a newline */ |
561 | bb_putchar('\n'); | 506 | bb_putchar('\n'); |
@@ -563,32 +508,31 @@ int iostat_main(int argc, char **argv) | |||
563 | 508 | ||
564 | if (opt & OPT_d) { | 509 | if (opt & OPT_d) { |
565 | if (this_is_smp()) { | 510 | if (this_is_smp()) { |
566 | smp_uptime[CURRENT] = get_smp_uptime(); | 511 | stats.itv = get_interval( |
567 | itv = get_interval(smp_uptime[LAST], smp_uptime[CURRENT]); | 512 | stats.prev->vector[SMP_UPTIME], |
568 | smp_uptime[LAST] = smp_uptime[CURRENT]; | 513 | stats.curr->vector[SMP_UPTIME] |
514 | ); | ||
569 | } | 515 | } |
570 | dev_report(itv); | 516 | dev_report(stats.itv); |
571 | } | 517 | } |
572 | 518 | ||
519 | bb_putchar('\n'); | ||
520 | |||
573 | if (count > 0) { | 521 | if (count > 0) { |
574 | if (--count == 0) | 522 | if (--count == 0) |
575 | break; | 523 | break; |
576 | } | 524 | } |
577 | 525 | ||
578 | /* Backup current stats */ | 526 | /* Swap stats */ |
579 | global_uptime[LAST] = global_uptime[CURRENT]; | 527 | current_stats ^= 1; |
580 | stats_last = stats_cur; | ||
581 | 528 | ||
582 | bb_putchar('\n'); | ||
583 | sleep(interval); | 529 | sleep(interval); |
584 | } | 530 | } |
585 | 531 | ||
586 | bb_putchar('\n'); | ||
587 | |||
588 | if (ENABLE_FEATURE_CLEAN_UP) { | 532 | if (ENABLE_FEATURE_CLEAN_UP) { |
589 | free(&G); | 533 | llist_free(G.dev_list, NULL); |
590 | free(G.dlist); | ||
591 | free(G.saved_stats_dev); | 534 | free(G.saved_stats_dev); |
535 | free(&G); | ||
592 | } | 536 | } |
593 | 537 | ||
594 | return EXIT_SUCCESS; | 538 | return EXIT_SUCCESS; |