111 static  uint_t  tohdr = 1;
 112 
 113 /*
 114  * If we're in raw format, have we printed a header? We only do it
 115  * once for raw but we emit it every REPRINT lines in non-raw format.
 116  * This applies only for the basic header. The extended header is
 117  * done only once in both formats.
 118  */
 119 static  uint_t  hdr_out;
 120 
 121 /*
 122  * Flags representing arguments from command line
 123  */
 124 static  uint_t  do_tty;                 /* show tty info (-t) */
 125 static  uint_t  do_disk;                /* show disk info per selected */
 126                                         /* format (-d, -D, -e, -E, -x -X -Y) */
 127 static  uint_t  do_cpu;                 /* show cpu info (-c) */
 128 static  uint_t  do_interval;            /* do intervals (-I) */
 129 static  int     do_partitions;          /* per-partition stats (-p) */
 130 static  int     do_partitions_only;     /* per-partition stats only (-P) */
 131                                         /* no per-device stats for disks */
 132 static  uint_t  do_conversions;         /* display disks as cXtYdZ (-n) */
 133 static  uint_t  do_megabytes;           /* display data in MB/sec (-M) */
 134 static  uint_t  do_controller;          /* display controller info (-C) */
 135 static  uint_t  do_raw;                 /* emit raw format (-r) */
 136 static  uint_t  timestamp_fmt = NODATE; /* timestamp  each display (-T) */
 137 static  uint_t  do_devid;               /* -E should show devid */
 138 
 139 /*
 140  * Default number of disk drives to be displayed in basic format
 141  */
 142 #define DEFAULT_LIMIT   4
 143 
 144 struct iodev_filter df;
 145 
 146 static  uint_t  suppress_state;         /* skip state change messages */
 147 static  uint_t  suppress_zero;          /* skip zero valued lines */
 148 static  uint_t  show_mountpts;          /* show mount points */
 149 static  int     interval;               /* interval (seconds) to output */
 150 static  int     iter;                   /* iterations from command line */
 151 
 152 #define SMALL_SCRATCH_BUFLEN    MAXNAMELEN
 153 
 154 static int      iodevs_nl;              /* name field width */
 155 #define IODEVS_NL_MIN           6       /* not too thin for "device" */
 156 #define IODEVS_NL_MAX           24      /* but keep full width under 80 */
 157 
 158 static  char    disk_header[132];
 159 static  uint_t  dh_len;                 /* disk header length for centering */
 160 static  int     lineout;                /* data waiting to be printed? */
 161 
 162 static struct snapshot *newss;
 163 static struct snapshot *oldss;
 164 static  double  getime;                 /* elapsed time */
 165 static  double  percent;                /* 100 / etime */
 166 
 167 /*
 168  * List of functions to be called which will construct the desired output
 169  */
 170 static format_t *formatter_list;
 171 static format_t *formatter_end;
 172 
 173 static u_longlong_t     ull_delta(u_longlong_t, u_longlong_t);
 174 static uint_t   u32_delta(uint_t, uint_t);
 175 static void setup(void (*nfunc)(void));
 176 static void print_tty_hdr1(void);
 
 
 208         hrtime_t start_n;
 209         hrtime_t period_n;
 210 
 211         (void) setlocale(LC_ALL, "");
 212 #if !defined(TEXT_DOMAIN)               /* Should be defined by cc -D */
 213 #define TEXT_DOMAIN "SYS_TEST"          /* Use this only if it weren't */
 214 #endif
 215         (void) textdomain(TEXT_DOMAIN);
 216 
 217         do_args(argc, argv);
 218 
 219         /*
 220          * iostat historically showed CPU changes, even though
 221          * it doesn't provide much useful information
 222          */
 223         types |= SNAP_CPUS;
 224 
 225         if (do_disk)
 226                 types |= SNAP_IODEVS;
 227 
 228         if (do_disk && !do_partitions_only)
 229                 df.if_allowed_types |= IODEV_DISK;
 230         if (do_disk & DISK_IOPATH_LI) {
 231                 df.if_allowed_types |= IODEV_IOPATH_LTI;
 232                 types |= SNAP_IOPATHS_LI;
 233         }
 234         if (do_disk & DISK_IOPATH_LTI) {
 235                 df.if_allowed_types |= IODEV_IOPATH_LTI;
 236                 types |= SNAP_IOPATHS_LTI;
 237         }
 238         if (do_disk & DISK_ERROR_MASK)
 239                 types |= SNAP_IODEV_ERRORS;
 240         if (do_partitions || do_partitions_only)
 241                 df.if_allowed_types |= IODEV_PARTITION;
 242         if (do_conversions)
 243                 types |= SNAP_IODEV_PRETTY;
 244         if (do_devid)
 245                 types |= SNAP_IODEV_DEVID;
 246         if (do_controller) {
 247                 if (!(do_disk & PRINT_VERTICAL) ||
 248                     (do_disk & DISK_EXTENDED_ERRORS))
 249                         fail(0, "-C can only be used with -e or -x.");
 250                 types |= SNAP_CONTROLLERS;
 251                 df.if_allowed_types |= IODEV_CONTROLLER;
 252         }
 253 
 254         hz = sysconf(_SC_CLK_TCK);
 255 
 256         /*
 257          * Undocumented behavior - sending a SIGCONT will result
 258          * in a new header being emitted. Used only if we're not
 259          * doing extended headers. This is a historical
 260          * artifact.
 261          */
 
 947             "\t\t-c:    report percentage of time system has spent\n"
 948             "\t\t\tin user/system/dtrace/idle mode\n"
 949             "\t\t-C:    report disk statistics by controller\n"
 950             "\t\t-d:    display disk Kb/sec, transfers/sec, avg. \n"
 951             "\t\t\tservice time in milliseconds  \n"
 952             "\t\t-D:    display disk reads/sec, writes/sec, \n"
 953             "\t\t\tpercentage disk utilization \n"
 954             "\t\t-e:    report device error summary statistics\n"
 955             "\t\t-E:    report extended device error statistics\n"
 956             "\t\t-i:    show device IDs for -E output\n"
 957             "\t\t-I:    report the counts in each interval,\n"
 958             "\t\t\tinstead of rates, where applicable\n"
 959             "\t\t-l n:  Limit the number of disks to n\n"
 960             "\t\t-m:    Display mount points (most useful with -p)\n"
 961             "\t\t-M:    Display data throughput in MB/sec "
 962             "instead of Kb/sec\n"
 963             "\t\t-n:    convert device names to cXdYtZ format\n"
 964             "\t\t-p:    report per-partition disk statistics\n"
 965             "\t\t-P:    report per-partition disk statistics only,\n"
 966             "\t\t\tno per-device disk statistics\n"
 967             "\t\t-r:    Display data in comma separated format\n"
 968             "\t\t-s:    Suppress state change messages\n"
 969             "\t\t-T d|u Display a timestamp in date (d) or unix "
 970             "time_t (u)\n"
 971             "\t\t-t:    display chars read/written to terminals\n"
 972             "\t\t-x:    display extended disk statistics\n"
 973             "\t\t-X:    display I/O path statistics\n"
 974             "\t\t-Y:    display I/O path (I/T/L) statistics\n"
 975             "\t\t-z:    Suppress entries with all zero values\n");
 976         exit(1);
 977 }
 978 
 979 /*ARGSUSED*/
 980 static void
 981 show_disk_errors(void *v1, void *v2, void *d)
 982 {
 983         struct iodev_snapshot *disk = (struct iodev_snapshot *)v2;
 984         kstat_named_t *knp;
 985         size_t  col;
 986         int     i, len;
 
1065                         }
1066                 if ((col >= 62) || (i == 2)) {
1067                         do_newline();
1068                         col = 0;
1069                 }
1070         }
1071         if (col > 0) {
1072                 do_newline();
1073         }
1074         do_newline();
1075 }
1076 
1077 void
1078 do_args(int argc, char **argv)
1079 {
1080         int             c;
1081         int             errflg = 0;
1082         extern char     *optarg;
1083         extern int      optind;
1084 
1085         while ((c = getopt(argc, argv, "tdDxXYCciIpPnmMeEszrT:l:")) != EOF)
1086                 switch (c) {
1087                 case 't':
1088                         do_tty++;
1089                         break;
1090                 case 'd':
1091                         do_disk |= DISK_OLD;
1092                         break;
1093                 case 'D':
1094                         do_disk |= DISK_NEW;
1095                         break;
1096                 case 'x':
1097                         do_disk |= DISK_EXTENDED;
1098                         break;
1099                 case 'X':
1100                         if (do_disk & DISK_IOPATH_LTI)
1101                                 errflg++;       /* -Y already used */
1102                         else
1103                                 do_disk |= DISK_IOPATH_LI;
1104                         break;
1105                 case 'Y':
1106                         if (do_disk & DISK_IOPATH_LI)
1107                                 errflg++;       /* -X already used */
1108                         else
1109                                 do_disk |= DISK_IOPATH_LTI;
1110                         break;
1111                 case 'C':
1112                         do_controller++;
1113                         break;
1114                 case 'c':
1115                         do_cpu++;
1116                         break;
1117                 case 'I':
1118                         do_interval++;
1119                         break;
1120                 case 'p':
1121                         do_partitions++;
1122                         break;
1123                 case 'P':
1124                         do_partitions_only++;
1125                         break;
1126                 case 'n':
1127                         do_conversions++;
1128                         break;
1129                 case 'M':
1130                         do_megabytes++;
1131                         break;
1132                 case 'e':
1133                         do_disk |= DISK_ERRORS;
1134                         break;
1135                 case 'E':
1136                         do_disk |= DISK_EXTENDED_ERRORS;
1137                         break;
1138                 case 'i':
1139                         do_devid = 1;
1140                         break;
1141                 case 's':
1142                         suppress_state = 1;
1143                         break;
1144                 case 'z':
1145                         suppress_zero = 1;
 
 | 
 
 
 111 static  uint_t  tohdr = 1;
 112 
 113 /*
 114  * If we're in raw format, have we printed a header? We only do it
 115  * once for raw but we emit it every REPRINT lines in non-raw format.
 116  * This applies only for the basic header. The extended header is
 117  * done only once in both formats.
 118  */
 119 static  uint_t  hdr_out;
 120 
 121 /*
 122  * Flags representing arguments from command line
 123  */
 124 static  uint_t  do_tty;                 /* show tty info (-t) */
 125 static  uint_t  do_disk;                /* show disk info per selected */
 126                                         /* format (-d, -D, -e, -E, -x -X -Y) */
 127 static  uint_t  do_cpu;                 /* show cpu info (-c) */
 128 static  uint_t  do_interval;            /* do intervals (-I) */
 129 static  int     do_partitions;          /* per-partition stats (-p) */
 130 static  int     do_partitions_only;     /* per-partition stats only (-P) */
 131 static  int     do_zfs;
 132 static  int     do_zfs_only;
 133                                         /* no per-device stats for disks */
 134 static  uint_t  do_conversions;         /* display disks as cXtYdZ (-n) */
 135 static  uint_t  do_megabytes;           /* display data in MB/sec (-M) */
 136 static  uint_t  do_controller;          /* display controller info (-C) */
 137 static  uint_t  do_raw;                 /* emit raw format (-r) */
 138 static  uint_t  timestamp_fmt = NODATE; /* timestamp  each display (-T) */
 139 static  uint_t  do_devid;               /* -E should show devid */
 140 
 141 /*
 142  * Default number of disk drives to be displayed in basic format
 143  */
 144 #define DEFAULT_LIMIT   4
 145 
 146 struct iodev_filter df;
 147 
 148 static  uint_t  suppress_state;         /* skip state change messages */
 149 static  uint_t  suppress_zero;          /* skip zero valued lines */
 150 static  uint_t  show_mountpts;          /* show mount points */
 151 static  int     interval;               /* interval (seconds) to output */
 152 static  int     iter;                   /* iterations from command line */
 153 
 154 #define SMALL_SCRATCH_BUFLEN    MAXNAMELEN
 155 
 156 static int      iodevs_nl;              /* name field width */
 157 #define IODEVS_NL_MIN           6       /* not too thin for "device" */
 158 #define IODEVS_NL_MAX           64      /* but keep full width under 80 */
 159 
 160 static  char    disk_header[132];
 161 static  uint_t  dh_len;                 /* disk header length for centering */
 162 static  int     lineout;                /* data waiting to be printed? */
 163 
 164 static struct snapshot *newss;
 165 static struct snapshot *oldss;
 166 static  double  getime;                 /* elapsed time */
 167 static  double  percent;                /* 100 / etime */
 168 
 169 /*
 170  * List of functions to be called which will construct the desired output
 171  */
 172 static format_t *formatter_list;
 173 static format_t *formatter_end;
 174 
 175 static u_longlong_t     ull_delta(u_longlong_t, u_longlong_t);
 176 static uint_t   u32_delta(uint_t, uint_t);
 177 static void setup(void (*nfunc)(void));
 178 static void print_tty_hdr1(void);
 
 
 210         hrtime_t start_n;
 211         hrtime_t period_n;
 212 
 213         (void) setlocale(LC_ALL, "");
 214 #if !defined(TEXT_DOMAIN)               /* Should be defined by cc -D */
 215 #define TEXT_DOMAIN "SYS_TEST"          /* Use this only if it weren't */
 216 #endif
 217         (void) textdomain(TEXT_DOMAIN);
 218 
 219         do_args(argc, argv);
 220 
 221         /*
 222          * iostat historically showed CPU changes, even though
 223          * it doesn't provide much useful information
 224          */
 225         types |= SNAP_CPUS;
 226 
 227         if (do_disk)
 228                 types |= SNAP_IODEVS;
 229 
 230         if (do_disk && !do_partitions_only && !do_zfs_only)
 231                 df.if_allowed_types |= IODEV_DISK;
 232         if (do_disk & DISK_IOPATH_LI) {
 233                 df.if_allowed_types |= IODEV_IOPATH_LTI;
 234                 types |= SNAP_IOPATHS_LI;
 235         }
 236         if (do_disk & DISK_IOPATH_LTI) {
 237                 df.if_allowed_types |= IODEV_IOPATH_LTI;
 238                 types |= SNAP_IOPATHS_LTI;
 239         }
 240         if (do_disk & DISK_ERROR_MASK)
 241                 types |= SNAP_IODEV_ERRORS;
 242         if (do_partitions || do_partitions_only)
 243                 df.if_allowed_types |= IODEV_PARTITION;
 244         if (do_zfs || do_zfs_only)
 245                 df.if_allowed_types |= IODEV_ZFS;
 246         if (do_conversions)
 247                 types |= SNAP_IODEV_PRETTY;
 248         if (do_devid)
 249                 types |= SNAP_IODEV_DEVID;
 250         if (do_controller) {
 251                 if (!(do_disk & PRINT_VERTICAL) ||
 252                     (do_disk & DISK_EXTENDED_ERRORS))
 253                         fail(0, "-C can only be used with -e or -x.");
 254                 types |= SNAP_CONTROLLERS;
 255                 df.if_allowed_types |= IODEV_CONTROLLER;
 256         }
 257 
 258         hz = sysconf(_SC_CLK_TCK);
 259 
 260         /*
 261          * Undocumented behavior - sending a SIGCONT will result
 262          * in a new header being emitted. Used only if we're not
 263          * doing extended headers. This is a historical
 264          * artifact.
 265          */
 
 951             "\t\t-c:    report percentage of time system has spent\n"
 952             "\t\t\tin user/system/dtrace/idle mode\n"
 953             "\t\t-C:    report disk statistics by controller\n"
 954             "\t\t-d:    display disk Kb/sec, transfers/sec, avg. \n"
 955             "\t\t\tservice time in milliseconds  \n"
 956             "\t\t-D:    display disk reads/sec, writes/sec, \n"
 957             "\t\t\tpercentage disk utilization \n"
 958             "\t\t-e:    report device error summary statistics\n"
 959             "\t\t-E:    report extended device error statistics\n"
 960             "\t\t-i:    show device IDs for -E output\n"
 961             "\t\t-I:    report the counts in each interval,\n"
 962             "\t\t\tinstead of rates, where applicable\n"
 963             "\t\t-l n:  Limit the number of disks to n\n"
 964             "\t\t-m:    Display mount points (most useful with -p)\n"
 965             "\t\t-M:    Display data throughput in MB/sec "
 966             "instead of Kb/sec\n"
 967             "\t\t-n:    convert device names to cXdYtZ format\n"
 968             "\t\t-p:    report per-partition disk statistics\n"
 969             "\t\t-P:    report per-partition disk statistics only,\n"
 970             "\t\t\tno per-device disk statistics\n"
 971             "\t\t-f:    report ZFS-level statistics for ZFS pool and\n"
 972             "\t\t\tindividual vdevs\n"
 973             "\t\t-F:    report ZFS pool and individual physical vdevs\n"
 974             "\t\t\tstatistics only, no per-device statistics\n"
 975             "\t\t-r:    Display data in comma separated format\n"
 976             "\t\t-s:    Suppress state change messages\n"
 977             "\t\t-T d|u Display a timestamp in date (d) or unix "
 978             "time_t (u)\n"
 979             "\t\t-t:    display chars read/written to terminals\n"
 980             "\t\t-x:    display extended disk statistics\n"
 981             "\t\t-X:    display I/O path statistics\n"
 982             "\t\t-Y:    display I/O path (I/T/L) statistics\n"
 983             "\t\t-z:    Suppress entries with all zero values\n");
 984         exit(1);
 985 }
 986 
 987 /*ARGSUSED*/
 988 static void
 989 show_disk_errors(void *v1, void *v2, void *d)
 990 {
 991         struct iodev_snapshot *disk = (struct iodev_snapshot *)v2;
 992         kstat_named_t *knp;
 993         size_t  col;
 994         int     i, len;
 
1073                         }
1074                 if ((col >= 62) || (i == 2)) {
1075                         do_newline();
1076                         col = 0;
1077                 }
1078         }
1079         if (col > 0) {
1080                 do_newline();
1081         }
1082         do_newline();
1083 }
1084 
1085 void
1086 do_args(int argc, char **argv)
1087 {
1088         int             c;
1089         int             errflg = 0;
1090         extern char     *optarg;
1091         extern int      optind;
1092 
1093         while ((c = getopt(argc, argv, "tdDxXYCciIpPfFnmMeEszrT:l:")) != EOF)
1094                 switch (c) {
1095                 case 't':
1096                         do_tty++;
1097                         break;
1098                 case 'd':
1099                         do_disk |= DISK_OLD;
1100                         break;
1101                 case 'D':
1102                         do_disk |= DISK_NEW;
1103                         break;
1104                 case 'x':
1105                         do_disk |= DISK_EXTENDED;
1106                         break;
1107                 case 'X':
1108                         if (do_disk & DISK_IOPATH_LTI)
1109                                 errflg++;       /* -Y already used */
1110                         else
1111                                 do_disk |= DISK_IOPATH_LI;
1112                         break;
1113                 case 'Y':
1114                         if (do_disk & DISK_IOPATH_LI)
1115                                 errflg++;       /* -X already used */
1116                         else
1117                                 do_disk |= DISK_IOPATH_LTI;
1118                         break;
1119                 case 'C':
1120                         do_controller++;
1121                         break;
1122                 case 'c':
1123                         do_cpu++;
1124                         break;
1125                 case 'I':
1126                         do_interval++;
1127                         break;
1128                 case 'p':
1129                         do_partitions++;
1130                         break;
1131                 case 'P':
1132                         do_partitions_only++;
1133                         break;
1134                 case 'f':
1135                         do_zfs++;
1136                         break;
1137                 case 'F':
1138                         do_zfs_only++;
1139                         break;
1140                 case 'n':
1141                         do_conversions++;
1142                         break;
1143                 case 'M':
1144                         do_megabytes++;
1145                         break;
1146                 case 'e':
1147                         do_disk |= DISK_ERRORS;
1148                         break;
1149                 case 'E':
1150                         do_disk |= DISK_EXTENDED_ERRORS;
1151                         break;
1152                 case 'i':
1153                         do_devid = 1;
1154                         break;
1155                 case 's':
1156                         suppress_state = 1;
1157                         break;
1158                 case 'z':
1159                         suppress_zero = 1;
 
 |