iostat.c revision 1.30
1/* $OpenBSD: iostat.c,v 1.30 2008/06/12 22:26:01 canacar Exp $ */ 2/* $NetBSD: iostat.c,v 1.5 1996/05/10 23:16:35 thorpej Exp $ */ 3 4/* 5 * Copyright (c) 1980, 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#include <sys/param.h> 34#include <sys/dkstat.h> 35#include <sys/buf.h> 36#include <sys/time.h> 37#include <sys/sysctl.h> 38#include <sys/mount.h> 39 40#include <string.h> 41#include <stdlib.h> 42#include <paths.h> 43#include "systat.h" 44 45#include "dkstats.h" 46extern struct _disk cur, last; 47struct bcachestats bclast, bccur; 48 49static double etime; 50 51void showtotal(void); 52void showdrive(int); 53void print_io(void); 54int read_io(void); 55int select_io(void); 56void showbcache(void); 57 58#define ATIME(x,y) ((double)x[y].tv_sec + \ 59 ((double)x[y].tv_usec / (double)1000000)) 60 61 62field_def fields_io[] = { 63 {"DEVICE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 64 {"READ", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 65 {"WRITE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 66 {"RTPS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 67 {"WTPS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 68 {"SEC", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 69 {"", 8, 10, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 70 {"STATS", 12, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0} 71}; 72 73#define FIELD_ADDR(x) (&fields_io[x]) 74 75#define FLD_IO_DEVICE FIELD_ADDR(0) 76#define FLD_IO_READ FIELD_ADDR(1) 77#define FLD_IO_WRITE FIELD_ADDR(2) 78#define FLD_IO_RTPS FIELD_ADDR(3) 79#define FLD_IO_WTPS FIELD_ADDR(4) 80#define FLD_IO_SEC FIELD_ADDR(5) 81 82/* This is a hack that stuffs bcache statistics to the last two columns! */ 83#define FLD_IO_SVAL FIELD_ADDR(6) 84#define FLD_IO_SSTR FIELD_ADDR(7) 85 86/* Define views */ 87field_def *view_io_0[] = { 88 FLD_IO_DEVICE, FLD_IO_READ, FLD_IO_WRITE, FLD_IO_RTPS, 89 FLD_IO_WTPS, FLD_IO_SEC, FLD_IO_SVAL, FLD_IO_SSTR, NULL 90}; 91 92 93/* Define view managers */ 94struct view_manager iostat_mgr = { 95 "Iostat", select_io, read_io, NULL, print_header, 96 print_io, keyboard_callback, NULL, NULL 97}; 98 99 100field_view views_io[] = { 101 {view_io_0, "iostat", '2', &iostat_mgr}, 102 {NULL, NULL, 0, NULL} 103}; 104 105 106int 107select_io(void) 108{ 109 num_disp = cur.dk_ndrive + 1; 110 return (0); 111} 112 113int 114read_io(void) 115{ 116 int mib[3]; 117 size_t size; 118 119 dkreadstats(); 120 dkswap(); 121 num_disp = cur.dk_ndrive + 1; 122 123 bclast = bccur; 124 mib[0] = CTL_VFS; 125 mib[1] = VFS_GENERIC; 126 mib[2] = VFS_BCACHESTAT; 127 size = sizeof(bccur); 128 129 if (sysctl(mib, 3, &bccur, &size, NULL, 0) < 0) 130 error("cannot get vfs.bcachestat"); 131 132 if (bclast.numbufs == 0) 133 bclast = bccur; 134 135 return 0; 136} 137 138 139void 140print_io(void) 141{ 142 int n, count = 0; 143 144 int i, curr; 145 146 etime = 0.0; 147 for (i = 0; i < CPUSTATES; i++) 148 etime += cur.cp_time[i]; 149 150 if (etime == 0.0) 151 etime = 1.0; 152 153 etime /= (float) hz; 154 155 156 /* XXX engine internals: save and restore curr_line for bcache */ 157 curr = curr_line; 158 159 for (n = dispstart; n < num_disp - 1; n++) { 160 showdrive(n); 161 count++; 162 if (maxprint > 0 && count >= maxprint) 163 break; 164 } 165 166 167 if (maxprint == 0 || count < maxprint) 168 showtotal(); 169 170 curr_line = curr; 171 showbcache(); 172} 173 174int 175initiostat(void) 176{ 177 field_view *v; 178 179 dkinit(1); 180 dkreadstats(); 181 182 bzero(&bccur, sizeof(bccur)); 183 184 for (v = views_io; v->name != NULL; v++) 185 add_view(v); 186 187 return(1); 188} 189 190void 191showtotal(void) 192{ 193 double rsum, wsum, rtsum, wtsum, mssum; 194 int dn; 195 196 rsum = wsum = rtsum = wtsum = mssum = 0.0; 197 198 for (dn = 0; dn < cur.dk_ndrive; dn++) { 199 rsum += cur.dk_rbytes[dn] / etime; 200 wsum += cur.dk_wbytes[dn] / etime; 201 rtsum += cur.dk_rxfer[dn] / etime; 202 wtsum += cur.dk_wxfer[dn] / etime; 203 mssum += ATIME(cur.dk_time, dn) / etime; 204 } 205 206 print_fld_str(FLD_IO_DEVICE, "Totals"); 207 print_fld_size(FLD_IO_READ, rsum); 208 print_fld_size(FLD_IO_WRITE, wsum); 209 print_fld_size(FLD_IO_RTPS, rtsum); 210 print_fld_size(FLD_IO_WTPS, wtsum); 211 print_fld_size(FLD_IO_SEC, mssum); 212 213 end_line(); 214} 215 216void 217showdrive(int dn) 218{ 219 print_fld_str(FLD_IO_DEVICE, cur.dk_name[dn]); 220 print_fld_size(FLD_IO_READ, cur.dk_rbytes[dn]/etime); 221 print_fld_size(FLD_IO_WRITE, cur.dk_wbytes[dn]/ etime); 222 print_fld_size(FLD_IO_RTPS, cur.dk_rxfer[dn] / etime); 223 print_fld_size(FLD_IO_WTPS, cur.dk_wxfer[dn] / etime); 224 print_fld_size(FLD_IO_SEC, ATIME(cur.dk_time, dn) / etime); 225 226 end_line(); 227} 228 229 230#define ENDLINE do { \ 231 count++; \ 232 if (maxprint > 0 && count >= maxprint) \ 233 return; \ 234 } while(0) 235 236void 237showbcache(void) 238{ 239 int count = 0; 240 241 print_fld_str(FLD_IO_SSTR, "numbufs"); 242 print_fld_size(FLD_IO_SVAL, bccur.numbufs); 243 end_line(); 244 245 print_fld_str(FLD_IO_SSTR, "freebufs"); 246 print_fld_size(FLD_IO_SVAL, bccur.freebufs); 247 end_line(); 248 249 print_fld_str(FLD_IO_SSTR, "numbufpages"); 250 print_fld_size(FLD_IO_SVAL, bccur.numbufpages); 251 end_line(); 252 253 print_fld_str(FLD_IO_SSTR, "numfreepages"); 254 print_fld_size(FLD_IO_SVAL, bccur.numfreepages); 255 end_line(); 256 257 print_fld_str(FLD_IO_SSTR, "numdirtypages"); 258 print_fld_size(FLD_IO_SVAL, bccur.numdirtypages); 259 end_line(); 260 261 print_fld_str(FLD_IO_SSTR, "numcleanpages"); 262 print_fld_size(FLD_IO_SVAL, bccur.numcleanpages); 263 end_line(); 264 265 print_fld_str(FLD_IO_SSTR, "pendingwrites"); 266 print_fld_size(FLD_IO_SVAL, bccur.pendingwrites); 267 end_line(); 268 269 print_fld_str(FLD_IO_SSTR, "pendingreads"); 270 print_fld_size(FLD_IO_SVAL, bccur.pendingreads); 271 end_line(); 272 273 print_fld_str(FLD_IO_SSTR, "numwrites"); 274 print_fld_size(FLD_IO_SVAL, bccur.numwrites - bclast.numwrites); 275 end_line(); 276 277 print_fld_str(FLD_IO_SSTR, "numreads"); 278 print_fld_size(FLD_IO_SVAL, bccur.numreads - bclast.numreads); 279 end_line(); 280 281 print_fld_str(FLD_IO_SSTR, "cachehits"); 282 print_fld_size(FLD_IO_SVAL, bccur.cachehits - bclast.cachehits); 283 end_line(); 284} 285