date and time created 88/09/19 15:01:31 by bostic
[unix-history] / usr / src / usr.sbin / iostat / iostat.c
index 7d5c18b..3076bd2 100644 (file)
@@ -1,14 +1,19 @@
-static char *sccsid = "@(#)iostat.c    4.3 (Berkeley) %G%";
+#ifndef lint
+static char *sccsid = "@(#)iostat.c    4.15 (Berkeley) 87/01/12";
+#endif
+
 /*
  * iostat
  */
 #include <stdio.h>
 /*
  * iostat
  */
 #include <stdio.h>
+#include <ctype.h>
 #include <nlist.h>
 #include <nlist.h>
+#include <signal.h>
+
 #include <sys/types.h>
 #include <sys/types.h>
+#include <sys/file.h>
 #include <sys/buf.h>
 #include <sys/buf.h>
-#include <sys/ubavar.h>
-#include <sys/mbavar.h>
-#include <sys/dk.h>
+#include <sys/dkstat.h>
 
 struct nlist nl[] = {
        { "_dk_busy" },
 
 struct nlist nl[] = {
        { "_dk_busy" },
@@ -29,40 +34,63 @@ struct nlist nl[] = {
 #define        X_CP_TIME       7
        { "_dk_mspw" },
 #define        X_DK_MSPW       8
 #define        X_CP_TIME       7
        { "_dk_mspw" },
 #define        X_DK_MSPW       8
+       { "_hz" },
+#define        X_HZ            9
+       { "_phz" },
+#define        X_PHZ           10
+       { "_dk_ndrive" },
+#define        X_DK_NDRIVE     11
+#ifdef vax
        { "_mbdinit" },
        { "_mbdinit" },
-#define X_MBDINIT      9
+#define X_MBDINIT      (X_DK_NDRIVE+1)
        { "_ubdinit" },
        { "_ubdinit" },
-#define X_UBDINIT      10
+#define X_UBDINIT      (X_DK_NDRIVE+2)
+#endif
+#ifdef tahoe
+#define        X_VBDINIT       (X_DK_NDRIVE+1)
+       { "_vbdinit" },
+#endif
        { 0 },
 };
 
        { 0 },
 };
 
-char dr_name[DK_NDRIVE][10];
+char   **dr_name;
+int    *dr_select;
+float  *dk_mspw;
+int    dk_ndrive;
+int    ndrives = 0;
+#ifdef vax
+char   *defdrives[] = { "hp0", "hp1", "hp2",  0 };
+#else
+char   *defdrives[] = { 0 };
+#endif
 
 
-struct
-{
+struct {
        int     dk_busy;
        long    cp_time[CPUSTATES];
        int     dk_busy;
        long    cp_time[CPUSTATES];
-       long    dk_time[DK_NDRIVE];
-       long    dk_wds[DK_NDRIVE];
-       long    dk_seek[DK_NDRIVE];
-       long    dk_xfer[DK_NDRIVE];
-       float   dk_mspw[DK_NDRIVE];
+       long    *dk_time;
+       long    *dk_wds;
+       long    *dk_seek;
+       long    *dk_xfer;
        long    tk_nin;
        long    tk_nout;
 } s, s1;
 
 int    mf;
        long    tk_nin;
        long    tk_nout;
 } s, s1;
 
 int    mf;
+int    hz;
+int    phz;
 double etime;
 double etime;
+int    tohdr = 1;
+int    printhdr();
 
 main(argc, argv)
 
 main(argc, argv)
-char *argv[];
+       char *argv[];
 {
        extern char *ctime();
        register  i;
 {
        extern char *ctime();
        register  i;
-       int iter;
+       int iter, ndrives;
        double f1, f2;
        long t;
        double f1, f2;
        long t;
-       int tohdr = 1;
+       char *arg, **cp, name[6], buf[BUFSIZ];
 
        nlist("/vmunix", nl);
        if(nl[X_DK_BUSY].n_type == 0) {
 
        nlist("/vmunix", nl);
        if(nl[X_DK_BUSY].n_type == 0) {
@@ -75,50 +103,100 @@ char *argv[];
                exit(1);
        }
        iter = 0;
                exit(1);
        }
        iter = 0;
-       while (argc>1&&argv[1][0]=='-') {
-               argc--;
-               argv++;
+       for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
+               ;
+       if (nl[X_DK_NDRIVE].n_value == 0) {
+               printf("dk_ndrive undefined in system\n");
+               exit(1);
+       }
+       lseek(mf, nl[X_DK_NDRIVE].n_value, L_SET);
+       read(mf, &dk_ndrive, sizeof (dk_ndrive));
+       if (dk_ndrive <= 0) {
+               printf("dk_ndrive %d\n", dk_ndrive);
+               exit(1);
        }
        }
-       lseek(mf, (long)nl[X_DK_MSPW].n_value, 0);
-       read(mf, s.dk_mspw, sizeof s.dk_mspw);
-       for (i = 0; i < DK_NDRIVE; i++)
+       dr_select = (int *)calloc(dk_ndrive, sizeof (int));
+       dr_name = (char **)calloc(dk_ndrive, sizeof (char *));
+       dk_mspw = (float *)calloc(dk_ndrive, sizeof (float));
+#define        allocate(e, t) \
+    s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \
+    s1./**/e = (t *)calloc(dk_ndrive, sizeof (t));
+       allocate(dk_time, long);
+       allocate(dk_wds, long);
+       allocate(dk_seek, long);
+       allocate(dk_xfer, long);
+       for (arg = buf, i = 0; i < dk_ndrive; i++) {
+               dr_name[i] = arg;
                sprintf(dr_name[i], "dk%d", i);
                sprintf(dr_name[i], "dk%d", i);
+               arg += strlen(dr_name[i]) + 1;
+       }
        read_names();
        read_names();
-       if(argc > 2)
-               iter = atoi(argv[2]);
+       lseek(mf, (long)nl[X_HZ].n_value, L_SET);
+       read(mf, &hz, sizeof hz);
+       lseek(mf, (long)nl[X_PHZ].n_value, L_SET);
+       read(mf, &phz, sizeof phz);
+       if (phz)
+               hz = phz;
+       lseek(mf, (long)nl[X_DK_MSPW].n_value, L_SET);
+       read(mf, dk_mspw, dk_ndrive*sizeof (dk_mspw));
+       /*
+        * Choose drives to be displayed.  Priority
+        * goes to (in order) drives supplied as arguments,
+        * default drives.  If everything isn't filled
+        * in and there are drives not taken care of,
+        * display the first few that fit.
+        */
+       ndrives = 0;
+       while (argc > 0 && !isdigit(argv[0][0])) {
+               for (i = 0; i < dk_ndrive; i++) {
+                       if (strcmp(dr_name[i], argv[0]))
+                               continue;
+                       dr_select[i] = 1;
+                       ndrives++;
+               }
+               argc--, argv++;
+       }
+       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
+               if (dr_select[i] || dk_mspw[i] == 0.0)
+                       continue;
+               for (cp = defdrives; *cp; cp++)
+                       if (strcmp(dr_name[i], *cp) == 0) {
+                               dr_select[i] = 1;
+                               ndrives++;
+                               break;
+                       }
+       }
+       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
+               if (dr_select[i])
+                       continue;
+               dr_select[i] = 1;
+               ndrives++;
+       }
+       if (argc > 1)
+               iter = atoi(argv[1]);
+       signal(SIGCONT, printhdr);
 loop:
 loop:
-       if (--tohdr == 0) {
-               printf("      tty");
-               for (i = 0; i < DK_NDRIVE; i++)
-                       if (s.dk_mspw[i] != 0.0)
-                               printf("          %3.3s ", dr_name[i]);
-               printf("         cpu\n");
-               printf(" tin tout");
-               for (i = 0; i < DK_NDRIVE; i++)
-                       if (s.dk_mspw[i] != 0.0)
-                               printf(" sps tps msps ");
-               printf(" us ni sy id\n");
-               tohdr = 19;
-       }
-       lseek(mf, (long)nl[X_DK_BUSY].n_value, 0);
+       if (--tohdr == 0)
+               printhdr();
+       lseek(mf, (long)nl[X_DK_BUSY].n_value, L_SET);
        read(mf, &s.dk_busy, sizeof s.dk_busy);
        read(mf, &s.dk_busy, sizeof s.dk_busy);
-       lseek(mf, (long)nl[X_DK_TIME].n_value, 0);
-       read(mf, s.dk_time, sizeof s.dk_time);
-       lseek(mf, (long)nl[X_DK_XFER].n_value, 0);
-       read(mf, s.dk_xfer, sizeof s.dk_xfer);
-       lseek(mf, (long)nl[X_DK_WDS].n_value, 0);
-       read(mf, s.dk_wds, sizeof s.dk_wds);
-       lseek(mf, (long)nl[X_TK_NIN].n_value, 0);
+       lseek(mf, (long)nl[X_DK_TIME].n_value, L_SET);
+       read(mf, s.dk_time, dk_ndrive*sizeof (long));
+       lseek(mf, (long)nl[X_DK_XFER].n_value, L_SET);
+       read(mf, s.dk_xfer, dk_ndrive*sizeof (long));
+       lseek(mf, (long)nl[X_DK_WDS].n_value, L_SET);
+       read(mf, s.dk_wds, dk_ndrive*sizeof (long));
+       lseek(mf, (long)nl[X_DK_SEEK].n_value, L_SET);
+       read(mf, s.dk_seek, dk_ndrive*sizeof (long));
+       lseek(mf, (long)nl[X_TK_NIN].n_value, L_SET);
        read(mf, &s.tk_nin, sizeof s.tk_nin);
        read(mf, &s.tk_nin, sizeof s.tk_nin);
-       lseek(mf, (long)nl[X_TK_NOUT].n_value, 0);
+       lseek(mf, (long)nl[X_TK_NOUT].n_value, L_SET);
        read(mf, &s.tk_nout, sizeof s.tk_nout);
        read(mf, &s.tk_nout, sizeof s.tk_nout);
-       lseek(mf, (long)nl[X_DK_SEEK].n_value, 0);
-       read(mf, s.dk_seek, sizeof s.dk_seek);
-       lseek(mf, (long)nl[X_CP_TIME].n_value, 0);
+       lseek(mf, (long)nl[X_CP_TIME].n_value, L_SET);
        read(mf, s.cp_time, sizeof s.cp_time);
        read(mf, s.cp_time, sizeof s.cp_time);
-       lseek(mf, (long)nl[X_DK_MSPW].n_value, 0);
-       read(mf, s.dk_mspw, sizeof s.dk_mspw);
-       for (i = 0; i < DK_NDRIVE; i++) {
+       for (i = 0; i < dk_ndrive; i++) {
+               if (!dr_select[i])
+                       continue;
 #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
                X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
        }
 #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t
                X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time);
        }
