109
112
***************************************************************************
110
* Set every disk_io entry to inactive state
113
* Set every disk_io or nfs_io entry to inactive state
111
114
***************************************************************************
113
void set_entries_inactive(int iodev_nr)
116
void set_entries_inactive(int ioln_nr, struct io_hdr_stats *st_hdr_ioln)
116
struct io_hdr_stats *shi = st_hdr_iodev;
119
struct io_hdr_stats *shi = st_hdr_ioln;
118
for (i = 0; i < iodev_nr; i++, shi++)
121
for (i = 0; i < ioln_nr; i++, shi++)
119
122
shi->active = FALSE;
166
169
***************************************************************************
170
* Allocate and init I/O NFS directories structures
171
***************************************************************************
173
void salloc_nfs(int ionfs_nr)
177
for (i = 0; i < 2; i++) {
178
if ((st_ionfs[i] = (struct io_nfs_stats *) malloc(IO_NFS_STATS_SIZE * ionfs_nr)) == NULL) {
182
memset(st_ionfs[i], 0, IO_NFS_STATS_SIZE * ionfs_nr);
185
if ((st_hdr_ionfs = (struct io_hdr_stats *) malloc(IO_HDR_STATS_SIZE * ionfs_nr)) == NULL) {
189
memset(st_hdr_ionfs, 0, IO_HDR_STATS_SIZE * ionfs_nr);
194
***************************************************************************
167
195
* Allocate structures for devices entered on the command line
168
196
***************************************************************************
270
301
sprintf(shi->name, "%s%d", K_HDISK, i);
305
/* Get number of NFS directories in /proc/self/mountstats */
306
if (DISPLAY_NFS(*flags) &&
307
((ionfs_nr = get_nfs_mount_nr()) > 0)) {
308
*flags |= I_F_HAS_NFS;
309
ionfs_nr += NR_NFS_PREALLOC;
311
/* Allocate structures for number of NFS directories found */
312
salloc_nfs(ionfs_nr);
277
318
***************************************************************************
278
* Save stats for current device or partition
319
* Save stats for current device, partition or NFS directory
279
320
***************************************************************************
281
void save_dev_stats(char *dev_name, int curr, struct io_stats *sdev)
322
void save_stats(char *name, int curr, void *st_io, int ioln_nr,
323
struct io_hdr_stats *st_hdr_ioln)
284
struct io_hdr_stats *st_hdr_iodev_i;
326
struct io_hdr_stats *st_hdr_ioln_i;
285
327
struct io_stats *st_iodev_i;
328
struct io_nfs_stats *st_ionfs_i;
287
/* Look for device in data table */
288
for (i = 0; i < iodev_nr; i++) {
289
st_hdr_iodev_i = st_hdr_iodev + i;
290
if (!strcmp(st_hdr_iodev_i->name, dev_name)) {
330
/* Look for device or NFS directory in data table */
331
for (i = 0; i < ioln_nr; i++) {
332
st_hdr_ioln_i = st_hdr_ioln + i;
333
if (!strcmp(st_hdr_ioln_i->name, name)) {
297
340
* This is a new device: look for an unused entry to store it.
298
341
* Thus we are able to handle dynamically registered devices.
300
for (i = 0; i < iodev_nr; i++) {
301
st_hdr_iodev_i = st_hdr_iodev + i;
302
if (!st_hdr_iodev_i->used) {
343
for (i = 0; i < ioln_nr; i++) {
344
st_hdr_ioln_i = st_hdr_ioln + i;
345
if (!st_hdr_ioln_i->used) {
303
346
/* Unused entry found... */
304
st_hdr_iodev_i->used = TRUE; /* Indicate it is now used */
305
strcpy(st_hdr_iodev_i->name, dev_name);
306
st_iodev_i = st_iodev[!curr] + i;
307
memset(st_iodev_i, 0, IO_STATS_SIZE);
347
st_hdr_ioln_i->used = TRUE; /* Indicate it is now used */
348
strcpy(st_hdr_ioln_i->name, name);
349
if (st_hdr_ioln == st_hdr_iodev) {
350
st_iodev_i = st_iodev[!curr] + i;
351
memset(st_iodev_i, 0, IO_STATS_SIZE);
354
st_ionfs_i = st_ionfs[!curr] + i;
355
memset(st_ionfs_i, 0, IO_NFS_STATS_SIZE);
313
st_hdr_iodev_i = st_hdr_iodev + i;
314
st_hdr_iodev_i->active = TRUE;
315
st_iodev_i = st_iodev[curr] + i;
362
st_hdr_ioln_i = st_hdr_ioln + i;
363
st_hdr_ioln_i->active = TRUE;
364
if (st_hdr_ioln == st_hdr_iodev) {
365
st_iodev_i = st_iodev[curr] + i;
366
*st_iodev_i = *((struct io_stats *) st_io);
369
st_ionfs_i = st_ionfs[curr] + i;
370
*st_ionfs_i = *((struct io_nfs_stats *) st_io);
318
/* else it was a new device but there was no free structure to store it */
374
* else it was a new device or NFS directory
375
* but there was no free structure to store it.
390
448
else if ((!strncmp(line, "cpu0", 4)) && (cpu_nr > 1)) {
392
450
* Read CPU line for proc#0 (if available).
393
* Useful to compute uptime reduced to one processor on SMP machines,
394
* with fewer risks to get an overflow...
451
* This is necessary to compute time interval since
452
* processors may be disabled (offline) sometimes.
453
* (Assume that proc#0 can never be offline).
396
455
cc_iowait = cc_hardirq = cc_softirq = cc_steal = 0;
397
456
sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu",
467
526
sdev.dk_drive = v_tmp[0];
468
527
sdev.dk_drive_rblk = v_tmp[1];
469
528
sdev.dk_drive_wblk = v_tmp[2];
470
save_dev_stats(dev_name, curr, &sdev);
529
save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
472
531
pos += strcspn(line + pos, " ") + 1;
475
534
/* Free structures corresponding to unregistered disks */
476
free_inactive_entries(iodev_nr);
535
free_inactive_entries(iodev_nr, st_hdr_iodev);
693
752
* No match: Use name generated from sysstat.ioconf data (if different
694
753
* from "nodev") works around known issues with EMC PowerPath.
696
strcpy(dev_name, ioc_dname);
755
strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
699
save_dev_stats(dev_name, curr, &sdev);
758
save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
704
763
/* Free structures corresponding to unregistered devices */
705
free_inactive_entries(iodev_nr);
764
free_inactive_entries(iodev_nr, st_hdr_iodev);
750
809
if ((ioc_dname = ioc_name(major, minor)) != NULL) {
751
810
if (strcmp(dev_name, ioc_dname) && strcmp(ioc_dname, K_NODEV))
752
811
/* Compensate for EMC PowerPath driver bug */
753
strcpy(dev_name, ioc_dname);
756
save_dev_stats(dev_name, curr, &sdev);
761
/* Free structures corresponding to unregistered devices */
762
free_inactive_entries(iodev_nr);
812
strncpy(dev_name, ioc_dname, MAX_NAME_LEN);
815
save_stats(dev_name, curr, &sdev, iodev_nr, st_hdr_iodev);
820
/* Free structures corresponding to unregistered devices */
821
free_inactive_entries(iodev_nr, st_hdr_iodev);
825
***************************************************************************
826
* Read NFS-mount directories stats from /proc/self/mountstats
827
***************************************************************************
829
void read_nfs_stat(int curr, int flags)
834
char nfs_name[MAX_NAME_LEN];
835
char mount[10], on[10], bytes[10], aux[32];
836
struct io_nfs_stats snfs;
838
/* Every I/O NFS entry is potentially unregistered */
839
set_entries_inactive(ionfs_nr, st_hdr_ionfs);
841
if ((fp = fopen(NFSMOUNTSTATS, "r")) == NULL)
844
sprintf(aux, "%%%ds %%10s %%10s",
845
MAX_NAME_LEN < 200 ? MAX_NAME_LEN : 200);
847
while (fgets(line, 256, fp) != NULL) {
849
/* read NFS directory name */
850
if (!strncmp(line, "device", 6)) {
852
sscanf(line + 6, aux, nfs_name, mount, on);
853
if ((!strncmp(mount, "mounted", 7)) && (!strncmp(on, "on", 2))) {
858
sscanf(line, "%10s", bytes);
859
if (sw && (!strncmp(bytes, "bytes:", 6))) {
860
/* Read the stats for the last NFS-mounted directory */
861
i = sscanf(strstr(line, "bytes:") + 6, "%llu %llu %llu %llu %llu %llu",
862
&snfs.rd_normal_bytes, &snfs.wr_normal_bytes, &snfs.rd_direct_bytes,
863
&snfs.wr_direct_bytes, &snfs.rd_server_bytes, &snfs.wr_server_bytes);
865
save_stats(nfs_name, curr, &snfs, ionfs_nr, st_hdr_ionfs);
872
/* Free structures corresponding to unregistered devices */
873
free_inactive_entries(ionfs_nr, st_hdr_ionfs);
788
899
***************************************************************************
789
* Display stats header
900
* Display disk stats header
790
901
***************************************************************************
792
void write_stat_header(int flags, int *fctr)
903
void write_disk_stat_header(int flags, int *fctr)
794
905
if (DISPLAY_EXTENDED(flags)) {
795
906
/* Extended stats */
796
printf("Device: rrqm/s wrqm/s r/s w/s");
907
printf("Device: rrqm/s wrqm/s r/s w/s");
797
908
if (DISPLAY_MEGABYTES(flags)) {
798
909
printf(" rMB/s wMB/s");
827
938
***************************************************************************
939
* Display NFS stats header
940
***************************************************************************
942
void write_nfs_stat_header(int flags, int *fctr)
944
printf("Filesystem: ");
945
if (DISPLAY_KILOBYTES(flags)) {
946
printf(" rkB_nor/s wkB_nor/s rkB_dir/s wkB_dir/s rkB_svr/s wkB_svr/s\n");
949
else if (DISPLAY_MEGABYTES(flags)) {
950
printf(" rMB_nor/s wMB_nor/s rMB_dir/s wMB_dir/s rMB_svr/s wMB_svr/s\n");
954
printf(" rBlk_nor/s wBlk_nor/s rBlk_dir/s wBlk_dir/s rBlk_svr/s wBlk_svr/s\n");
961
***************************************************************************
828
962
* Display extended stats, read from /proc/{diskstats,partitions} or /sys
829
963
***************************************************************************
866
1000
arqsz = nr_ios ? (rd_sec + wr_sec) / nr_ios : 0.0;
868
printf("%-13s", shi->name);
869
if (strlen(shi->name) > 10)
871
/* rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await svctm %util */
872
printf(" %8.2f %8.2f %5.2f %5.2f %8.2f %8.2f %8.2f %8.2f %7.2f %6.2f %6.2f\n",
1002
/* DEV rrq/s wrq/s r/s w/s rsec wsec rqsz qusz await svctm %util */
1003
printf("%-13s %8.2f %8.2f %7.2f %7.2f %8.2f %8.2f %8.2f %8.2f %7.2f %6.2f %6.2f\n",
873
1005
S_VALUE(ioj->rd_merges, ioi->rd_merges, itv),
874
1006
S_VALUE(ioj->wr_merges, ioi->wr_merges, itv),
875
1007
S_VALUE(ioj->rd_ios, ioi->rd_ios, itv),
935
1065
***************************************************************************
1066
* Write NFS stats read from /proc/self/mountstats
1067
***************************************************************************
1069
void write_nfs_stat(int curr, unsigned long long itv, int flags, int fctr,
1070
struct io_hdr_stats *shi, struct io_nfs_stats *ioni,
1071
struct io_nfs_stats *ionj)
1073
printf("%-22s %12.2f %12.2f %12.2f %12.2f %12.2f %12.2f\n",
1075
S_VALUE(ionj->rd_normal_bytes, ioni->rd_normal_bytes, itv) / fctr,
1076
S_VALUE(ionj->wr_normal_bytes, ioni->wr_normal_bytes, itv) / fctr,
1077
S_VALUE(ionj->rd_direct_bytes, ioni->rd_direct_bytes, itv) / fctr,
1078
S_VALUE(ionj->wr_direct_bytes, ioni->wr_direct_bytes, itv) / fctr,
1079
S_VALUE(ionj->rd_server_bytes, ioni->rd_server_bytes, itv) / fctr,
1080
S_VALUE(ionj->wr_server_bytes, ioni->wr_server_bytes, itv) / fctr);
1085
***************************************************************************
936
1086
* Print everything now (stats and uptime)
937
1087
***************************************************************************
939
int write_stat(int curr, int flags, struct tm *loc_time)
1089
int write_stat(int curr, int flags, struct tm *rectime)
941
1091
int dev, i, fctr = 1;
942
1092
unsigned long long itv;
943
struct io_hdr_stats *shi = st_hdr_iodev;
944
struct io_stats *ioi, *ioj;
1093
struct io_hdr_stats *shi;
945
1094
struct io_dlist *st_dev_list_i;
1206
if (DISPLAY_NFS(flags)) {
1207
struct io_nfs_stats *ioni, *ionj;
1211
/* Display NFS stats header */
1212
write_nfs_stat_header(flags, &fctr);
1214
if (!HAS_NFS(flags)) {
1220
for (i = 0; i < ionfs_nr; i++, shi++) {
1223
ioni = st_ionfs[curr] + i;
1224
ionj = st_ionfs[!curr] + i;
1225
write_nfs_stat(curr, itv, flags, fctr, shi, ioni, ionj);
1237
/* Linux does not provide extended stats for partitions */
1420
/* Default: Display CPU and DISK reports */
1421
if (!DISPLAY_CPU(flags) && !DISPLAY_DISK(flags) && !DISPLAY_NFS(flags))
1422
flags |= I_D_CPU + I_D_DISK;
1424
* Also display DISK reports if options -p, -x or a device has been entered
1425
* on the command line.
1427
if (DISPLAY_PARTITIONS(flags) || DISPLAY_EXTENDED(flags) ||
1428
DISPLAY_UNFILTERED(flags))
1431
/* Linux does not provide extended stats for partitions nor for NFS directories */
1238
1432
if (DISPLAY_PARTITIONS(flags) && DISPLAY_EXTENDED(flags)) {
1239
1433
fprintf(stderr, _("-x and -p options are mutually exclusive\n"));