iostat.c revision 1.44
1/* $OpenBSD: iostat.c,v 1.44 2014/11/23 04:34:48 guenther 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/mount.h> 35#include <sys/sched.h> 36#include <sys/sysctl.h> 37#include <sys/time.h> 38 39#include <string.h> 40#include <stdlib.h> 41#include <paths.h> 42#include "systat.h" 43 44#include "dkstats.h" 45extern struct _disk cur, last; 46struct bcachestats bclast, bccur; 47 48static double etime; 49 50void showtotal(void); 51void showdrive(int); 52void print_io(void); 53int read_io(void); 54int select_io(void); 55void showbcache(void); 56 57#define ATIME(x,y) ((double)x[y].tv_sec + \ 58 ((double)x[y].tv_usec / (double)1000000)) 59 60 61field_def fields_io[] = { 62 {"DEVICE", 8, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}, 63 {"READ", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 64 {"WRITE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 65 {"RTPS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 66 {"WTPS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 67 {"SEC", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 68 {"", 8, 19, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}, 69 {"STATS", 12, 15, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0} 70}; 71 72#define FLD_IO_DEVICE FIELD_ADDR(fields_io,0) 73#define FLD_IO_READ FIELD_ADDR(fields_io,1) 74#define FLD_IO_WRITE FIELD_ADDR(fields_io,2) 75#define FLD_IO_RTPS FIELD_ADDR(fields_io,3) 76#define FLD_IO_WTPS FIELD_ADDR(fields_io,4) 77#define FLD_IO_SEC FIELD_ADDR(fields_io,5) 78 79/* This is a hack that stuffs bcache statistics to the last two columns! */ 80#define FLD_IO_SVAL FIELD_ADDR(fields_io,6) 81#define FLD_IO_SSTR FIELD_ADDR(fields_io,7) 82 83/* Define views */ 84field_def *view_io_0[] = { 85 FLD_IO_DEVICE, FLD_IO_READ, FLD_IO_WRITE, FLD_IO_RTPS, 86 FLD_IO_WTPS, FLD_IO_SEC, FLD_IO_SVAL, FLD_IO_SSTR, NULL 87}; 88 89 90/* Define view managers */ 91struct view_manager iostat_mgr = { 92 "Iostat", select_io, read_io, NULL, print_header, 93 print_io, keyboard_callback, NULL, NULL 94}; 95 96 97field_view views_io[] = { 98 {view_io_0, "iostat", '2', &iostat_mgr}, 99 {NULL, NULL, 0, NULL} 100}; 101 102 103int 104select_io(void) 105{ 106 num_disp = cur.dk_ndrive + 1; 107 return (0); 108} 109 110int 111read_io(void) 112{ 113 int mib[3]; 114 size_t size; 115 116 dkreadstats(); 117 dkswap(); 118 num_disp = cur.dk_ndrive + 1; 119 120 bclast = bccur; 121 mib[0] = CTL_VFS; 122 mib[1] = VFS_GENERIC; 123 mib[2] = VFS_BCACHESTAT; 124 size = sizeof(bccur); 125 126 if (sysctl(mib, 3, &bccur, &size, NULL, 0) < 0) 127 error("cannot get vfs.bcachestat"); 128 129 if (bclast.numbufs == 0) 130 bclast = bccur; 131 132 return 0; 133} 134 135 136void 137print_io(void) 138{ 139 int n, count = 0; 140 141 int curr; 142 etime = naptime; 143 144 /* XXX engine internals: save and restore curr_line for bcache */ 145 curr = curr_line; 146 147 for (n = dispstart; n < num_disp - 1; n++) { 148 showdrive(n); 149 count++; 150 if (maxprint > 0 && count >= maxprint) 151 break; 152 } 153 154 155 if (maxprint == 0 || count < maxprint) 156 showtotal(); 157 158 curr_line = curr; 159 showbcache(); 160} 161 162int 163initiostat(void) 164{ 165 field_view *v; 166 167 dkinit(1); 168 dkreadstats(); 169 170 bzero(&bccur, sizeof(bccur)); 171 172 for (v = views_io; v->name != NULL; v++) 173 add_view(v); 174 175 return(1); 176} 177 178void 179showtotal(void) 180{ 181 double rsum, wsum, rtsum, wtsum, mssum; 182 int dn; 183 184 rsum = wsum = rtsum = wtsum = mssum = 0.0; 185 186 for (dn = 0; dn < cur.dk_ndrive; dn++) { 187 rsum += cur.dk_rbytes[dn] / etime; 188 wsum += cur.dk_wbytes[dn] / etime; 189 rtsum += cur.dk_rxfer[dn] / etime; 190 wtsum += cur.dk_wxfer[dn] / etime; 191 mssum += ATIME(cur.dk_time, dn) / etime; 192 } 193 194 print_fld_str(FLD_IO_DEVICE, "Totals"); 195 print_fld_size(FLD_IO_READ, rsum); 196 print_fld_size(FLD_IO_WRITE, wsum); 197 print_fld_size(FLD_IO_RTPS, rtsum); 198 print_fld_size(FLD_IO_WTPS, wtsum); 199 print_fld_float(FLD_IO_SEC, mssum, 1); 200 201 end_line(); 202} 203 204void 205showdrive(int dn) 206{ 207 print_fld_str(FLD_IO_DEVICE, cur.dk_name[dn]); 208 print_fld_size(FLD_IO_READ, cur.dk_rbytes[dn]/etime); 209 print_fld_size(FLD_IO_WRITE, cur.dk_wbytes[dn]/ etime); 210 print_fld_size(FLD_IO_RTPS, cur.dk_rxfer[dn] / etime); 211 print_fld_size(FLD_IO_WTPS, cur.dk_wxfer[dn] / etime); 212 print_fld_float(FLD_IO_SEC, ATIME(cur.dk_time, dn) / etime, 1); 213 214 end_line(); 215} 216 217void 218showbcache(void) 219{ 220 print_fld_str(FLD_IO_SSTR, "total pages"); 221 print_fld_ssize(FLD_IO_SVAL, bccur.numbufpages); 222 end_line(); 223 224 print_fld_str(FLD_IO_SSTR, "dirty pages"); 225 print_fld_ssize(FLD_IO_SVAL, bccur.numdirtypages); 226 end_line(); 227 228 print_fld_str(FLD_IO_SSTR, "delwri bufs"); 229 print_fld_ssize(FLD_IO_SVAL, bccur.delwribufs); 230 end_line(); 231 232 print_fld_str(FLD_IO_SSTR, "busymap bufs"); 233 print_fld_ssize(FLD_IO_SVAL, bccur.busymapped); 234 end_line(); 235 236 print_fld_str(FLD_IO_SSTR, "avail kvaslots"); 237 print_fld_ssize(FLD_IO_SVAL, bccur.kvaslots_avail); 238 end_line(); 239 240 print_fld_str(FLD_IO_SSTR, "kvaslots"); 241 print_fld_ssize(FLD_IO_SVAL, bccur.kvaslots); 242 end_line(); 243 244 print_fld_str(FLD_IO_SSTR, "pending writes"); 245 print_fld_ssize(FLD_IO_SVAL, bccur.pendingwrites); 246 end_line(); 247 248 print_fld_str(FLD_IO_SSTR, "pending reads"); 249 print_fld_ssize(FLD_IO_SVAL, bccur.pendingreads); 250 end_line(); 251 252 print_fld_str(FLD_IO_SSTR, "cache hits"); 253 print_fld_ssize(FLD_IO_SVAL, bccur.cachehits - bclast.cachehits); 254 end_line(); 255} 256