@@ -131,53 +209,61 @@ loop:
        }
        if (etime == 0.0)
                etime = 1.0;
        }
        if (etime == 0.0)
                etime = 1.0;
-       etime /= 60.0;
+       etime /= (float) hz;
        printf("%4.0f%5.0f", s.tk_nin/etime, s.tk_nout/etime);
        printf("%4.0f%5.0f", s.tk_nin/etime, s.tk_nout/etime);
-       for (i=0; i<DK_NDRIVE; i++)
-               if (s.dk_mspw[i] != 0.0)
+       for (i=0; i<dk_ndrive; i++)
+               if (dr_select[i])
                        stats(i);
        for (i=0; i<CPUSTATES; i++)
                stat1(i);
        printf("\n");
                        stats(i);
        for (i=0; i<CPUSTATES; i++)
                stat1(i);
        printf("\n");
+       fflush(stdout);
 contin:
 contin:
-       --iter;
-       if(iter)
-       if(argc > 1) {
-               sleep(atoi(argv[1]));
+       if (--iter && argc > 0) {
+               sleep(atoi(argv[0]));
                goto loop;
        }
 }
 
                goto loop;
        }
 }
 
+printhdr()
+{
+       register int i;
+
+       printf("      tty");
+       for (i = 0; i < dk_ndrive; i++)
+               if (dr_select[i])
+                       printf("          %3.3s ", dr_name[i]);
+       printf("         cpu\n");
+       printf(" tin tout");
+       for (i = 0; i < dk_ndrive; i++)
+               if (dr_select[i])
+                       printf(" bps tps msps ");
+       printf(" us ni sy id\n");
+       tohdr = 19;
+}
+
 stats(dn)
 {
        register i;
        double atime, words, xtime, itime;
 
 stats(dn)
 {
        register i;
        double atime, words, xtime, itime;
 
-       if (s.dk_mspw[dn] == 0.0) {
+       if (dk_mspw[dn] == 0.0) {
                printf("%4.0f%4.0f%5.1f ", 0.0, 0.0, 0.0);
                return;
        }
        atime = s.dk_time[dn];
                printf("%4.0f%4.0f%5.1f ", 0.0, 0.0, 0.0);
                return;
        }
        atime = s.dk_time[dn];
-       atime /= 60.0;
+       atime /= (float) hz;
        words = s.dk_wds[dn]*32.0;      /* number of words transferred */
        words = s.dk_wds[dn]*32.0;      /* number of words transferred */
-       xtime = s.dk_mspw[dn]*words;    /* transfer time */
+       xtime = dk_mspw[dn]*words;      /* transfer time */
        itime = atime - xtime;          /* time not transferring */
        itime = atime - xtime;          /* time not transferring */
-/*
-       printf("\ndn %d, words %8.2f, atime %6.2f, xtime %6.2f, itime %6.2f\n",
-           dn, words, atime, xtime, itime);
-*/
        if (xtime < 0)
                itime += xtime, xtime = 0;
        if (itime < 0)
                xtime += itime, itime = 0;
        if (xtime < 0)
                itime += xtime, xtime = 0;
        if (itime < 0)
                xtime += itime, itime = 0;
-       printf("%4.0f", s.dk_seek[dn]/etime);
+       printf("%4.0f", words/512/etime);
        printf("%4.0f", s.dk_xfer[dn]/etime);
        printf("%5.1f ",
            s.dk_seek[dn] ? itime*1000./s.dk_seek[dn] : 0.0);
        printf("%4.0f", s.dk_xfer[dn]/etime);
        printf("%5.1f ",
            s.dk_seek[dn] ? itime*1000./s.dk_seek[dn] : 0.0);
-/*
-       printf("%4.1f",
-           s.dk_xfer[dn] ? xtime*1000./s.dk_xfer[dn] : 0.0);
-*/
 }
 
 stat1(o)
 }
 
 stat1(o)
