perfmonger 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +6 -0
  3. data/.tachikoma.yml +1 -0
  4. data/.travis.yml +18 -6
  5. data/Gemfile +1 -3
  6. data/Guardfile +26 -0
  7. data/NEWS +21 -0
  8. data/README.md +8 -9
  9. data/Rakefile +33 -1
  10. data/core/Makefile +23 -0
  11. data/core/build.sh +48 -0
  12. data/core/perfmonger-player.go +165 -0
  13. data/core/perfmonger-recorder.go +296 -0
  14. data/core/perfmonger-summarizer.go +207 -0
  15. data/core/subsystem/Makefile +3 -0
  16. data/core/subsystem/perfmonger.go +60 -0
  17. data/core/subsystem/perfmonger_darwin.go +22 -0
  18. data/core/subsystem/perfmonger_linux.go +292 -0
  19. data/core/subsystem/perfmonger_linux_test.go +73 -0
  20. data/core/subsystem/stat.go +214 -0
  21. data/core/subsystem/stat_test.go +281 -0
  22. data/core/subsystem/usage.go +410 -0
  23. data/core/subsystem/usage_test.go +496 -0
  24. data/lib/exec/operationBinding.rb.svn-base +59 -0
  25. data/lib/exec/perfmonger-player_darwin_amd64 +0 -0
  26. data/lib/exec/perfmonger-player_linux_386 +0 -0
  27. data/lib/exec/perfmonger-player_linux_amd64 +0 -0
  28. data/lib/exec/perfmonger-recorder_darwin_amd64 +0 -0
  29. data/lib/exec/perfmonger-recorder_linux_386 +0 -0
  30. data/lib/exec/perfmonger-recorder_linux_amd64 +0 -0
  31. data/lib/exec/perfmonger-summarizer_darwin_amd64 +0 -0
  32. data/lib/exec/perfmonger-summarizer_linux_386 +0 -0
  33. data/lib/exec/perfmonger-summarizer_linux_amd64 +0 -0
  34. data/lib/exec/perfmonger-summary_linux_386 +0 -0
  35. data/lib/exec/perfmonger-summary_linux_amd64 +0 -0
  36. data/lib/perfmonger/cli.rb +8 -3
  37. data/lib/perfmonger/command/core.rb +62 -0
  38. data/lib/perfmonger/command/live.rb +39 -0
  39. data/lib/perfmonger/command/play.rb +56 -0
  40. data/lib/perfmonger/command/plot.rb +30 -22
  41. data/lib/perfmonger/command/record.rb +3 -2
  42. data/lib/perfmonger/command/record_option.rb +40 -59
  43. data/lib/perfmonger/command/server.rb +7 -2
  44. data/lib/perfmonger/command/stat.rb +2 -2
  45. data/lib/perfmonger/command/stat_option.rb +1 -1
  46. data/lib/perfmonger/command/summary.rb +11 -326
  47. data/lib/perfmonger/version.rb +1 -3
  48. data/lib/perfmonger.rb +3 -0
  49. data/misc/_perfmonger +128 -0
  50. data/misc/perfmonger-completion.bash +49 -0
  51. data/perfmonger.gemspec +6 -5
  52. data/spec/data/busy100.pgr +0 -0
  53. data/spec/fingerprint_spec.rb +35 -0
  54. data/spec/live_spec.rb +25 -0
  55. data/spec/perfmonger_spec.rb +37 -0
  56. data/spec/play_spec.rb +21 -0
  57. data/spec/plot_spec.rb +42 -0
  58. data/spec/record_spec.rb +15 -0
  59. data/spec/spec_helper.rb +33 -0
  60. data/spec/stat_spec.rb +15 -0
  61. data/spec/summary_spec.rb +51 -0
  62. data/spec/support/aruba.rb +11 -0
  63. data/wercker.yml +59 -0
  64. metadata +117 -45
  65. data/ext/perfmonger/extconf.rb +0 -19
  66. data/ext/perfmonger/perfmonger.h +0 -58
  67. data/ext/perfmonger/perfmonger_record.c +0 -754
  68. data/ext/perfmonger/sysstat/common.c +0 -627
  69. data/ext/perfmonger/sysstat/common.h +0 -207
  70. data/ext/perfmonger/sysstat/ioconf.c +0 -515
  71. data/ext/perfmonger/sysstat/ioconf.h +0 -84
  72. data/ext/perfmonger/sysstat/iostat.c +0 -1100
  73. data/ext/perfmonger/sysstat/iostat.h +0 -121
  74. data/ext/perfmonger/sysstat/libsysstat.h +0 -19
  75. data/ext/perfmonger/sysstat/mpstat.c +0 -953
  76. data/ext/perfmonger/sysstat/mpstat.h +0 -79
  77. data/ext/perfmonger/sysstat/rd_stats.c +0 -2388
  78. data/ext/perfmonger/sysstat/rd_stats.h +0 -651
  79. data/ext/perfmonger/sysstat/sysconfig.h +0 -13
  80. data/test/run-test.sh +0 -39
  81. data/test/spec/bin_spec.rb +0 -37
  82. data/test/spec/data/2devices.expected +0 -42
  83. data/test/spec/data/2devices.output +0 -42
  84. data/test/spec/spec_helper.rb +0 -20
  85. data/test/spec/summary_spec.rb +0 -193
  86. data/test/test-perfmonger.c +0 -145
  87. data/test/test.h +0 -9
