aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Kryzhanovskyy <xmaks@email.cz>2011-06-05 03:37:14 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-06-05 03:37:14 +0200
commit9f7780250ce4bbee9c0a8f1044875e303479e196 (patch)
tree88d314931dbe8f7a4c89821bfbb3aefc40220670
parent5d3aaceb790461dca3f770483bbccd161e78a728 (diff)
downloadbusybox-w32-9f7780250ce4bbee9c0a8f1044875e303479e196.tar.gz
busybox-w32-9f7780250ce4bbee9c0a8f1044875e303479e196.tar.bz2
busybox-w32-9f7780250ce4bbee9c0a8f1044875e303479e196.zip
iostat: code shrink
function old new delta iostat_main 2048 2400 +352 is_partition 48 - -48 print_stats_dev_struct 350 - -350 Signed-off-by: Maksym Kryzhanovskyy <xmaks@email.cz> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--procps/iostat.c237
1 files changed, 117 insertions, 120 deletions
diff --git a/procps/iostat.c b/procps/iostat.c
index cd233c72f..51c5fac08 100644
--- a/procps/iostat.c
+++ b/procps/iostat.c
@@ -7,23 +7,24 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9 9
10//applet:IF_IOSTAT(APPLET(iostat, BB_DIR_BIN, BB_SUID_DROP))
11
12//kbuild:lib-$(CONFIG_IOSTAT) += iostat.o
13
14//config:config IOSTAT 10//config:config IOSTAT
15//config: bool "iostat" 11//config: bool "iostat"
16//config: default y 12//config: default y
17//config: help 13//config: help
18//config: Report CPU and I/O statistics 14//config: Report CPU and I/O statistics
19 15
16//applet:IF_IOSTAT(APPLET(iostat, BB_DIR_BIN, BB_SUID_DROP))
17
18//kbuild:lib-$(CONFIG_IOSTAT) += iostat.o
19
20#include "libbb.h" 20#include "libbb.h"
21#include <sys/utsname.h> /* Need struct utsname */ 21#include <sys/utsname.h> /* struct utsname */
22 22
23//#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) 23//#define debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
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 MAX_DEVICE_NAME_STR "12"
27 28
28#if 1 29#if 1
29typedef unsigned long long cputime_t; 30typedef unsigned long long cputime_t;
@@ -64,21 +65,27 @@ typedef struct {
64 cputime_t itv; 65 cputime_t itv;
65} stats_cpu_pair_t; 66} stats_cpu_pair_t;
66 67
67struct stats_dev { 68typedef struct {
68 char dname[MAX_DEVICE_NAME];
69 unsigned long long rd_sectors; 69 unsigned long long rd_sectors;
70 unsigned long long wr_sectors; 70 unsigned long long wr_sectors;
71 unsigned long rd_ops; 71 unsigned long rd_ops;
72 unsigned long wr_ops; 72 unsigned long wr_ops;
73}; 73} stats_dev_data_t;
74
75typedef struct stats_dev {
76 struct stats_dev *next;
77 char dname[MAX_DEVICE_NAME + 1];
78 stats_dev_data_t prev_data;
79 stats_dev_data_t curr_data;
80} stats_dev_t;
74 81
75/* Globals. Sort by size and access frequency. */ 82/* Globals. Sort by size and access frequency. */
76struct globals { 83struct globals {
77 smallint show_all; 84 smallint show_all;
78 unsigned total_cpus; /* Number of CPUs */ 85 unsigned total_cpus; /* Number of CPUs */
79 unsigned clk_tck; /* Number of clock ticks per second */ 86 unsigned clk_tck; /* Number of clock ticks per second */
80 llist_t *dev_list; /* List of devices entered on the command line */ 87 llist_t *dev_name_list; /* List of devices entered on the command line */
81 struct stats_dev *saved_stats_dev; 88 stats_dev_t *stats_dev_list;
82 struct tm tmtime; 89 struct tm tmtime;
83 struct { 90 struct {
84 const char *str; 91 const char *str;
@@ -114,7 +121,7 @@ static ALWAYS_INLINE int this_is_smp(void)
114 121
115static void print_header(void) 122static void print_header(void)
116{ 123{
117 char buf[16]; 124 char buf[32];
118 struct utsname uts; 125 struct utsname uts;
119 126
120 uname(&uts); /* never fails */ 127 uname(&uts); /* never fails */
@@ -136,7 +143,7 @@ static void get_localtime(struct tm *ptm)
136 143
137static void print_timestamp(void) 144static void print_timestamp(void)
138{ 145{
139 char buf[20]; 146 char buf[64];
140 /* %x: date representation for the current locale */ 147 /* %x: date representation for the current locale */
141 /* %X: time representation for the current locale */ 148 /* %X: time representation for the current locale */
142 strftime(buf, sizeof(buf), "%x %X", &G.tmtime); 149 strftime(buf, sizeof(buf), "%x %X", &G.tmtime);
@@ -162,18 +169,22 @@ static cputime_t get_smp_uptime(void)
162static void get_cpu_statistics(stats_cpu_t *sc) 169static void get_cpu_statistics(stats_cpu_t *sc)
163{ 170{
164 FILE *fp; 171 FILE *fp;
165 char buf[1024], *ibuf = buf + 4; 172 char buf[1024];
166 173
167 fp = xfopen_for_read("/proc/stat"); 174 fp = xfopen_for_read("/proc/stat");
168 175
169 memset(sc, 0, sizeof(*sc)); 176 memset(sc, 0, sizeof(*sc));
170 177
171 while (fgets(buf, sizeof(buf), fp)) { 178 while (fgets(buf, sizeof(buf), fp)) {
172 /* Does the line starts with "cpu "? */ 179 int i;
180 char *ibuf;
181
182 /* Does the line start with "cpu "? */
173 if (!starts_with_cpu(buf) || buf[3] != ' ') { 183 if (!starts_with_cpu(buf) || buf[3] != ' ') {
174 continue; 184 continue;
175 } 185 }
176 for (int i = STATS_CPU_USER; i <= STATS_CPU_GUEST; i++) { 186 ibuf = buf + 4;
187 for (i = STATS_CPU_USER; i <= STATS_CPU_GUEST; i++) {
177 ibuf = skip_whitespace(ibuf); 188 ibuf = skip_whitespace(ibuf);
178 sscanf(ibuf, "%"FMT_DATA"u", &sc->vector[i]); 189 sscanf(ibuf, "%"FMT_DATA"u", &sc->vector[i]);
179 if (i != STATS_CPU_GUEST) { 190 if (i != STATS_CPU_GUEST) {
@@ -233,7 +244,7 @@ static void print_stats_cpu_struct(stats_cpu_pair_t *stats)
233{ 244{
234 cputime_t *p = stats->prev->vector; 245 cputime_t *p = stats->prev->vector;
235 cputime_t *c = stats->curr->vector; 246 cputime_t *c = stats->curr->vector;
236 printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n", 247 printf(" %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f\n",
237 percent_value(p[STATS_CPU_USER] , c[STATS_CPU_USER] , stats->itv), 248 percent_value(p[STATS_CPU_USER] , c[STATS_CPU_USER] , stats->itv),
238 percent_value(p[STATS_CPU_NICE] , c[STATS_CPU_NICE] , stats->itv), 249 percent_value(p[STATS_CPU_NICE] , c[STATS_CPU_NICE] , stats->itv),
239 percent_value(p[STATS_CPU_SYSTEM] + p[STATS_CPU_SOFTIRQ] + p[STATS_CPU_IRQ], 250 percent_value(p[STATS_CPU_SYSTEM] + p[STATS_CPU_SOFTIRQ] + p[STATS_CPU_IRQ],
@@ -244,36 +255,40 @@ static void print_stats_cpu_struct(stats_cpu_pair_t *stats)
244 ); 255 );
245} 256}
246 257
247static void print_stats_dev_struct(const struct stats_dev *p, 258static void cpu_report(stats_cpu_pair_t *stats)
248 const struct stats_dev *c, cputime_t itv)
249{ 259{
260 /* Always print a header */
261 puts("avg-cpu: %user %nice %system %iowait %steal %idle");
262
263 /* Print current statistics */
264 print_stats_cpu_struct(stats);
265}
266
267static void print_stats_dev_struct(stats_dev_t *stats_dev, cputime_t itv)
268{
269 stats_dev_data_t *p = &stats_dev->prev_data;
270 stats_dev_data_t *c = &stats_dev->curr_data;
250 if (option_mask32 & OPT_z) 271 if (option_mask32 & OPT_z)
251 if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops) 272 if (p->rd_ops == c->rd_ops && p->wr_ops == c->wr_ops)
252 return; 273 return;
253 274
254 printf("%-13s %8.2f %12.2f %12.2f %10llu %10llu \n", c->dname, 275 printf("%-13s %8.2f %12.2f %12.2f %10llu %10llu\n",
255 percent_value(p->rd_ops + p->wr_ops , 276 stats_dev->dname,
256 /**/ c->rd_ops + c->wr_ops , itv), 277 percent_value(p->rd_ops + p->wr_ops, c->rd_ops + c->wr_ops, itv),
257 percent_value(p->rd_sectors, c->rd_sectors, itv) / G.unit.div, 278 percent_value(p->rd_sectors, c->rd_sectors, itv) / G.unit.div,
258 percent_value(p->wr_sectors, c->wr_sectors, itv) / G.unit.div, 279 percent_value(p->wr_sectors, c->wr_sectors, itv) / G.unit.div,
259 (c->rd_sectors - p->rd_sectors) / G.unit.div, 280 (c->rd_sectors - p->rd_sectors) / G.unit.div,
260 (c->wr_sectors - p->wr_sectors) / G.unit.div); 281 (c->wr_sectors - p->wr_sectors) / G.unit.div
261} 282 );
262
263static void cpu_report(stats_cpu_pair_t *stats)
264{
265 /* Always print a header */
266 puts("avg-cpu: %user %nice %system %iowait %steal %idle");
267
268 /* Print current statistics */
269 print_stats_cpu_struct(stats);
270} 283}
271 284
272static void print_devstat_header(void) 285static void print_devstat_header(void)
273{ 286{
274 printf("Device:%15s%6s%s/s%6s%s/s%6s%s%6s%s\n", "tps", 287 printf("Device:%15s%6s%s/s%6s%s/s%6s%s%6s%s\n",
288 "tps",
275 G.unit.str, "_read", G.unit.str, "_wrtn", 289 G.unit.str, "_read", G.unit.str, "_wrtn",
276 G.unit.str, "_read", G.unit.str, "_wrtn"); 290 G.unit.str, "_read", G.unit.str, "_wrtn"
291 );
277} 292}
278 293
279/* 294/*
@@ -285,61 +300,81 @@ static int is_partition(const char *dev)
285 return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]); 300 return ((dev[0] - 's') | (dev[1] - 'd') | (dev[2] - 'a')) == 0 && isdigit(dev[3]);
286} 301}
287 302
303static stats_dev_t *stats_dev_find_or_new(const char *dev_name)
304{
305 stats_dev_t **curr = &G.stats_dev_list;
306
307 while (*curr != NULL) {
308 if (strcmp((*curr)->dname, dev_name) == 0)
309 return *curr;
310 curr = &(*curr)->next;
311 }
312
313 *curr = xzalloc(sizeof(stats_dev_t));
314 strncpy((*curr)->dname, dev_name, MAX_DEVICE_NAME);
315 return *curr;
316}
317
318static void stats_dev_free(stats_dev_t *stats_dev)
319{
320 if (stats_dev) {
321 stats_dev_free(stats_dev->next);
322 free(stats_dev);
323 }
324}
325
288static void do_disk_statistics(cputime_t itv) 326static void do_disk_statistics(cputime_t itv)
289{ 327{
328 char buf[128];
329 char dev_name[MAX_DEVICE_NAME + 1];
330 unsigned long long rd_sec_or_dummy;
331 unsigned long long wr_sec_or_dummy;
332 stats_dev_data_t *curr_data;
333 stats_dev_t *stats_dev;
290 FILE *fp; 334 FILE *fp;
291 int rc; 335 int rc;
292 int i = 0;
293 char buf[128];
294 unsigned major, minor;
295 unsigned long wr_ops, dummy; /* %*lu for suppress the conversion wouldn't work */
296 unsigned long long rd_sec_or_wr_ops;
297 unsigned long long rd_sec_or_dummy, wr_sec_or_dummy, wr_sec;
298 struct stats_dev sd;
299 336
300 fp = xfopen_for_read("/proc/diskstats"); 337 fp = xfopen_for_read("/proc/diskstats");
301
302 /* Read and possibly print stats from /proc/diskstats */ 338 /* Read and possibly print stats from /proc/diskstats */
303 while (fgets(buf, sizeof(buf), fp)) { 339 while (fgets(buf, sizeof(buf), fp)) {
304 rc = sscanf(buf, "%u %u %s %lu %llu %llu %llu %lu %lu %llu %lu %lu %lu %lu", 340 sscanf(buf, "%*s %*s %"MAX_DEVICE_NAME_STR"s", dev_name);
305 &major, &minor, sd.dname, &sd.rd_ops, 341 if (G.dev_name_list) {
306 &rd_sec_or_dummy, &rd_sec_or_wr_ops, &wr_sec_or_dummy, 342 /* Is device name in list? */
307 &wr_ops, &dummy, &wr_sec, &dummy, &dummy, &dummy, &dummy); 343 if (!llist_find_str(G.dev_name_list, dev_name))
308 344 continue;
309 switch (rc) { 345 } else if (is_partition(dev_name)) {
310 case 14: 346 continue;
311 sd.wr_ops = wr_ops;
312 sd.rd_sectors = rd_sec_or_wr_ops;
313 sd.wr_sectors = wr_sec;
314 break;
315 case 7:
316 sd.rd_sectors = rd_sec_or_dummy;
317 sd.wr_ops = (unsigned long)rd_sec_or_wr_ops;
318 sd.wr_sectors = wr_sec_or_dummy;
319 break;
320 default:
321 break;
322 } 347 }
323 348
324 if (!G.dev_list && !is_partition(sd.dname)) { 349 stats_dev = stats_dev_find_or_new(dev_name);
325 /* User didn't specify device */ 350 curr_data = &stats_dev->curr_data;
326 if (!G.show_all && !sd.rd_ops && !sd.wr_ops) { 351
327 /* Don't print unused device */ 352 rc = sscanf(buf, "%*s %*s %*s %lu %llu %llu %llu %lu %*s %llu",
328 continue; 353 &curr_data->rd_ops,
329 } 354 &rd_sec_or_dummy,
330 print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); 355 &curr_data->rd_sectors,
331 G.saved_stats_dev[i] = sd; 356 &wr_sec_or_dummy,
332 i++; 357 &curr_data->wr_ops,
333 } else { 358 &curr_data->wr_sectors);
334 /* Is device in device list? */ 359 if (rc != 6) {
335 if (llist_find_str(G.dev_list, sd.dname)) { 360 curr_data->rd_sectors = rd_sec_or_dummy;
336 /* Print current statistics */ 361 curr_data->wr_sectors = wr_sec_or_dummy;
337 print_stats_dev_struct(&G.saved_stats_dev[i], &sd, itv); 362 //curr_data->rd_ops = ;
338 G.saved_stats_dev[i] = sd; 363 curr_data->wr_ops = (unsigned long)curr_data->rd_sectors;
339 i++;
340 } else
341 continue;
342 } 364 }
365
366 if (!G.dev_name_list /* User didn't specify device */
367 && !G.show_all
368 && curr_data->rd_ops == 0
369 && curr_data->wr_ops == 0
370 ) {
371 /* Don't print unused device */
372 continue;
373 }
374
375 /* Print current statistics */
376 print_stats_dev_struct(stats_dev, itv);
377 stats_dev->prev_data = *curr_data;
343 } 378 }
344 379
345 fclose(fp); 380 fclose(fp);
@@ -354,35 +389,6 @@ static void dev_report(cputime_t itv)
354 do_disk_statistics(itv); 389 do_disk_statistics(itv);
355} 390}
356 391
357static unsigned get_number_of_devices(void)
358{
359 FILE *fp;
360 char buf[128];
361 int rv;
362 unsigned n = 0;
363 unsigned long rd_ops, wr_ops;
364 char dname[MAX_DEVICE_NAME];
365
366 fp = xfopen_for_read("/proc/diskstats");
367
368 while (fgets(buf, sizeof(buf), fp)) {
369 rv = sscanf(buf, "%*d %*d %s %lu %*u %*u %*u %lu",
370 dname, &rd_ops, &wr_ops);
371 if (rv == 2 || is_partition(dname))
372 /* A partition */
373 continue;
374 if (!rd_ops && !wr_ops) {
375 /* Unused device */
376 if (!G.show_all)
377 continue;
378 }
379 n++;
380 }
381
382 fclose(fp);
383 return n;
384}
385
386//usage:#define iostat_trivial_usage 392//usage:#define iostat_trivial_usage
387//usage: "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]" 393//usage: "[-c] [-d] [-t] [-z] [-k|-m] [ALL|BLOCKDEV...] [INTERVAL [COUNT]]"
388//usage:#define iostat_full_usage "\n\n" 394//usage:#define iostat_full_usage "\n\n"
@@ -398,7 +404,7 @@ static unsigned get_number_of_devices(void)
398int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 404int iostat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
399int iostat_main(int argc UNUSED_PARAM, char **argv) 405int iostat_main(int argc UNUSED_PARAM, char **argv)
400{ 406{
401 int opt, dev_num; 407 int opt;
402 unsigned interval; 408 unsigned interval;
403 int count; 409 int count;
404 stats_cpu_t stats_data[2]; 410 stats_cpu_t stats_data[2];
@@ -427,14 +433,12 @@ int iostat_main(int argc UNUSED_PARAM, char **argv)
427 argv += optind; 433 argv += optind;
428 434
429 /* Store device names into device list */ 435 /* Store device names into device list */
430 dev_num = 0;
431 while (*argv && !isdigit(*argv[0])) { 436 while (*argv && !isdigit(*argv[0])) {
432 if (strcmp(*argv, "ALL") != 0) { 437 if (strcmp(*argv, "ALL") != 0) {
433 /* If not ALL, save device name */ 438 /* If not ALL, save device name */
434 char *dev_name = skip_dev_pfx(*argv); 439 char *dev_name = skip_dev_pfx(*argv);
435 if (!llist_find_str(G.dev_list, dev_name)) { 440 if (!llist_find_str(G.dev_name_list, dev_name)) {
436 llist_add_to(&G.dev_list, dev_name); 441 llist_add_to(&G.dev_name_list, dev_name);
437 dev_num++;
438 } 442 }
439 } else { 443 } else {
440 G.show_all = 1; 444 G.show_all = 1;
@@ -454,13 +458,6 @@ int iostat_main(int argc UNUSED_PARAM, char **argv)
454 count = xatoi_positive(*argv); 458 count = xatoi_positive(*argv);
455 } 459 }
456 460
457 /* Allocate space for device stats */
458 if (opt & OPT_d) {
459 G.saved_stats_dev = xzalloc(sizeof(G.saved_stats_dev[0]) *
460 (dev_num ? dev_num : get_number_of_devices())
461 );
462 }
463
464 if (opt & OPT_m) { 461 if (opt & OPT_m) {
465 G.unit.str = " MB"; 462 G.unit.str = " MB";
466 G.unit.div = 2048; 463 G.unit.div = 2048;
@@ -530,8 +527,8 @@ int iostat_main(int argc UNUSED_PARAM, char **argv)
530 } 527 }
531 528
532 if (ENABLE_FEATURE_CLEAN_UP) { 529 if (ENABLE_FEATURE_CLEAN_UP) {
533 llist_free(G.dev_list, NULL); 530 llist_free(G.dev_name_list, NULL);
534 free(G.saved_stats_dev); 531 stats_dev_free(G.stats_dev_list);
535 free(&G); 532 free(&G);
536 } 533 }
537 534