Commit | Line | Data |
---|---|---|
07ed1e09 | 1 | /* |
1e3c68be KM |
2 | * Copyright (c) 1980, 1992 Regents of the University of California. |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
07ed1e09 KM |
6 | */ |
7 | ||
8b38f7fc | 8 | #ifndef lint |
1e3c68be | 9 | static char sccsid[] = "@(#)iostat.c 5.13 (Berkeley) %G%"; |
07ed1e09 | 10 | #endif not lint |
8b38f7fc | 11 | |
5abc08c8 KB |
12 | #include <sys/param.h> |
13 | #include <sys/dkstat.h> | |
8b38f7fc | 14 | #include <sys/buf.h> |
8b38f7fc | 15 | |
5abc08c8 KB |
16 | #include <string.h> |
17 | #include <stdlib.h> | |
18 | #include <nlist.h> | |
19 | #include <paths.h> | |
20 | #include "systat.h" | |
21 | #include "extern.h" | |
8b38f7fc | 22 | |
86923762 | 23 | static struct nlist namelist[] = { |
eef33ea7 KB |
24 | #define X_DK_BUSY 0 |
25 | { "_dk_busy" }, | |
26 | #define X_DK_TIME 1 | |
27 | { "_dk_time" }, | |
28 | #define X_DK_XFER 2 | |
29 | { "_dk_xfer" }, | |
30 | #define X_DK_WDS 3 | |
31 | { "_dk_wds" }, | |
32 | #define X_DK_SEEK 4 | |
33 | { "_dk_seek" }, | |
34 | #define X_CP_TIME 5 | |
35 | { "_cp_time" }, | |
8b38f7fc | 36 | #ifdef vax |
eef33ea7 KB |
37 | #define X_MBDINIT (X_CP_TIME+1) |
38 | { "_mbdinit" }, | |
39 | #define X_UBDINIT (X_CP_TIME+2) | |
40 | { "_ubdinit" }, | |
8d7d38c3 SL |
41 | #endif |
42 | #ifdef tahoe | |
43 | #define X_VBDINIT (X_CP_TIME+1) | |
44 | { "_vbdinit" }, | |
8b38f7fc | 45 | #endif |
eef33ea7 | 46 | { "" }, |
8b38f7fc SL |
47 | }; |
48 | ||
855ff304 | 49 | static struct { |
eef33ea7 KB |
50 | int dk_busy; |
51 | long cp_time[CPUSTATES]; | |
52 | long *dk_time; | |
53 | long *dk_wds; | |
54 | long *dk_seek; | |
55 | long *dk_xfer; | |
8b38f7fc SL |
56 | } s, s1; |
57 | ||
855ff304 KM |
58 | static int linesperregion; |
59 | static double etime; | |
eef33ea7 KB |
60 | static int numbers = 0; /* default display bar graphs */ |
61 | static int msps = 0; /* default ms/seek shown */ | |
8b38f7fc | 62 | |
5abc08c8 KB |
63 | static int barlabels __P((int)); |
64 | static void histogram __P((double, int, double)); | |
65 | static int numlabels __P((int)); | |
66 | static int stats __P((int, int, int)); | |
67 | static void stat1 __P((int, int)); | |
2202cfef | 68 | |
5abc08c8 KB |
69 | |
70 | WINDOW * | |
71 | openiostat() | |
72 | { | |
73 | return (subwin(stdscr, LINES-1-5, 0, 5, 0)); | |
74 | } | |
75 | ||
76 | void | |
77 | closeiostat(w) | |
78 | WINDOW *w; | |
79 | { | |
80 | if (w == NULL) | |
81 | return; | |
82 | wclear(w); | |
83 | wrefresh(w); | |
84 | delwin(w); | |
85 | } | |
86 | ||
87 | int | |
8b38f7fc SL |
88 | initiostat() |
89 | { | |
86923762 KB |
90 | if (namelist[X_DK_BUSY].n_type == 0) { |
91 | if (kvm_nlist(kd, namelist)) { | |
92 | nlisterr(namelist); | |
5abc08c8 KB |
93 | return(0); |
94 | } | |
86923762 | 95 | if (namelist[X_DK_BUSY].n_type == 0) { |
eef33ea7 KB |
96 | error("Disk init information isn't in namelist"); |
97 | return(0); | |
98 | } | |
99 | } | |
c0b7e584 JB |
100 | if (! dkinit()) |
101 | return(0); | |
833d578b SL |
102 | if (dk_ndrive) { |
103 | #define allocate(e, t) \ | |
104 | s./**/e = (t *)calloc(dk_ndrive, sizeof (t)); \ | |
105 | s1./**/e = (t *)calloc(dk_ndrive, sizeof (t)); | |
106 | allocate(dk_time, long); | |
107 | allocate(dk_wds, long); | |
108 | allocate(dk_seek, long); | |
109 | allocate(dk_xfer, long); | |
110 | #undef allocate | |
111 | } | |
c0b7e584 | 112 | return(1); |
8b38f7fc SL |
113 | } |
114 | ||
5abc08c8 | 115 | void |
8b38f7fc SL |
116 | fetchiostat() |
117 | { | |
86923762 | 118 | if (namelist[X_DK_BUSY].n_type == 0) |
eef33ea7 | 119 | return; |
142cb8a1 MT |
120 | NREAD(X_DK_BUSY, &s.dk_busy, LONG); |
121 | NREAD(X_DK_TIME, s.dk_time, dk_ndrive * LONG); | |
122 | NREAD(X_DK_XFER, s.dk_xfer, dk_ndrive * LONG); | |
123 | NREAD(X_DK_WDS, s.dk_wds, dk_ndrive * LONG); | |
124 | NREAD(X_DK_SEEK, s.dk_seek, dk_ndrive * LONG); | |
125 | NREAD(X_CP_TIME, s.cp_time, sizeof s.cp_time); | |
8b38f7fc SL |
126 | } |
127 | ||
b5eefd1e SL |
128 | #define INSET 10 |
129 | ||
5abc08c8 | 130 | void |
8b38f7fc SL |
131 | labeliostat() |
132 | { | |
eef33ea7 | 133 | int row; |
8b38f7fc | 134 | |
86923762 | 135 | if (namelist[X_DK_BUSY].n_type == 0) { |
eef33ea7 KB |
136 | error("No dk_busy defined."); |
137 | return; | |
138 | } | |
139 | row = 0; | |
140 | wmove(wnd, row, 0); wclrtobot(wnd); | |
141 | mvwaddstr(wnd, row++, INSET, | |
142 | "/0 /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); | |
143 | mvwaddstr(wnd, row++, 0, "cpu user|"); | |
144 | mvwaddstr(wnd, row++, 0, " nice|"); | |
145 | mvwaddstr(wnd, row++, 0, " system|"); | |
146 | mvwaddstr(wnd, row++, 0, " idle|"); | |
147 | if (numbers) | |
148 | row = numlabels(row + 1); | |
149 | else | |
150 | row = barlabels(row + 1); | |
855ff304 KM |
151 | } |
152 | ||
2202cfef | 153 | static int |
855ff304 | 154 | numlabels(row) |
2202cfef | 155 | int row; |
855ff304 | 156 | { |
eef33ea7 | 157 | int i, col, regions, ndrives; |
855ff304 | 158 | |
eef33ea7 | 159 | #define COLWIDTH 14 |
edfbb71e | 160 | #define DRIVESPERLINE ((wnd->maxx - INSET) / COLWIDTH) |
833d578b SL |
161 | for (ndrives = 0, i = 0; i < dk_ndrive; i++) |
162 | if (dk_select[i]) | |
163 | ndrives++; | |
eef33ea7 KB |
164 | regions = howmany(ndrives, DRIVESPERLINE); |
165 | /* | |
166 | * Deduct -regions for blank line after each scrolling region. | |
167 | */ | |
edfbb71e | 168 | linesperregion = (wnd->maxy - row - regions) / regions; |
eef33ea7 KB |
169 | /* |
170 | * Minimum region contains space for two | |
171 | * label lines and one line of statistics. | |
172 | */ | |
173 | if (linesperregion < 3) | |
174 | linesperregion = 3; | |
175 | col = 0; | |
176 | for (i = 0; i < dk_ndrive; i++) | |
177 | if (dk_select[i] && dk_mspw[i] != 0.0) { | |
edfbb71e | 178 | if (col + COLWIDTH >= wnd->maxx - INSET) { |
eef33ea7 | 179 | col = 0, row += linesperregion + 1; |
edfbb71e | 180 | if (row > wnd->maxy - (linesperregion + 1)) |
eef33ea7 KB |
181 | break; |
182 | } | |
183 | mvwaddstr(wnd, row, col + 4, dr_name[i]); | |
184 | mvwaddstr(wnd, row + 1, col, "bps tps msps"); | |
185 | col += COLWIDTH; | |
186 | } | |
187 | if (col) | |
188 | row += linesperregion + 1; | |
189 | return (row); | |
855ff304 KM |
190 | } |
191 | ||
2202cfef | 192 | static int |
855ff304 | 193 | barlabels(row) |
eef33ea7 | 194 | int row; |
855ff304 | 195 | { |
eef33ea7 | 196 | int i; |
855ff304 | 197 | |
eef33ea7 KB |
198 | mvwaddstr(wnd, row++, INSET, |
199 | "/0 /5 /10 /15 /20 /25 /30 /35 /40 /45 /50"); | |
200 | linesperregion = 2 + msps; | |
201 | for (i = 0; i < dk_ndrive; i++) | |
202 | if (dk_select[i] && dk_mspw[i] != 0.0) { | |
edfbb71e | 203 | if (row > wnd->maxy - linesperregion) |
eef33ea7 KB |
204 | break; |
205 | mvwprintw(wnd, row++, 0, "%3.3s bps|", dr_name[i]); | |
206 | mvwaddstr(wnd, row++, 0, " tps|"); | |
207 | if (msps) | |
208 | mvwaddstr(wnd, row++, 0, " msps|"); | |
209 | } | |
210 | return (row); | |
8b38f7fc SL |
211 | } |
212 | ||
5abc08c8 KB |
213 | |
214 | void | |
8b38f7fc SL |
215 | showiostat() |
216 | { | |
eef33ea7 | 217 | register long t; |
c03898eb | 218 | register int i, row, col; |
8b38f7fc | 219 | |
86923762 | 220 | if (namelist[X_DK_BUSY].n_type == 0) |
eef33ea7 KB |
221 | return; |
222 | for (i = 0; i < dk_ndrive; i++) { | |
223 | #define X(fld) t = s.fld[i]; s.fld[i] -= s1.fld[i]; s1.fld[i] = t | |
224 | X(dk_xfer); X(dk_seek); X(dk_wds); X(dk_time); | |
225 | } | |
226 | etime = 0; | |
227 | for(i = 0; i < CPUSTATES; i++) { | |
228 | X(cp_time); | |
229 | etime += s.cp_time[i]; | |
230 | } | |
231 | if (etime == 0.0) | |
232 | etime = 1.0; | |
233 | etime /= (float) hz; | |
234 | row = 1; | |
5abc08c8 KB |
235 | |
236 | /* | |
237 | * Last CPU state not calculated yet. | |
238 | */ | |
239 | for (i = 0; i < CPUSTATES - 1; i++) | |
eef33ea7 KB |
240 | stat1(row++, i); |
241 | if (!numbers) { | |
242 | row += 2; | |
243 | for (i = 0; i < dk_ndrive; i++) | |
244 | if (dk_select[i] && dk_mspw[i] != 0.0) { | |
edfbb71e | 245 | if (row > wnd->maxy - linesperregion) |
eef33ea7 KB |
246 | break; |
247 | row = stats(row, INSET, i); | |
248 | } | |
249 | return; | |
250 | } | |
251 | col = 0; | |
252 | wmove(wnd, row + linesperregion, 0); | |
253 | wdeleteln(wnd); | |
254 | wmove(wnd, row + 3, 0); | |
255 | winsertln(wnd); | |
256 | for (i = 0; i < dk_ndrive; i++) | |
257 | if (dk_select[i] && dk_mspw[i] != 0.0) { | |
edfbb71e | 258 | if (col + COLWIDTH >= wnd->maxx) { |
eef33ea7 | 259 | col = 0, row += linesperregion + 1; |
edfbb71e | 260 | if (row > wnd->maxy - (linesperregion + 1)) |
eef33ea7 KB |
261 | break; |
262 | wmove(wnd, row + linesperregion, 0); | |
263 | wdeleteln(wnd); | |
264 | wmove(wnd, row + 3, 0); | |
265 | winsertln(wnd); | |
266 | } | |
267 | (void) stats(row + 3, col, i); | |
268 | col += COLWIDTH; | |
269 | } | |
8b38f7fc SL |
270 | } |
271 | ||
2202cfef | 272 | static int |
855ff304 | 273 | stats(row, col, dn) |
2202cfef | 274 | int row, col, dn; |
8b38f7fc | 275 | { |
eef33ea7 | 276 | double atime, words, xtime, itime; |
8b38f7fc | 277 | |
eef33ea7 KB |
278 | atime = s.dk_time[dn]; |
279 | atime /= (float) hz; | |
280 | words = s.dk_wds[dn]*32.0; /* number of words transferred */ | |
281 | xtime = dk_mspw[dn]*words; /* transfer time */ | |
282 | itime = atime - xtime; /* time not transferring */ | |
283 | if (xtime < 0) | |
284 | itime += xtime, xtime = 0; | |
285 | if (itime < 0) | |
286 | xtime += itime, itime = 0; | |
287 | if (numbers) { | |
288 | mvwprintw(wnd, row, col, "%3.0f%4.0f%5.1f", | |
289 | words / 512 / etime, s.dk_xfer[dn] / etime, | |
290 | s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0.0); | |
291 | return (row); | |
292 | } | |
293 | wmove(wnd, row++, col); | |
294 | histogram(words / 512 / etime, 50, 1.0); | |
295 | wmove(wnd, row++, col); | |
296 | histogram(s.dk_xfer[dn] / etime, 50, 1.0); | |
297 | if (msps) { | |
298 | wmove(wnd, row++, col); | |
299 | histogram(s.dk_seek[dn] ? itime * 1000. / s.dk_seek[dn] : 0, | |
300 | 50, 1.0); | |
301 | } | |
302 | return (row); | |
8b38f7fc SL |
303 | } |
304 | ||
2202cfef | 305 | static void |
8b38f7fc | 306 | stat1(row, o) |
eef33ea7 | 307 | int row, o; |
8b38f7fc | 308 | { |
c03898eb | 309 | register int i; |
eef33ea7 | 310 | double time; |
8b38f7fc | 311 | |
eef33ea7 KB |
312 | time = 0; |
313 | for (i = 0; i < CPUSTATES; i++) | |
314 | time += s.cp_time[i]; | |
315 | if (time == 0.0) | |
316 | time = 1.0; | |
317 | wmove(wnd, row, INSET); | |
318 | #define CPUSCALE 0.5 | |
bcc006b0 | 319 | histogram(100.0 * s.cp_time[o] / time, 50, CPUSCALE); |
8b38f7fc SL |
320 | } |
321 | ||
5abc08c8 | 322 | static void |
855ff304 | 323 | histogram(val, colwidth, scale) |
eef33ea7 KB |
324 | double val; |
325 | int colwidth; | |
326 | double scale; | |
8b38f7fc | 327 | { |
eef33ea7 KB |
328 | char buf[10]; |
329 | register int k; | |
330 | register int v = (int)(val * scale) + 0.5; | |
8b38f7fc | 331 | |
eef33ea7 KB |
332 | k = MIN(v, colwidth); |
333 | if (v > colwidth) { | |
334 | sprintf(buf, "%4.1f", val); | |
335 | k -= strlen(buf); | |
336 | while (k--) | |
337 | waddch(wnd, 'X'); | |
338 | waddstr(wnd, buf); | |
339 | return; | |
340 | } | |
341 | while (k--) | |
342 | waddch(wnd, 'X'); | |
343 | wclrtoeol(wnd); | |
8b38f7fc SL |
344 | } |
345 | ||
5abc08c8 | 346 | int |
855ff304 | 347 | cmdiostat(cmd, args) |
eef33ea7 | 348 | char *cmd, *args; |
8b38f7fc | 349 | { |
8b38f7fc | 350 | |
eef33ea7 KB |
351 | if (prefix(cmd, "msps")) |
352 | msps = !msps; | |
833d578b | 353 | else if (prefix(cmd, "numbers")) |
eef33ea7 | 354 | numbers = 1; |
833d578b | 355 | else if (prefix(cmd, "bars")) |
eef33ea7 | 356 | numbers = 0; |
833d578b SL |
357 | else if (!dkcmd(cmd, args)) |
358 | return (0); | |
eef33ea7 KB |
359 | wclear(wnd); |
360 | labeliostat(); | |
361 | refresh(); | |
362 | return (1); | |
8b38f7fc | 363 | } |