@@ -1,1100 +0,0 @@
1
- /*
2
- * (C) 2011 Modified by Yuto HAYAMIZU (haya <at> tkl.iis.u-tokyo.ac.jp)
3
- */
4
-
5
- /*
6
- * iostat: report CPU and I/O statistics
7
- * (C) 1998-2010 by Sebastien GODARD (sysstat <at> orange.fr)
8
- *
9
- ***************************************************************************
10
- * This program is free software; you can redistribute it and/or modify it *
11
- * under the terms of the GNU General Public License as published by the *
12
- * Free Software Foundation; either version 2 of the License, or (at your *
13
- * option) any later version. *
14
- * *
15
- * This program is distributed in the hope that it will be useful, but *
16
- * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
17
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
18
- * for more details. *
19
- * *
20
- * You should have received a copy of the GNU General Public License along *
21
- * with this program; if not, write to the Free Software Foundation, Inc., *
22
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
23
- ***************************************************************************
24
- */
25
-
26
- #include <stdio.h>
27
- #include <string.h>
28
- #include <stdlib.h>
29
- #include <unistd.h>
30
- #include <signal.h>
31
- #include <fcntl.h>
32
- #include <errno.h>
33
- #include <time.h>
34
- #include <ctype.h>
35
- #include <dirent.h>
36
- #include <sys/types.h>
37
- #include <sys/stat.h>
38
- #include <sys/utsname.h>
39
-
40
- #include "iostat.h"
41
- #include "common.h"
42
- #include "ioconf.h"
43
- #include "rd_stats.h"
44
-
45
- #ifdef USE_NLS
46
- #include <locale.h>
47
- #include <libintl.h>
48
- #define _(string) gettext(string)
49
- #else
50
- #define _(string) (string)
51
- #endif
52
-
53
- struct stats_cpu *st_cpu[2];
54
- extern unsigned long long uptime[3]; /* defined in mpstat.c */
55
- extern unsigned long long uptime0[3]; /* defined in mpstat.c */
56
- struct io_stats *st_iodev[2];
57
- struct io_hdr_stats *st_hdr_iodev;
58
- struct io_dlist *st_dev_list;
59
-
60
- int iodev_nr = 0; /* Nb of devices and partitions found */
61
- int cpu_nr = 0; /* Nb of processors on the machine */
62
- int dlist_idx = 0; /* Nb of devices entered on the command line */
63
- int flags = 0; /* Flag for common options and system state */
64
- unsigned int dm_major; /* Device-mapper major number */
65
-
66
- long interval = 0;
67
- char timestamp[64];
68
-
69
-
70
- /*
71
- ***************************************************************************
72
- * Print usage and exit.
73
- *
74
- * IN:
75
- * @progname Name of sysstat command.
76
- ***************************************************************************
77
- */
78
- void usage(char *progname)
79
- {
80
- fprintf(stderr, _("Usage: %s [ options ] [ <interval> [ <count> ] ]\n"),
81
- progname);
82
- #ifdef DEBUG
83
- fprintf(stderr, _("Options are:\n"
84
- "[ -c ] [ -d ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ]\n"
85
- "[ <device> [...] | ALL ] [ -p [ <device> [,...] | ALL ] ] [ --debuginfo ]\n"));
86
- #else
87
- fprintf(stderr, _("Options are:\n"
88
- "[ -c ] [ -d ] [ -N ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -z ]\n"
89
- "[ <device> [...] | ALL ] [ -p [ <device> [,...] | ALL ] ]\n"));
90
- #endif
91
- exit(1);
92
- }
93
-
94
- /*
95
- ***************************************************************************
96
- * Set disk output unit. Unit will be kB/s unless POSIXLY_CORRECT
97
- * environment variable has been set, in which case the output will be
98
- * expressed in blocks/s.
99
- ***************************************************************************
100
- */
101
- void set_disk_output_unit(void)
102
- {
103
- char *e;
104
-
105
- if (DISPLAY_KILOBYTES(flags) || DISPLAY_MEGABYTES(flags))
106
- return;
107
-
108
- /* Check POSIXLY_CORRECT environment variable */
109
- if ((e = getenv(ENV_POSIXLY_CORRECT)) == NULL) {
110
- /* Variable not set: Unit is kB/s and not blocks/s */
111
- flags |= I_D_KILOBYTES;
112
- }
113
- }
114
-
115
- /*
116
- ***************************************************************************
117
- * Initialize stats common structures.
118
- ***************************************************************************
119
- */
120
- void init_stats(void)
121
- {
122
- int i;
123
-
124
- /* Allocate structures for CPUs "all" and 0 */
125
- for (i = 0; i < 2; i++) {
126
- if ((st_cpu[i] = (struct stats_cpu *) malloc(STATS_CPU_SIZE * 2)) == NULL) {
127
- perror("malloc");
128
- exit(4);
129
- }
130
- memset(st_cpu[i], 0, STATS_CPU_SIZE * 2);
131
- }
132
- }
133
-
134
- /*
135
- ***************************************************************************
136
- * Set every disk_io entry to inactive state (unregistered).
137
- *
138
- * IN:
139
- * @ioln_nr Number of devices and partitions.
140
- * @st_hdr_ioln Pointer on first structure describing a device/partition.
141
- ***************************************************************************
142
- */
143
- void set_entries_inactive(int ioln_nr, struct io_hdr_stats *st_hdr_ioln)
144
- {
145
- int i;
146
- struct io_hdr_stats *shi = st_hdr_ioln;
147
-
148
- for (i = 0; i < ioln_nr; i++, shi++) {
149
- shi->active = FALSE;
150
- }
151
- }
152
-
153
- /*
154
- ***************************************************************************
155
- * Free inactive entries (mark them as unused).
156
- *
157
- * IN:
158
- * @ioln_nr Number of devices and partitions.
159
- * @st_hdr_ioln Pointer on first structure describing a device/partition.
160
- ***************************************************************************
161
- */
162
- void free_inactive_entries(int ioln_nr, struct io_hdr_stats *st_hdr_ioln)
163
- {
164
- int i;
165
- struct io_hdr_stats *shi = st_hdr_ioln;
166
-
167
- for (i = 0; i < ioln_nr; i++, shi++) {
168
- if (!shi->active) {
169
- shi->used = FALSE;
170
- }
171
- }
172
- }
173
-
174
- /*
175
- ***************************************************************************
176
- * Allocate and init I/O device structures.
177
- *
178
- * IN:
179
- * @iodev_nr Number of devices and partitions.
180
- ***************************************************************************
181
- */
182
- void salloc_device(int iodev_nr)
183
- {
184
- int i;
185
-
186
- for (i = 0; i < 2; i++) {
187
- if ((st_iodev[i] =
188
- (struct io_stats *) malloc(IO_STATS_SIZE * iodev_nr)) == NULL) {
189
- perror("malloc");
190
- exit(4);
191
- }
192
- memset(st_iodev[i], 0, IO_STATS_SIZE * iodev_nr);
193
- }
194
-
195
- if ((st_hdr_iodev =
196
- (struct io_hdr_stats *) malloc(IO_HDR_STATS_SIZE * iodev_nr)) == NULL) {
197
- perror("malloc");
198
- exit(4);
199
- }
200
- memset(st_hdr_iodev, 0, IO_HDR_STATS_SIZE * iodev_nr);
201
- }
202
-
203
- /*
204
- ***************************************************************************
205
- * Allocate structures for devices entered on the command line.
206
- *
207
- * IN:
208
- * @list_len Number of arguments on the command line.
209
- ***************************************************************************
210
- */
211
- void salloc_dev_list(int list_len)
212
- {
213
- if ((st_dev_list = (struct io_dlist *) malloc(IO_DLIST_SIZE * list_len)) == NULL) {
214
- perror("malloc");
215
- exit(4);
216
- }
217
- memset(st_dev_list, 0, IO_DLIST_SIZE * list_len);
218
- }
219
-
220
- /*
221
- ***************************************************************************
222
- * Free structures used for devices entered on the command line.
223
- ***************************************************************************
224
- */
225
- void sfree_dev_list(void)
226
- {
227
- if (st_dev_list) {
228
- free(st_dev_list);
229
- }
230
- }
231
-
232
- /*
233
- ***************************************************************************
234
- * Look for the device in the device list and store it if necessary.
235
- *
236
- * IN:
237
- * @dlist_idx Length of the device list.
238
- * @device_name Name of the device.
239
- *
240
- * OUT:
241
- * @dlist_idx Length of the device list.
242
- *
243
- * RETURNS:
244
- * Position of the device in the list.
245
- ***************************************************************************
246
- */
247
- int update_dev_list(int *dlist_idx, char *device_name)
248
- {
249
- int i;
250
- struct io_dlist *sdli = st_dev_list;
251
-
252
- for (i = 0; i < *dlist_idx; i++, sdli++) {
253
- if (!strcmp(sdli->dev_name, device_name))
254
- break;
255
- }
256
-
257
- if (i == *dlist_idx) {
258
- /* Device not found: Store it */
259
- (*dlist_idx)++;
260
- strncpy(sdli->dev_name, device_name, MAX_NAME_LEN - 1);
261
- }
262
-
263
- return i;
264
- }
265
-
266
- /*
267
- ***************************************************************************
268
- * Allocate and init structures, according to system state.
269
- ***************************************************************************
270
- */
271
- void io_sys_init(void)
272
- {
273
- /* Allocate and init stat common counters */
274
- init_stats();
275
-
276
- /* How many processors on this machine? */
277
- cpu_nr = get_cpu_nr(~0);
278
-
279
- /* Get number of block devices and partitions in /proc/diskstats */
280
- if ((iodev_nr = get_diskstats_dev_nr(CNT_PART, CNT_ALL_DEV)) > 0) {
281
- flags |= I_F_HAS_DISKSTATS;
282
- iodev_nr += NR_DEV_PREALLOC;
283
- }
284
-
285
- if (!HAS_DISKSTATS(flags) ||
286
- (DISPLAY_PARTITIONS(flags) && !DISPLAY_PART_ALL(flags))) {
287
- /*
288
- * If /proc/diskstats exists but we also want stats for the partitions
289
- * of a particular device, stats will have to be found in /sys. So we
290
- * need to know if /sys is mounted or not, and set flags accordingly.
291
- */
292
-
293
- /* Get number of block devices (and partitions) in sysfs */
294
- if ((iodev_nr = get_sysfs_dev_nr(DISPLAY_PARTITIONS(flags))) > 0) {
295
- flags |= I_F_HAS_SYSFS;
296
- iodev_nr += NR_DEV_PREALLOC;
297
- }
298
- else {
299
- fprintf(stderr, _("Cannot find disk data\n"));
300
- exit(2);
301
- }
302
- }
303
- /*
304
- * Allocate structures for number of disks found.
305
- * iodev_nr must be <> 0.
306
- */
307
- salloc_device(iodev_nr);
308
- }
309
-
310
- /*
311
- ***************************************************************************
312
- * Free various structures.
313
- ***************************************************************************
314
- */
315
- void io_sys_free(void)
316
- {
317
- int i;
318
-
319
- for (i = 0; i < 2; i++) {
320
-
321
- /* Free CPU structures */
322
- if (st_cpu[i]) {
323
- free(st_cpu[i]);
324
- }
325
-
326
- /* Free I/O device structures */
327
- if (st_iodev[i]) {
328
- free(st_iodev[i]);
329
- }
330
- }
331
-
332
- if (st_hdr_iodev) {
333
- free(st_hdr_iodev);
334
- }
335
- }
336
-
337
- /*
338
- ***************************************************************************
339
- * Save stats for current device or partition.
340
- *
341
- * IN:
342
- * @name Name of the device/partition.
343
- * @curr Index in array for current sample statistics.
344
- * @st_io Structure with device or partition to save.
345
- * @ioln_nr Number of devices and partitions.
346
- * @st_hdr_ioln Pointer on structures describing a device/partition.
347
- *
348
- * OUT:
349
- * @st_hdr_ioln Pointer on structures describing a device/partition.
350
- ***************************************************************************
351
- */
352
- void save_stats(char *name, int curr, void *st_io, int ioln_nr,
353
- struct io_hdr_stats *st_hdr_ioln)
354
- {
355
- int i;
356
- struct io_hdr_stats *st_hdr_ioln_i;
357
- struct io_stats *st_iodev_i;
358
-
359
- /* Look for device in data table */
360
- for (i = 0; i < ioln_nr; i++) {
361
- st_hdr_ioln_i = st_hdr_ioln + i;
362
- if (!strcmp(st_hdr_ioln_i->name, name)) {
363
- break;
364
- }
365
- }
366
-
367
- if (i == ioln_nr) {
368
- /*
369
- * This is a new device: look for an unused entry to store it.
370
- * Thus we are able to handle dynamically registered devices.
371
- */
372
- for (i = 0; i < ioln_nr; i++) {
373
- st_hdr_ioln_i = st_hdr_ioln + i;
374
- if (!st_hdr_ioln_i->used) {
375
- /* Unused entry found... */
376
- st_hdr_ioln_i->used = TRUE; /* Indicate it is now used */
377
- strcpy(st_hdr_ioln_i->name, name);
378
- st_iodev_i = st_iodev[!curr] + i;
379
- memset(st_iodev_i, 0, IO_STATS_SIZE);
380
- break;
381
- }
382
- }
383
- }
384
- if (i < ioln_nr) {
385
- st_hdr_ioln_i = st_hdr_ioln + i;
386
- st_hdr_ioln_i->active = TRUE;
387
- st_iodev_i = st_iodev[curr] + i;
388
- *st_iodev_i = *((struct io_stats *) st_io);
389
- }
390
- /*
391
- * else it was a new device
392
- * but there was no free structure to store it.
393
- */
394
- }
395
-
396
- /*
397
- ***************************************************************************
398
- * Read sysfs stat for current block device or partition.
399
- *
400
- * IN:
401
- * @curr Index in array for current sample statistics.
402
- * @filename File name where stats will be read.
403
- * @dev_name Device or partition name.
404
- *
405
- * RETURNS:
406
- * 0 if file couldn't be opened, 1 otherwise.
407
- ***************************************************************************
408
- */
409
- int read_sysfs_file_stat(int curr, char *filename, char *dev_name)
410
- {
411
- FILE *fp;
412
- struct io_stats sdev;
413
- int i;
414
- unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios;
415
- unsigned long ios_pgr, tot_ticks, rq_ticks, wr_merges, wr_ticks;
416
- unsigned long long rd_sec_or_wr_ios, wr_sec;
417
-
418
- /* Try to read given stat file */
419
- if ((fp = fopen(filename, "r")) == NULL)
420
- return 0;
421
-
422
- i = fscanf(fp, "%lu %lu %llu %lu %lu %lu %llu %lu %lu %lu %lu",
423
- &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, &rd_ticks_or_wr_sec,
424
- &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks);
425
-
426
- if (i == 11) {
427
- /* Device or partition */
428
- sdev.rd_ios = rd_ios;
429
- sdev.rd_merges = rd_merges_or_rd_sec;
430
- sdev.rd_sectors = rd_sec_or_wr_ios;
431
- sdev.rd_ticks = rd_ticks_or_wr_sec;
432
- sdev.wr_ios = wr_ios;
433
- sdev.wr_merges = wr_merges;
434
- sdev.wr_sectors = wr_sec;
435
- sdev.wr_ticks = wr_ticks;
436
- sdev.ios_pgr = ios_pgr;
437
- sdev.tot_ticks = tot_ticks;
438
- sdev.rq_ticks = rq_ticks;
439
- }
440
- else if (i == 4) {
441
- /* Partition without extended statistics */
442
- sdev.rd_ios = rd_ios;
443
- sdev.rd_sectors = rd_merges_or_rd_sec;
444
- sdev.wr_ios = rd_sec_or_wr_ios;
445
- sdev.wr_sectors = rd_ticks_or_wr_sec;
446
- }
447
-
448
- if ((i == 11) || !DISPLAY_EXTENDED(flags)) {
449
- /*
450
- * In fact, we _don't_ save stats if it's a partition without
451
- * extended stats and yet we want to display ext stats.
452
- */
453
- save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
454
- }
455
-
456
- fclose(fp);
457
-
458
- return 1;
459
- }
460
-
461
- /*
462
- ***************************************************************************
463
- * Read sysfs stats for all the partitions of a device.
464
- *
465
- * IN:
466
- * @curr Index in array for current sample statistics.
467
- * @dev_name Device name.
468
- ***************************************************************************
469
- */
470
- void read_sysfs_dlist_part_stat(int curr, char *dev_name)
471
- {
472
- DIR *dir;
473
- struct dirent *drd;
474
- char dfile[MAX_PF_NAME], filename[MAX_PF_NAME];
475
-
476
- snprintf(dfile, MAX_PF_NAME, "%s/%s", SYSFS_BLOCK, dev_name);
477
- dfile[MAX_PF_NAME - 1] = '\0';
478
-
479
- /* Open current device directory in /sys/block */
480
- if ((dir = opendir(dfile)) == NULL)
481
- return;
482
-
483
- /* Get current entry */
484
- while ((drd = readdir(dir)) != NULL) {
485
- if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
486
- continue;
487
- snprintf(filename, MAX_PF_NAME, "%s/%s/%s", dfile, drd->d_name, S_STAT);
488
- filename[MAX_PF_NAME - 1] = '\0';
489
-
490
- /* Read current partition stats */
491
- read_sysfs_file_stat(curr, filename, drd->d_name);
492
- }
493
-
494
- /* Close device directory */
495
- closedir(dir);
496
- }
497
-
498
- /*
499
- ***************************************************************************
500
- * Read stats from the sysfs filesystem for the devices entered on the
501
- * command line.
502
- *
503
- * IN:
504
- * @curr Index in array for current sample statistics.
505
- ***************************************************************************
506
- */
507
- void read_sysfs_dlist_stat(int curr)
508
- {
509
- int dev, ok;
510
- char filename[MAX_PF_NAME];
511
- char *slash;
512
- struct io_dlist *st_dev_list_i;
513
-
514
- /* Every I/O device (or partition) is potentially unregistered */
515
- set_entries_inactive(iodev_nr, st_hdr_iodev);
516
-
517
- for (dev = 0; dev < dlist_idx; dev++) {
518
- st_dev_list_i = st_dev_list + dev;
519
-
520
- /* Some devices may have a slash in their name (eg. cciss/c0d0...) */
521
- while ((slash = strchr(st_dev_list_i->dev_name, '/'))) {
522
- *slash = '!';
523
- }
524
-
525
- snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
526
- SYSFS_BLOCK, st_dev_list_i->dev_name, S_STAT);
527
- filename[MAX_PF_NAME - 1] = '\0';
528
-
529
- /* Read device stats */
530
- ok = read_sysfs_file_stat(curr, filename, st_dev_list_i->dev_name);
531
-
532
- if (ok && st_dev_list_i->disp_part) {
533
- /* Also read stats for its partitions */
534
- read_sysfs_dlist_part_stat(curr, st_dev_list_i->dev_name);
535
- }
536
- }
537
-
538
- /* Free structures corresponding to unregistered devices */
539
- free_inactive_entries(iodev_nr, st_hdr_iodev);
540
- }
541
-
542
- /*
543
- ***************************************************************************
544
- * Read stats from the sysfs filesystem for every block devices found.
545
- *
546
- * IN:
547
- * @curr Index in array for current sample statistics.
548
- ***************************************************************************
549
- */
550
- void read_sysfs_stat(int curr)
551
- {
552
- DIR *dir;
553
- struct dirent *drd;
554
- char filename[MAX_PF_NAME];
555
- int ok;
556
-
557
- /* Every I/O device entry is potentially unregistered */
558
- set_entries_inactive(iodev_nr, st_hdr_iodev);
559
-
560
- /* Open /sys/block directory */
561
- if ((dir = opendir(SYSFS_BLOCK)) != NULL) {
562
-
563
- /* Get current entry */
564
- while ((drd = readdir(dir)) != NULL) {
565
- if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
566
- continue;
567
- snprintf(filename, MAX_PF_NAME, "%s/%s/%s",
568
- SYSFS_BLOCK, drd->d_name, S_STAT);
569
- filename[MAX_PF_NAME - 1] = '\0';
570
-
571
- /* If current entry is a directory, try to read its stat file */
572
- ok = read_sysfs_file_stat(curr, filename, drd->d_name);
573
-
574
- /*
575
- * If '-p ALL' was entered on the command line,
576
- * also try to read stats for its partitions
577
- */
578
- if (ok && DISPLAY_PART_ALL(flags)) {
579
- read_sysfs_dlist_part_stat(curr, drd->d_name);
580
- }
581
- }
582
-
583
- /* Close /sys/block directory */
584
- closedir(dir);
585
- }
586
-
587
- /* Free structures corresponding to unregistered devices */
588
- free_inactive_entries(iodev_nr, st_hdr_iodev);
589
- }
590
-
591
- /*
592
- ***************************************************************************
593
- * Read stats from /proc/diskstats.
594
- *
595
- * IN:
596
- * @curr Index in array for current sample statistics.
597
- ***************************************************************************
598
- */
599
- void read_diskstats_stat(int curr)
600
- {
601
- FILE *fp;
602
- char line[256], dev_name[MAX_NAME_LEN];
603
- char *dm_name;
604
- struct io_stats sdev;
605
- int i;
606
- unsigned long rd_ios, rd_merges_or_rd_sec, rd_ticks_or_wr_sec, wr_ios;
607
- unsigned long ios_pgr, tot_ticks, rq_ticks, wr_merges, wr_ticks;
608
- unsigned long long rd_sec_or_wr_ios, wr_sec;
609
- char *ioc_dname;
610
- unsigned int major, minor;
611
-
612
- /* Every I/O device entry is potentially unregistered */
613
- set_entries_inactive(iodev_nr, st_hdr_iodev);
614
-
615
- if ((fp = fopen(DISKSTATS, "r")) == NULL)
616
- return;
617
-
618
- while (fgets(line, 256, fp) != NULL) {
619
-
620
- /* major minor name rio rmerge rsect ruse wio wmerge wsect wuse running use aveq */
621
- i = sscanf(line, "%u %u %s %lu %lu %llu %lu %lu %lu %llu %lu %lu %lu %lu",
622
- &major, &minor, dev_name,
623
- &rd_ios, &rd_merges_or_rd_sec, &rd_sec_or_wr_ios, &rd_ticks_or_wr_sec,
624
- &wr_ios, &wr_merges, &wr_sec, &wr_ticks, &ios_pgr, &tot_ticks, &rq_ticks);
625
-
626
- if (i == 14) {
627
- /* Device or partition */
628
- if (!dlist_idx && !DISPLAY_PARTITIONS(flags) && !is_device(dev_name))
629
- continue;
630
- sdev.rd_ios = rd_ios;
631
- sdev.rd_merges = rd_merges_or_rd_sec;
632
- sdev.rd_sectors = rd_sec_or_wr_ios;
633
- sdev.rd_ticks = rd_ticks_or_wr_sec;
634
- sdev.wr_ios = wr_ios;
635
- sdev.wr_merges = wr_merges;
636
- sdev.wr_sectors = wr_sec;
637
- sdev.wr_ticks = wr_ticks;
638
- sdev.ios_pgr = ios_pgr;
639
- sdev.tot_ticks = tot_ticks;
640
- sdev.rq_ticks = rq_ticks;
641
- }
642
- else if (i == 7) {
643
- /* Partition without extended statistics */
644
- if (DISPLAY_EXTENDED(flags) ||
645
- (!dlist_idx && !DISPLAY_PARTITIONS(flags)))
646
- continue;
647
-
648
- sdev.rd_ios = rd_ios;
649
- sdev.rd_sectors = rd_merges_or_rd_sec;
650
- sdev.wr_ios = rd_sec_or_wr_ios;
651
- sdev.wr_sectors = rd_ticks_or_wr_sec;
652
- }
653
- else
654
- /* Unknown entry: Ignore it */
655
- continue;
656
-
657
- if ((ioc_dname = ioc_name(major, minor)) != NULL) {
658
- if (strcmp(dev_name, ioc_dname) && strcmp(ioc_dname, K_NODEV)) {
659
- /*
660
- * No match: Use name generated from sysstat.ioconf data
661
- * (if different from "nodev") works around known issues
662
- * with EMC PowerPath.
663
- */
664
- strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
665
- }
666
- }
667
-
668
- if ((DISPLAY_DEVMAP_NAME(flags)) && (major == dm_major)) {
669
- /*
670
- * If the device is a device mapper device, try to get its
671
- * assigned name of its logical device.
672
- */
673
- dm_name = transform_devmapname(major, minor);
674
- if (dm_name) {
675
- strcpy(dev_name, dm_name);
676
- }
677
- }
678
-
679
- save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
680
- }
681
- fclose(fp);
682
-
683
- /* Free structures corresponding to unregistered devices */
684
- free_inactive_entries(iodev_nr, st_hdr_iodev);
685
- }
686
-
687
- /*
688
- ***************************************************************************
689
- * Display CPU utilization.
690
- *
691
- * IN:
692
- * @curr Index in array for current sample statistics.
693
- * @itv Interval of time.
694
- ***************************************************************************
695
- */
696
- void write_cpu_stat(int curr, unsigned long long itv)
697
- {
698
- printf("avg-cpu: %%user %%nice %%system %%iowait %%steal %%idle\n");
699
-
700
- printf(" %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n\n",
701
- ll_sp_value(st_cpu[!curr]->cpu_user, st_cpu[curr]->cpu_user, itv),
702
- ll_sp_value(st_cpu[!curr]->cpu_nice, st_cpu[curr]->cpu_nice, itv),
703
- /*
704
- * Time spent in system mode also includes time spent servicing
705
- * hard and soft interrupts.
706
- */
707
- ll_sp_value(st_cpu[!curr]->cpu_sys + st_cpu[!curr]->cpu_softirq +
708
- st_cpu[!curr]->cpu_hardirq,
709
- st_cpu[curr]->cpu_sys + st_cpu[curr]->cpu_softirq +
710
- st_cpu[curr]->cpu_hardirq, itv),
711
- ll_sp_value(st_cpu[!curr]->cpu_iowait, st_cpu[curr]->cpu_iowait, itv),
712
- ll_sp_value(st_cpu[!curr]->cpu_steal, st_cpu[curr]->cpu_steal, itv),
713
- (st_cpu[curr]->cpu_idle < st_cpu[!curr]->cpu_idle) ?
714
- 0.0 :
715
- ll_sp_value(st_cpu[!curr]->cpu_idle, st_cpu[curr]->cpu_idle, itv));
716
- }
717
-
718
- /*
719
- ***************************************************************************
720
- * Display disk stats header.
721
- *
722
- * OUT:
723
- * @fctr Conversion factor.
724
- ***************************************************************************
725
- */
726
- void write_disk_stat_header(int *fctr)
727
- {
728
- if (DISPLAY_EXTENDED(flags)) {
729
- /* Extended stats */
730
- printf("Device: rrqm/s wrqm/s r/s w/s");
731
- if (DISPLAY_MEGABYTES(flags)) {
732
- printf(" rMB/s wMB/s");
733
- *fctr = 2048;
734
- }
735
- else if (DISPLAY_KILOBYTES(flags)) {
736
- printf(" rkB/s wkB/s");
737
- *fctr = 2;
738
- }
739
- else {
740
- printf(" rsec/s wsec/s");
741
- }
742
- printf(" avgrq-sz avgqu-sz await r_await w_await svctm %%util\n");
743
- }
744
- else {
745
- /* Basic stats */
746
- printf("Device: tps");
747
- if (DISPLAY_KILOBYTES(flags)) {
748
- printf(" kB_read/s kB_wrtn/s kB_read kB_wrtn\n");
749
- *fctr = 2;
750
- }
751
- else if (DISPLAY_MEGABYTES(flags)) {
752
- printf(" MB_read/s MB_wrtn/s MB_read MB_wrtn\n");
753
- *fctr = 2048;
754
- }
755
- else {
756
- printf(" Blk_read/s Blk_wrtn/s Blk_read Blk_wrtn\n");
757
- }
758
- }
759
- }
760
-
761
- /*
762
- ***************************************************************************
763
- * Display extended stats, read from /proc/{diskstats,partitions} or /sys.
764
- *
765
- * IN:
766
- * @curr Index in array for current sample statistics.
767
- * @itv Interval of time.
768
- * @fctr Conversion factor.
769
- * @shi Structures describing the devices and partitions.
770
- * @ioi Current sample statistics.
771
- * @ioj Previous sample statistics.
772
- ***************************************************************************
773
- */
774
- void write_ext_stat(int curr, unsigned long long itv, int fctr,
775
- struct io_hdr_stats *shi, struct io_stats *ioi,
776
- struct io_stats *ioj)
777
- {
778
- struct stats_disk sdc, sdp;
779
- struct ext_disk_stats xds;
780
- double r_await, w_await;
781
-
782
- /*
783
- * Counters overflows are possible, but don't need to be handled in
784
- * a special way: the difference is still properly calculated if the
785
- * result is of the same type as the two values.
786
- * Exception is field rq_ticks which is incremented by the number of
787
- * I/O in progress times the number of milliseconds spent doing I/O.
788
- * But the number of I/O in progress (field ios_pgr) happens to be
789
- * sometimes negative...
790
- */
791
- sdc.nr_ios = ioi->rd_ios + ioi->wr_ios;
792
- sdp.nr_ios = ioj->rd_ios + ioj->wr_ios;
793
-
794
- sdc.tot_ticks = ioi->tot_ticks;
795
- sdp.tot_ticks = ioj->tot_ticks;
796
-
797
- sdc.rd_ticks = ioi->rd_ticks;
798
- sdp.rd_ticks = ioj->rd_ticks;
799
- sdc.wr_ticks = ioi->wr_ticks;
800
- sdp.wr_ticks = ioj->wr_ticks;
801
-
802
- sdc.rd_sect = ioi->rd_sectors;
803
- sdp.rd_sect = ioj->rd_sectors;
804
- sdc.wr_sect = ioi->wr_sectors;
805
- sdp.wr_sect = ioj->wr_sectors;
806
-
807
- compute_ext_disk_stats(&sdc, &sdp, itv, &xds);
808
-
809
- r_await = (ioi->rd_ios - ioj->rd_ios) ?
810
- (ioi->rd_ticks - ioj->rd_ticks) /
811
- ((double) (ioi->rd_ios - ioj->rd_ios)) : 0.0;
812
- w_await = (ioi->wr_ios - ioj->wr_ios) ?
813
- (ioi->wr_ticks - ioj->wr_ticks) /
814
- ((double) (ioi->wr_ios - ioj->wr_ios)) : 0.0;
815
-
816
- /* DEV rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await r_await w_await svctm %util */
817
- printf("%-13s %8.2f %8.2f %7.2f %7.2f %8.2f %8.2f %8.2f %8.2f %7.2f %7.2f %7.2f %6.2f %6.2f\n",
818
- shi->name,
819
- S_VALUE(ioj->rd_merges, ioi->rd_merges, itv),
820
- S_VALUE(ioj->wr_merges, ioi->wr_merges, itv),
821
- S_VALUE(ioj->rd_ios, ioi->rd_ios, itv),
822
- S_VALUE(ioj->wr_ios, ioi->wr_ios, itv),
823
- ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr,
824
- ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr,
825
- xds.arqsz,
826
- S_VALUE(ioj->rq_ticks, ioi->rq_ticks, itv) / 1000.0,
827
- xds.await,
828
- r_await,
829
- w_await,
830
- /* The ticks output is biased to output 1000 ticks per second */
831
- xds.svctm,
832
- /* Again: Ticks in milliseconds */
833
- xds.util / 10.0);
834
- }
835
-
836
- /*
837
- ***************************************************************************
838
- * Write basic stats, read from /proc/diskstats or from sysfs.
839
- *
840
- * IN:
841
- * @curr Index in array for current sample statistics.
842
- * @itv Interval of time.
843
- * @fctr Conversion factor.
844
- * @shi Structures describing the devices and partitions.
845
- * @ioi Current sample statistics.
846
- * @ioj Previous sample statistics.
847
- ***************************************************************************
848
- */
849
- void write_basic_stat(int curr, unsigned long long itv, int fctr,
850
- struct io_hdr_stats *shi, struct io_stats *ioi,
851
- struct io_stats *ioj)
852
- {
853
- unsigned long long rd_sec, wr_sec;
854
-
855
- printf("%-13s", shi->name);
856
-
857
- /* Print stats coming from /sys or /proc/diskstats */
858
- rd_sec = ioi->rd_sectors - ioj->rd_sectors;
859
- if ((ioi->rd_sectors < ioj->rd_sectors) && (ioj->rd_sectors <= 0xffffffff)) {
860
- rd_sec &= 0xffffffff;
861
- }
862
- wr_sec = ioi->wr_sectors - ioj->wr_sectors;
863
- if ((ioi->wr_sectors < ioj->wr_sectors) && (ioj->wr_sectors <= 0xffffffff)) {
864
- wr_sec &= 0xffffffff;
865
- }
866
-
867
- printf(" %8.2f %12.2f %12.2f %10llu %10llu\n",
868
- S_VALUE(ioj->rd_ios + ioj->wr_ios, ioi->rd_ios + ioi->wr_ios, itv),
869
- ll_s_value(ioj->rd_sectors, ioi->rd_sectors, itv) / fctr,
870
- ll_s_value(ioj->wr_sectors, ioi->wr_sectors, itv) / fctr,
871
- (unsigned long long) rd_sec / fctr,
872
- (unsigned long long) wr_sec / fctr);
873
- }
874
-
875
- /*
876
- ***************************************************************************
877
- * Print everything now (stats and uptime).
878
- *
879
- * IN:
880
- * @curr Index in array for current sample statistics.
881
- * @rectime Current date and time.
882
- ***************************************************************************
883
- */
884
- void write_stats(int curr, struct tm *rectime)
885
- {
886
- int dev, i, fctr = 1;
887
- unsigned long long itv;
888
- struct io_hdr_stats *shi;
889
- struct io_dlist *st_dev_list_i;
890
-
891
- /* Test stdout */
892
- TEST_STDOUT(STDOUT_FILENO);
893
-
894
- /* Print time stamp */
895
- if (DISPLAY_TIMESTAMP(flags)) {
896
- if (DISPLAY_ISO(flags)) {
897
- strftime(timestamp, sizeof(timestamp), "%FT%T%z", rectime);
898
- }
899
- else {
900
- strftime(timestamp, sizeof(timestamp), "%x %X", rectime);
901
- }
902
- printf("%s\n", timestamp);
903
- #ifdef DEBUG
904
- if (DISPLAY_DEBUG(flags)) {
905
- fprintf(stderr, "%s\n", timestamp);
906
- }
907
- #endif
908
- }
909
-
910
- /* Interval is multiplied by the number of processors */
911
- itv = get_interval(uptime[!curr], uptime[curr]);
912
-
913
- if (DISPLAY_CPU(flags)) {
914
- #ifdef DEBUG
915
- if (DISPLAY_DEBUG(flags)) {
916
- /* Debug output */
917
- fprintf(stderr, "itv=%llu st_cpu[curr]{ cpu_user=%llu cpu_nice=%llu "
918
- "cpu_sys=%llu cpu_idle=%llu cpu_iowait=%llu cpu_steal=%llu "
919
- "cpu_hardirq=%llu cpu_softirq=%llu cpu_guest=%llu }\n",
920
- itv,
921
- st_cpu[curr]->cpu_user,
922
- st_cpu[curr]->cpu_nice,
923
- st_cpu[curr]->cpu_sys,
924
- st_cpu[curr]->cpu_idle,
925
- st_cpu[curr]->cpu_iowait,
926
- st_cpu[curr]->cpu_steal,
927
- st_cpu[curr]->cpu_hardirq,
928
- st_cpu[curr]->cpu_softirq,
929
- st_cpu[curr]->cpu_guest
930
- );
931
- }
932
- #endif
933
-
934
- /* Display CPU utilization */
935
- write_cpu_stat(curr, itv);
936
- }
937
-
938
- if (cpu_nr > 1) {
939
- /* On SMP machines, reduce itv to one processor (see note above) */
940
- itv = get_interval(uptime0[!curr], uptime0[curr]);
941
- }
942
-
943
- if (DISPLAY_DISK(flags)) {
944
- struct io_stats *ioi, *ioj;
945
-
946
- shi = st_hdr_iodev;
947
-
948
- /* Display disk stats header */
949
- write_disk_stat_header(&fctr);
950
-
951
- for (i = 0; i < iodev_nr; i++, shi++) {
952
- if (shi->used) {
953
-
954
- if (dlist_idx && !HAS_SYSFS(flags)) {
955
- /*
956
- * With sysfs, only stats for the requested
957
- * devices are read.
958
- * With /proc/diskstats, stats for
959
- * every device are read. Thus we need to check
960
- * if stats for current device are to be displayed.
961
- */
962
- for (dev = 0; dev < dlist_idx; dev++) {
963
- st_dev_list_i = st_dev_list + dev;
964
- if (!strcmp(shi->name, st_dev_list_i->dev_name))
965
- break;
966
- }
967
- if (dev == dlist_idx)
968
- /* Device not found in list: Don't display it */
969
- continue;
970
- }
971
-
972
- ioi = st_iodev[curr] + i;
973
- ioj = st_iodev[!curr] + i;
974
-
975
- if (!DISPLAY_UNFILTERED(flags)) {
976
- if (!ioi->rd_ios && !ioi->wr_ios)
977
- continue;
978
- }
979
-
980
- if (DISPLAY_ZERO_OMIT(flags)) {
981
- if ((ioi->rd_ios == ioj->rd_ios) &&
982
- (ioi->wr_ios == ioj->wr_ios))
983
- /* No activity: Ignore it */
984
- continue;
985
- }
986
- #ifdef DEBUG
987
- if (DISPLAY_DEBUG(flags)) {
988
- /* Debug output */
989
- fprintf(stderr, "name=%s itv=%llu fctr=%d ioi{ rd_sectors=%llu "
990
- "wr_sectors=%llu rd_ios=%lu rd_merges=%lu rd_ticks=%lu "
991
- "wr_ios=%lu wr_merges=%lu wr_ticks=%lu ios_pgr=%lu tot_ticks=%lu "
992
- "rq_ticks=%lu dk_drive=%lu dk_drive_rblk=%lu dk_drive_wblk=%lu }\n",
993
- shi->name,
994
- itv,
995
- fctr,
996
- ioi->rd_sectors,
997
- ioi->wr_sectors,
998
- ioi->rd_ios,
999
- ioi->rd_merges,
1000
- ioi->rd_ticks,
1001
- ioi->wr_ios,
1002
- ioi->wr_merges,
1003
- ioi->wr_ticks,
1004
- ioi->ios_pgr,
1005
- ioi->tot_ticks,
1006
- ioi->rq_ticks,
1007
- ioi->dk_drive,
1008
- ioi->dk_drive_rblk,
1009
- ioi->dk_drive_wblk
1010
- );
1011
- }
1012
- #endif
1013
-
1014
- if (DISPLAY_EXTENDED(flags)) {
1015
- write_ext_stat(curr, itv, fctr, shi, ioi, ioj);
1016
- }
1017
- else {
1018
- write_basic_stat(curr, itv, fctr, shi, ioi, ioj);
1019
- }
1020
- }
1021
- }
1022
- printf("\n");
1023
- }
1024
- }
1025
-
1026
- /*
1027
- ***************************************************************************
1028
- * Main loop: Read I/O stats from the relevant sources and display them.
1029
- *
1030
- * IN:
1031
- * @count Number of lines of stats to print.
1032
- * @rectime Current date and time.
1033
- ***************************************************************************
1034
- */
1035
- void rw_io_stat_loop(long int count, struct tm *rectime)
1036
- {
1037
- int curr = 1;
1038
-
1039
- /* Don't buffer data if redirected to a pipe */
1040
- setbuf(stdout, NULL);
1041
-
1042
- do {
1043
- if (cpu_nr > 1) {
1044
- /*
1045
- * Read system uptime (only for SMP machines).
1046
- * Init uptime0. So if /proc/uptime cannot fill it,
1047
- * this will be done by /proc/stat.
1048
- */
1049
- uptime0[curr] = 0;
1050
- read_uptime(&(uptime0[curr]));
1051
- }
1052
-
1053
- /*
1054
- * Read stats for CPU "all" and 0.
1055
- * Note that stats for CPU 0 are not used per se. It only makes
1056
- * read_stat_cpu() fill uptime0.
1057
- */
1058
- read_stat_cpu(st_cpu[curr], 2, &(uptime[curr]), &(uptime0[curr]));
1059
-
1060
- if (dlist_idx) {
1061
- /*
1062
- * A device or partition name was entered on the command line,
1063
- * with or without -p option (but not -p ALL).
1064
- */
1065
- if (HAS_DISKSTATS(flags) && !DISPLAY_PARTITIONS(flags)) {
1066
- read_diskstats_stat(curr);
1067
- }
1068
- else if (HAS_SYSFS(flags)) {
1069
- read_sysfs_dlist_stat(curr);
1070
- }
1071
- }
1072
- else {
1073
- /*
1074
- * No devices nor partitions entered on the command line
1075
- * (for example if -p ALL was used).
1076
- */
1077
- if (HAS_DISKSTATS(flags)) {
1078
- read_diskstats_stat(curr);
1079
- }
1080
- else if (HAS_SYSFS(flags)) {
1081
- read_sysfs_stat(curr);
1082
- }
1083
- }
1084
-
1085
- /* Get time */
1086
- get_localtime(rectime);
1087
-
1088
- /* Print results */
1089
- write_stats(curr, rectime);
1090
-
1091
- if (count > 0) {
1092
- count--;
1093
- }
1094
- if (count) {
1095
- curr ^= 1;
1096
- pause();
1097
- }
1098
- }
1099
- while (count);
1100
- }