perfmonger 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/.dir-locals.el +2 -0
  3. data/.gitignore +4 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +12 -0
  6. data/COPYING +674 -0
  7. data/Gemfile +5 -0
  8. data/HOWTO.md +15 -0
  9. data/NEWS +115 -0
  10. data/README.md +61 -0
  11. data/Rakefile +8 -0
  12. data/bin/perfmonger +6 -0
  13. data/data/NOTICE +8 -0
  14. data/data/Twitter_Bootstrap_LICENSE.txt +176 -0
  15. data/data/assets/css/bootstrap-responsive.css +1109 -0
  16. data/data/assets/css/bootstrap.css +6167 -0
  17. data/data/assets/css/perfmonger.css +17 -0
  18. data/data/assets/dashboard.erb +319 -0
  19. data/data/assets/img/glyphicons-halflings-white.png +0 -0
  20. data/data/assets/img/glyphicons-halflings.png +0 -0
  21. data/data/assets/js/bootstrap.js +2280 -0
  22. data/data/assets/js/bootstrap.min.js +6 -0
  23. data/data/assets/js/canvasjs.js +9042 -0
  24. data/data/assets/js/canvasjs.min.js +271 -0
  25. data/data/sysstat.ioconf +268 -0
  26. data/ext/perfmonger/extconf.rb +19 -0
  27. data/ext/perfmonger/perfmonger.h +58 -0
  28. data/ext/perfmonger/perfmonger_record.c +754 -0
  29. data/ext/perfmonger/sysstat/common.c +627 -0
  30. data/ext/perfmonger/sysstat/common.h +207 -0
  31. data/ext/perfmonger/sysstat/ioconf.c +515 -0
  32. data/ext/perfmonger/sysstat/ioconf.h +84 -0
  33. data/ext/perfmonger/sysstat/iostat.c +1100 -0
  34. data/ext/perfmonger/sysstat/iostat.h +121 -0
  35. data/ext/perfmonger/sysstat/libsysstat.h +19 -0
  36. data/ext/perfmonger/sysstat/mpstat.c +953 -0
  37. data/ext/perfmonger/sysstat/mpstat.h +79 -0
  38. data/ext/perfmonger/sysstat/rd_stats.c +2388 -0
  39. data/ext/perfmonger/sysstat/rd_stats.h +651 -0
  40. data/ext/perfmonger/sysstat/sysconfig.h +13 -0
  41. data/lib/perfmonger/cli.rb +115 -0
  42. data/lib/perfmonger/command/base_command.rb +39 -0
  43. data/lib/perfmonger/command/fingerprint.rb +453 -0
  44. data/lib/perfmonger/command/plot.rb +429 -0
  45. data/lib/perfmonger/command/record.rb +32 -0
  46. data/lib/perfmonger/command/record_option.rb +149 -0
  47. data/lib/perfmonger/command/server.rb +294 -0
  48. data/lib/perfmonger/command/stat.rb +60 -0
  49. data/lib/perfmonger/command/stat_option.rb +29 -0
  50. data/lib/perfmonger/command/summary.rb +402 -0
  51. data/lib/perfmonger/config.rb +6 -0
  52. data/lib/perfmonger/version.rb +5 -0
  53. data/lib/perfmonger.rb +12 -0
  54. data/misc/release-howto.txt +17 -0
  55. data/misc/sample-cpu.png +0 -0
  56. data/misc/sample-read-iops.png +0 -0
  57. data/perfmonger.gemspec +44 -0
  58. data/test/run-test.sh +39 -0
  59. data/test/spec/bin_spec.rb +37 -0
  60. data/test/spec/data/2devices.expected +42 -0
  61. data/test/spec/data/2devices.output +42 -0
  62. data/test/spec/spec_helper.rb +20 -0
  63. data/test/spec/summary_spec.rb +193 -0
  64. data/test/test-perfmonger.c +145 -0
  65. data/test/test.h +9 -0
  66. metadata +154 -0