@@ -190,15 +276,16 @@ stat1(o)
                time += s.cp_time[i];
        if (time == 0.0)
                time = 1.0;
                time += s.cp_time[i];
        if (time == 0.0)
                time = 1.0;
-       printf("%3.0f", 100*s.cp_time[o]/time);
+       printf("%3.0f", 100.*s.cp_time[o]/time);
 }
 
 }
 
-/*
- * Read the drive names out of kmem.
- * ARGH ARGH ARGH ARGH !!!!!!!!!!!!
- */
+#define steal(where, var) \
+    lseek(mf, where, L_SET); read(mf, &var, sizeof var);
+
+#ifdef vax
+#include <vaxuba/ubavar.h>
+#include <vaxmba/mbavar.h>
 
 
-#define steal(where, var) lseek(mf, where, 0); read(mf, &var, sizeof var);
 read_names()
 {
        struct mba_device mdev;
 read_names()
 {
        struct mba_device mdev;
@@ -211,13 +298,11 @@ read_names()
 
        mp = (struct mba_device *) nl[X_MBDINIT].n_value;
        up = (struct uba_device *) nl[X_UBDINIT].n_value;
 
        mp = (struct mba_device *) nl[X_MBDINIT].n_value;
        up = (struct uba_device *) nl[X_UBDINIT].n_value;
-       if (mp == 0 || up == 0)
-       {
+       if (up == 0) {
                fprintf(stderr, "iostat: Disk init info not in namelist\n");
                exit(1);
        }
                fprintf(stderr, "iostat: Disk init info not in namelist\n");
                exit(1);
        }
-       while(1)
-       {
+       if (mp) for (;;) {
                steal(mp++, mdev);
                if (mdev.mi_driver == 0)
                        break;
                steal(mp++, mdev);
                if (mdev.mi_driver == 0)
                        break;
@@ -225,10 +310,42 @@ read_names()
                        continue;
                steal(mdev.mi_driver, mdrv);
                steal(mdrv.md_dname, two_char);
                        continue;
                steal(mdev.mi_driver, mdrv);
                steal(mdrv.md_dname, two_char);
-               sprintf(dr_name[mdev.mi_dk], "%c%c%d", cp[0], cp[1], mdev.mi_unit);
+               sprintf(dr_name[mdev.mi_dk], "%c%c%d",
+                   cp[0], cp[1], mdev.mi_unit);
+       }
+       if (up) for (;;) {
+               steal(up++, udev);
+               if (udev.ui_driver == 0)
+                       break;
+               if (udev.ui_dk < 0 || udev.ui_alive == 0)
+                       continue;
+               steal(udev.ui_driver, udrv);
+               steal(udrv.ud_dname, two_char);
+               sprintf(dr_name[udev.ui_dk], "%c%c%d",
+                   cp[0], cp[1], udev.ui_unit);
+       }
+}
+#endif
+
+#ifdef tahoe
+#include <tahoevba/vbavar.h>
+
+/*
+ * Read the drive names out of kmem.
+ */
+read_names()
+{
+       struct vba_device udev, *up;
+       struct vba_driver udrv;
+       short two_char;
+       char *cp = (char *)&two_char;
+
+       up = (struct vba_device *) nl[X_VBDINIT].n_value;
+       if (up == 0) {
+               fprintf(stderr, "vmstat: Disk init info not in namelist\n");
+               exit(1);
        }
        }
-       while(1)
-       {
+       for (;;) {
                steal(up++, udev);
                if (udev.ui_driver == 0)
                        break;
                steal(up++, udev);
                if (udev.ui_driver == 0)
                        break;
@@ -236,6 +353,8 @@ read_names()
                        continue;
                steal(udev.ui_driver, udrv);
                steal(udrv.ud_dname, two_char);
                        continue;
                steal(udev.ui_driver, udrv);
                steal(udrv.ud_dname, two_char);
-               sprintf(dr_name[udev.ui_dk], "%c%c%d", cp[0], cp[1], udev.ui_unit);
+               sprintf(dr_name[udev.ui_dk], "%c%c%d",
+                    cp[0], cp[1], udev.ui_unit);
        }
 }
        }
 }
+#endif