@@ -0,0 +1,627 @@
1
+ /*
2
+ * (C) 2011 Modified by Yuto HAYAMIZU (haya <at> tkl.iis.u-tokyo.ac.jp)
3
+ */
4
+
5
+ /*
6
+ * sar, sadc, sadf, mpstat and iostat common routines.
7
+ * (C) 1999-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
+
27
+ #include <stdio.h>
28
+ #include <string.h>
29
+ #include <stdlib.h>
30
+ #include <time.h>
31
+ #include <errno.h>
32
+ #include <unistd.h> /* For STDOUT_FILENO, among others */
33
+ #include <sys/ioctl.h>
34
+ #include <sys/types.h>
35
+ #include <dirent.h>
36
+
37
+ #include "common.h"
38
+ #include "ioconf.h"
39
+ #include "rd_stats.h"
40
+
41
+ #ifdef USE_NLS
42
+ #include <locale.h>
43
+ #include <libintl.h>
44
+ #define _(string) gettext(string)
45
+ #else
46
+ #define _(string) (string)
47
+ #endif
48
+
49
+ /* Number of ticks per second */
50
+ unsigned int hz;
51
+ /* Number of bit shifts to convert pages to kB */
52
+ unsigned int kb_shift;
53
+
54
+ /*
55
+ ***************************************************************************
56
+ * Get local date and time.
57
+ *
58
+ * OUT:
59
+ * @rectime Current local date and time.
60
+ *
61
+ * RETURNS:
62
+ * Value of time in seconds since the Epoch.
63
+ ***************************************************************************
64
+ */
65
+ time_t get_localtime(struct tm *rectime)
66
+ {
67
+ time_t timer;
68
+ struct tm *ltm;
69
+
70
+ time(&timer);
71
+ ltm = localtime(&timer);
72
+
73
+ *rectime = *ltm;
74
+ return timer;
75
+ }
76
+
77
+ /*
78
+ ***************************************************************************
79
+ * Get date and time expressed in UTC.
80
+ *
81
+ * OUT:
82
+ * @rectime Current date and time expressed in UTC.
83
+ *
84
+ * RETURNS:
85
+ * Value of time in seconds since the Epoch.
86
+ ***************************************************************************
87
+ */
88
+ time_t get_gmtime(struct tm *rectime)
89
+ {
90
+ time_t timer;
91
+ struct tm *ltm;
92
+
93
+ time(&timer);
94
+ ltm = gmtime(&timer);
95
+
96
+ *rectime = *ltm;
97
+ return timer;
98
+ }
99
+
100
+ /*
101
+ ***************************************************************************
102
+ * Get date and time and take into account <ENV_TIME_DEFTM> variable.
103
+ *
104
+ * OUT:
105
+ * @rectime Current date and time.
106
+ *
107
+ * RETURNS:
108
+ * Value of time in seconds since the Epoch.
109
+ ***************************************************************************
110
+ */
111
+ time_t get_time(struct tm *rectime)
112
+ {
113
+ static int utc = 0;
114
+ char *e;
115
+
116
+ if (!utc) {
117
+ /* Read environment variable value once */
118
+ if ((e = getenv(ENV_TIME_DEFTM)) != NULL) {
119
+ utc = !strcmp(e, K_UTC);
120
+ }
121
+ utc++;
122
+ }
123
+
124
+ if (utc == 2)
125
+ return get_gmtime(rectime);
126
+ else
127
+ return get_localtime(rectime);
128
+ }
129
+
130
+ /*
131
+ ***************************************************************************
132
+ * Count number of comma-separated values in arguments list. For example,
133
+ * the number will be 3 for the list "foobar -p 1 -p 2,3,4 2 5".
134
+ *
135
+ * IN:
136
+ * @arg_c Number of arguments in the list.
137
+ * @arg_v Arguments list.
138
+ *
139
+ * RETURNS:
140
+ * Number of comma-separated values in the list.
141
+ ***************************************************************************
142
+ */
143
+ int count_csvalues(int arg_c, char **arg_v)
144
+ {
145
+ int opt = 1;
146
+ int nr = 0;
147
+ char *t;
148
+
149
+ while (opt < arg_c) {
150
+ if (strchr(arg_v[opt], ',')) {
151
+ for (t = arg_v[opt]; t; t = strchr(t + 1, ',')) {
152
+ nr++;
153
+ }
154
+ }
155
+ opt++;
156
+ }
157
+
158
+ return nr;
159
+ }
160
+
161
+ /*
162
+ ***************************************************************************
163
+ * Look for partitions of a given block device in /sys filesystem.
164
+ *
165
+ * IN:
166
+ * @dev_name Name of the block device.
167
+ *
168
+ * RETURNS:
169
+ * Number of partitions for the given block device.
170
+ ***************************************************************************
171
+ */
172
+ int get_dev_part_nr(char *dev_name)
173
+ {
174
+ DIR *dir;
175
+ struct dirent *drd;
176
+ char dfile[MAX_PF_NAME], line[MAX_PF_NAME];
177
+ int part = 0;
178
+
179
+ snprintf(dfile, MAX_PF_NAME, "%s/%s", SYSFS_BLOCK, dev_name);
180
+ dfile[MAX_PF_NAME - 1] = '\0';
181
+
182
+ /* Open current device directory in /sys/block */
183
+ if ((dir = opendir(dfile)) == NULL)
184
+ return 0;
185
+
186
+ /* Get current file entry */
187
+ while ((drd = readdir(dir)) != NULL) {
188
+ if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
189
+ continue;
190
+ snprintf(line, MAX_PF_NAME, "%s/%s/%s", dfile, drd->d_name, S_STAT);
191
+ line[MAX_PF_NAME - 1] = '\0';
192
+
193
+ /* Try to guess if current entry is a directory containing a stat file */
194
+ if (!access(line, R_OK)) {
195
+ /* Yep... */
196
+ part++;
197
+ }
198
+ }
199
+
200
+ /* Close directory */
201
+ closedir(dir);
202
+
203
+ return part;
204
+ }
205
+
206
+ /*
207
+ ***************************************************************************
208
+ * Look for block devices present in /sys/ filesystem:
209
+ * Check first that sysfs is mounted (done by trying to open /sys/block
210
+ * directory), then find number of devices registered.
211
+ *
212
+ * IN:
213
+ * @display_partitions Set to TRUE if partitions must also be counted.
214
+ *
215
+ * RETURNS:
216
+ * Total number of block devices (and partitions if @display_partitions was
217
+ * set).
218
+ ***************************************************************************
219
+ */
220
+ int get_sysfs_dev_nr(int display_partitions)
221
+ {
222
+ DIR *dir;
223
+ struct dirent *drd;
224
+ char line[MAX_PF_NAME];
225
+ int dev = 0;
226
+
227
+ /* Open /sys/block directory */
228
+ if ((dir = opendir(SYSFS_BLOCK)) == NULL)
229
+ /* sysfs not mounted, or perhaps this is an old kernel */
230
+ return 0;
231
+
232
+ /* Get current file entry in /sys/block directory */
233
+ while ((drd = readdir(dir)) != NULL) {
234
+ if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
235
+ continue;
236
+ snprintf(line, MAX_PF_NAME, "%s/%s/%s", SYSFS_BLOCK, drd->d_name, S_STAT);
237
+ line[MAX_PF_NAME - 1] = '\0';
238
+
239
+ /* Try to guess if current entry is a directory containing a stat file */
240
+ if (!access(line, R_OK)) {
241
+ /* Yep... */
242
+ dev++;
243
+
244
+ if (display_partitions) {
245
+ /* We also want the number of partitions for this device */
246
+ dev += get_dev_part_nr(drd->d_name);
247
+ }
248
+ }
249
+ }
250
+
251
+ /* Close /sys/block directory */
252
+ closedir(dir);
253
+
254
+ return dev;
255
+ }
256
+
257
+ /*
258
+ ***************************************************************************
259
+ * Read /proc/devices file and get device-mapper major number.
260
+ * If device-mapper entry is not found in file, use DEFAULT_DEMAP_MAJOR
261
+ * number.
262
+ *
263
+ * RETURNS:
264
+ * Device-mapper major number.
265
+ ***************************************************************************
266
+ */
267
+ unsigned int get_devmap_major(void)
268
+ {
269
+ FILE *fp;
270
+ char line[128];
271
+ unsigned int dm_major = DEFAULT_DEVMAP_MAJOR;
272
+
273
+ if ((fp = fopen(DEVICES, "r")) == NULL)
274
+ return dm_major;
275
+
276
+ while (fgets(line, 128, fp) != NULL) {
277
+
278
+ if (strstr(line, "device-mapper")) {
279
+ /* Read device-mapper major number */
280
+ sscanf(line, "%u", &dm_major);
281
+ }
282
+ }
283
+
284
+ fclose(fp);
285
+
286
+ return dm_major;
287
+ }
288
+
289
+ /*
290
+ ***************************************************************************
291
+ * Print banner.
292
+ *
293
+ * IN:
294
+ * @rectime Date and time to display.
295
+ * @sysname System name to display.
296
+ * @release System release number to display.
297
+ * @nodename Hostname to display.
298
+ * @machine Machine architecture to display.
299
+ * @cpu_nr Number of CPU.
300
+ *
301
+ * RETURNS:
302
+ * TRUE if S_TIME_FORMAT is set to ISO, or FALSE otherwise.
303
+ ***************************************************************************
304
+ */
305
+ int print_gal_header(struct tm *rectime, char *sysname, char *release,
306
+ char *nodename, char *machine, int cpu_nr)
307
+ {
308
+ char cur_date[64];
309
+ char *e;
310
+ int rc = 0;
311
+
312
+ if (rectime == NULL) {
313
+ strcpy(cur_date, "?/?/?");
314
+ }
315
+ else if (((e = getenv(ENV_TIME_FMT)) != NULL) && !strcmp(e, K_ISO)) {
316
+ strftime(cur_date, sizeof(cur_date), "%Y-%m-%d", rectime);
317
+ rc = 1;
318
+ }
319
+ else {
320
+ strftime(cur_date, sizeof(cur_date), "%x", rectime);
321
+ }
322
+
323
+ printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n", sysname, release, nodename,
324
+ cur_date, machine, cpu_nr);
325
+
326
+ return rc;
327
+ }
328
+
329
+ #ifdef USE_NLS
330
+ /*
331
+ ***************************************************************************
332
+ * Init National Language Support.
333
+ ***************************************************************************
334
+ */
335
+ void init_nls(void)
336
+ {
337
+ setlocale(LC_MESSAGES, "");
338
+ setlocale(LC_CTYPE, "");
339
+ setlocale(LC_TIME, "");
340
+ setlocale(LC_NUMERIC, "");
341
+
342
+ bindtextdomain(PACKAGE, LOCALEDIR);
343
+ textdomain(PACKAGE);
344
+ }
345
+ #endif
346
+
347
+ /*
348
+ ***************************************************************************
349
+ * Get number of rows for current window.
350
+ *
351
+ * RETURNS:
352
+ * Number of rows.
353
+ ***************************************************************************
354
+ */
355
+ int get_win_height(void)
356
+ {
357
+ struct winsize win;
358
+ /*
359
+ * This default value will be used whenever STDOUT
360
+ * is redirected to a pipe or a file
361
+ */
362
+ int rows = 3600 * 24;
363
+
364
+ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1) {
365
+ if (win.ws_row > 2) {
366
+ rows = win.ws_row - 2;
367
+ }
368
+ }
369
+ return rows;
370
+ }
371
+
372
+ /*
373
+ ***************************************************************************
374
+ * Remove /dev from path name.
375
+ *
376
+ * IN:
377
+ * @name Device name (may begins with "/dev/")
378
+ *
379
+ * RETURNS:
380
+ * Device basename.
381
+ ***************************************************************************
382
+ */
383
+ char *device_name(char *name)
384
+ {
385
+ if (!strncmp(name, "/dev/", 5))
386
+ return name + 5;
387
+
388
+ return name;
389
+ }
390
+
391
+ /*
392
+ ***************************************************************************
393
+ * Test whether given name is a device or a partition, using sysfs.
394
+ * This is more straightforward that using ioc_iswhole() function from
395
+ * ioconf.c which should be used only with kernels that don't have sysfs.
396
+ *
397
+ * IN:
398
+ * @name Device or partition name.
399
+ *
400
+ * RETURNS:
401
+ * TRUE if @name is a (whole) device.
402
+ ***************************************************************************
403
+ */
404
+ int is_device(char *name)
405
+ {
406
+ char syspath[PATH_MAX];
407
+ char *slash;
408
+
409
+ /* Some devices may have a slash in their name (eg. cciss/c0d0...) */
410
+ while ((slash = strchr(name, '/'))) {
411
+ *slash = '!';
412
+ }
413
+ snprintf(syspath, sizeof(syspath), "%s/%s", SYSFS_BLOCK, name);
414
+
415
+ return !(access(syspath, F_OK));
416
+ }
417
+
418
+ /*
419
+ ***************************************************************************
420
+ * Get page shift in kB.
421
+ ***************************************************************************
422
+ */
423
+ void get_kb_shift(void)
424
+ {
425
+ int shift = 0;
426
+ long size;
427
+
428
+ /* One can also use getpagesize() to get the size of a page */
429
+ if ((size = sysconf(_SC_PAGESIZE)) == -1) {
430
+ perror("sysconf");
431
+ }
432
+
433
+ size >>= 10; /* Assume that a page has a minimum size of 1 kB */
434
+
435
+ while (size > 1) {
436
+ shift++;
437
+ size >>= 1;
438
+ }
439
+
440
+ kb_shift = (unsigned int) shift;
441
+ }
442
+
443
+ /*
444
+ ***************************************************************************
445
+ * Get number of clock ticks per second.
446
+ ***************************************************************************
447
+ */
448
+ void get_HZ(void)
449
+ {
450
+ long ticks;
451
+
452
+ if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
453
+ perror("sysconf");
454
+ }
455
+
456
+ hz = (unsigned int) ticks;
457
+ }
458
+
459
+ /*
460
+ ***************************************************************************
461
+ * Handle overflow conditions properly for counters which are read as
462
+ * unsigned long long, but which can be unsigned long long or
463
+ * unsigned long only depending on the kernel version used.
464
+ * @value1 and @value2 being two values successively read for this
465
+ * counter, if @value2 < @value1 and @value1 <= 0xffffffff, then we can
466
+ * assume that the counter's type was unsigned long and has overflown, and
467
+ * so the difference @value2 - @value1 must be casted to this type.
468
+ * NOTE: These functions should no longer be necessary to handle a particular
469
+ * stat counter when we can assume that everybody is using a recent kernel
470
+ * (defining this counter as unsigned long long).
471
+ ***************************************************************************
472
+ */
473
+ double ll_sp_value(unsigned long long value1, unsigned long long value2,
474
+ unsigned long long itv)
475
+ {
476
+ if ((value2 < value1) && (value1 <= 0xffffffff))
477
+ /* Counter's type was unsigned long and has overflown */
478
+ return ((double) ((value2 - value1) & 0xffffffff)) / itv * 100;
479
+ else
480
+ return SP_VALUE(value1, value2, itv);
481
+ }
482
+
483
+ double ll_s_value(unsigned long long value1, unsigned long long value2,
484
+ unsigned long long itv)
485
+ {
486
+ if ((value2 < value1) && (value1 <= 0xffffffff))
487
+ /* Counter's type was unsigned long and has overflown */
488
+ return ((double) ((value2 - value1) & 0xffffffff)) / itv * HZ;
489
+ else
490
+ return S_VALUE(value1, value2, itv);
491
+ }
492
+
493
+ /*
494
+ ***************************************************************************
495
+ * Compute time interval.
496
+ *
497
+ * IN:
498
+ * @prev_uptime Previous uptime value in jiffies.
499
+ * @curr_uptime Current uptime value in jiffies.
500
+ *
501
+ * RETURNS:
502
+ * Interval of time in jiffies.
503
+ ***************************************************************************
504
+ */
505
+ unsigned long long get_interval(unsigned long long prev_uptime,
506
+ unsigned long long curr_uptime)
507
+ {
508
+ unsigned long long itv;
509
+
510
+ /* prev_time=0 when displaying stats since system startup */
511
+ itv = curr_uptime - prev_uptime;
512
+
513
+ if (!itv) { /* Paranoia checking */
514
+ itv = 1;
515
+ }
516
+
517
+ return itv;
518
+ }
519
+
520
+ /*
521
+ ***************************************************************************
522
+ * Since ticks may vary slightly from CPU to CPU, we'll want
523
+ * to recalculate itv based on this CPU's tick count, rather
524
+ * than that reported by the "cpu" line. Otherwise we
525
+ * occasionally end up with slightly skewed figures, with
526
+ * the skew being greater as the time interval grows shorter.
527
+ *
528
+ * IN:
529
+ * @scc Current sample statistics for current CPU.
530
+ * @scp Previous sample statistics for current CPU.
531
+ *
532
+ * RETURNS:
533
+ * Interval of time based on current CPU.
534
+ ***************************************************************************
535
+ */
536
+ unsigned long long get_per_cpu_interval(struct stats_cpu *scc,
537
+ struct stats_cpu *scp)
538
+ {
539
+ /* Don't take cpu_guest into account because cpu_user already includes it */
540
+ return ((scc->cpu_user + scc->cpu_nice +
541
+ scc->cpu_sys + scc->cpu_iowait +
542
+ scc->cpu_idle + scc->cpu_steal +
543
+ scc->cpu_hardirq + scc->cpu_softirq) -
544
+ (scp->cpu_user + scp->cpu_nice +
545
+ scp->cpu_sys + scp->cpu_iowait +
546
+ scp->cpu_idle + scp->cpu_steal +
547
+ scp->cpu_hardirq + scp->cpu_softirq));
548
+ }
549
+
550
+ /*
551
+ ***************************************************************************
552
+ * Unhandled situation: Panic and exit.
553
+ *
554
+ * IN:
555
+ * @function Function name where situation occured.
556
+ * @error_code Error code.
557
+ ***************************************************************************
558
+ */
559
+ void sysstat_panic(const char *function, int error_code)
560
+ {
561
+ fprintf(stderr, "sysstat: %s[%d]: Last chance handler...\n",
562
+ function, error_code);
563
+ exit(1);
564
+ }
565
+
566
+ /*
567
+ ***************************************************************************
568
+ * Count number of bits set in an array.
569
+ *
570
+ * IN:
571
+ * @ptr Pointer to array.
572
+ * @size Size of array in bytes.
573
+ *
574
+ * RETURNS:
575
+ * Number of bits set in the array.
576
+ ***************************************************************************
577
+ */
578
+ int count_bits(void *ptr, int size)
579
+ {
580
+ int nr = 0, i, k;
581
+ char *p;
582
+
583
+ p = ptr;
584
+ for (i = 0; i < size; i++, p++) {
585
+ k = 0x80;
586
+ while (k) {
587
+ if (*p & k)
588
+ nr++;
589
+ k >>= 1;
590
+ }
591
+ }
592
+
593
+ return nr;
594
+ }
595
+
596
+ /*
597
+ ***************************************************************************
598
+ * Compute "extended" device statistics (service time, etc.).
599
+ *
600
+ * IN:
601
+ * @sdc Structure with current device statistics.
602
+ * @sdp Structure with previous device statistics.
603
+ * @itv Interval of time in jiffies.
604
+ *
605
+ * OUT:
606
+ * @xds Structure with extended statistics.
607
+ ***************************************************************************
608
+ */
609
+ void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp,
610
+ unsigned long long itv, struct ext_disk_stats *xds)
611
+ {
612
+ double tput
613
+ = ((double) (sdc->nr_ios - sdp->nr_ios)) * HZ / itv;
614
+
615
+ xds->util = S_VALUE(sdp->tot_ticks, sdc->tot_ticks, itv);
616
+ xds->svctm = tput ? xds->util / tput : 0.0;
617
+ /*
618
+ * Kernel gives ticks already in milliseconds for all platforms
619
+ * => no need for further scaling.
620
+ */
621
+ xds->await = (sdc->nr_ios - sdp->nr_ios) ?
622
+ ((sdc->rd_ticks - sdp->rd_ticks) + (sdc->wr_ticks - sdp->wr_ticks)) /
623
+ ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
624
+ xds->arqsz = (sdc->nr_ios - sdp->nr_ios) ?
625
+ ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect)) /
626
+ ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
627
+ }