1 1.1 christos #!/usr/bin/ksh 2 1.1 christos # 3 1.1 christos # iopattern - print disk I/O pattern. 4 1.1 christos # Written using DTrace (Solaris 10 3/05). 5 1.1 christos # 6 1.1 christos # This prints details on the I/O access pattern for the disks, such as 7 1.1 christos # percentage of events that were of a random or sequential nature. 8 1.1 christos # By default totals for all disks are printed. 9 1.1 christos # 10 1.1 christos # $Id: iopattern,v 1.1.1.1 2015/09/30 22:01:06 christos Exp $ 11 1.1 christos # 12 1.1 christos # USAGE: iopattern [-v] [-d device] [-f filename] [-m mount_point] 13 1.1 christos # [interval [count]] 14 1.1 christos # 15 1.1 christos # -v # print timestamp, string 16 1.1 christos # -d device # instance name to snoop (eg, dad0) 17 1.1 christos # -f filename # full pathname of file to snoop 18 1.1 christos # -m mount_point # this FS only (will skip raw events) 19 1.1 christos # eg, 20 1.1 christos # iopattern # default output, 1 second intervals 21 1.1 christos # iopattern 10 # 10 second samples 22 1.1 christos # iopattern 5 12 # print 12 x 5 second samples 23 1.1 christos # iopattern -m / # snoop events on filesystem / only 24 1.1 christos # 25 1.1 christos # FIELDS: 26 1.1 christos # %RAN percentage of events of a random nature 27 1.1 christos # %SEQ percentage of events of a sequential nature 28 1.1 christos # COUNT number of I/O events 29 1.1 christos # MIN minimum I/O event size 30 1.1 christos # MAX maximum I/O event size 31 1.1 christos # AVG average I/O event size 32 1.1 christos # KR total kilobytes read during sample 33 1.1 christos # KW total kilobytes written during sample 34 1.1 christos # DEVICE device name 35 1.1 christos # MOUNT mount point 36 1.1 christos # FILE filename 37 1.1 christos # TIME timestamp, string 38 1.1 christos # 39 1.1 christos # NOTES: 40 1.1 christos # 41 1.1 christos # An event is considered random when the heads seek. This program prints 42 1.1 christos # the percentage of events that are random. The size of the seek is not 43 1.1 christos # measured - it's either random or not. 44 1.1 christos # 45 1.1 christos # SEE ALSO: iosnoop, iotop 46 1.1 christos # 47 1.1 christos # IDEA: Ryan Matteson 48 1.1 christos # 49 1.1 christos # COPYRIGHT: Copyright (c) 2005 Brendan Gregg. 50 1.1 christos # 51 1.1 christos # CDDL HEADER START 52 1.1 christos # 53 1.1 christos # The contents of this file are subject to the terms of the 54 1.1 christos # Common Development and Distribution License, Version 1.0 only 55 1.1 christos # (the "License"). You may not use this file except in compliance 56 1.1 christos # with the License. 57 1.1 christos # 58 1.1 christos # You can obtain a copy of the license at Docs/cddl1.txt 59 1.1 christos # or http://www.opensolaris.org/os/licensing. 60 1.1 christos # See the License for the specific language governing permissions 61 1.1 christos # and limitations under the License. 62 1.1 christos # 63 1.1 christos # CDDL HEADER END 64 1.1 christos # 65 1.1 christos # Author: Brendan Gregg [Sydney, Australia] 66 1.1 christos # 67 1.1 christos # 25-Jul-2005 Brendan Gregg Created this. 68 1.1 christos # 25-Jul-2005 " " Last update. 69 1.1 christos # 70 1.1 christos 71 1.1 christos 72 1.1 christos ############################## 73 1.1 christos # --- Process Arguments --- 74 1.1 christos # 75 1.1 christos 76 1.1 christos ### default variables 77 1.1 christos opt_device=0; opt_file=0; opt_mount=0; opt_time=0 78 1.1 christos filter=0; device=.; filename=.; mount=.; interval=1; count=-1 79 1.1 christos 80 1.1 christos ### process options 81 1.1 christos while getopts d:f:hm:v name 82 1.1 christos do 83 1.1 christos case $name in 84 1.1 christos d) opt_device=1; device=$OPTARG ;; 85 1.1 christos f) opt_file=1; filename=$OPTARG ;; 86 1.1 christos m) opt_mount=1; mount=$OPTARG ;; 87 1.1 christos v) opt_time=1 ;; 88 1.1 christos h|?) cat <<-END >&2 89 1.1 christos USAGE: iopattern [-v] [-d device] [-f filename] [-m mount_point] 90 1.1 christos [interval [count]] 91 1.1 christos 92 1.1 christos -v # print timestamp 93 1.1 christos -d device # instance name to snoop 94 1.1 christos -f filename # snoop this file only 95 1.1 christos -m mount_point # this FS only 96 1.1 christos eg, 97 1.1 christos iopattern # default output, 1 second samples 98 1.1 christos iopattern 10 # 10 second samples 99 1.1 christos iopattern 5 12 # print 12 x 5 second samples 100 1.1 christos iopattern -m / # snoop events on filesystem / only 101 1.1 christos END 102 1.1 christos exit 1 103 1.1 christos esac 104 1.1 christos done 105 1.1 christos 106 1.1 christos shift $(( $OPTIND - 1 )) 107 1.1 christos 108 1.1 christos ### option logic 109 1.1 christos if [[ "$1" > 0 ]]; then 110 1.1 christos interval=$1; shift 111 1.1 christos fi 112 1.1 christos if [[ "$1" > 0 ]]; then 113 1.1 christos count=$1; shift 114 1.1 christos fi 115 1.1 christos if (( opt_device || opt_mount || opt_file )); then 116 1.1 christos filter=1 117 1.1 christos fi 118 1.1 christos 119 1.1 christos 120 1.1 christos ################################# 121 1.1 christos # --- Main Program, DTrace --- 122 1.1 christos # 123 1.1 christos /usr/sbin/dtrace -n ' 124 1.1 christos /* 125 1.1 christos * Command line arguments 126 1.1 christos */ 127 1.1 christos inline int OPT_time = '$opt_time'; 128 1.1 christos inline int OPT_device = '$opt_device'; 129 1.1 christos inline int OPT_mount = '$opt_mount'; 130 1.1 christos inline int OPT_file = '$opt_file'; 131 1.1 christos inline int INTERVAL = '$interval'; 132 1.1 christos inline int COUNTER = '$count'; 133 1.1 christos inline int FILTER = '$filter'; 134 1.1 christos inline string DEVICE = "'$device'"; 135 1.1 christos inline string FILENAME = "'$filename'"; 136 1.1 christos inline string MOUNT = "'$mount'"; 137 1.1 christos 138 1.1 christos #pragma D option quiet 139 1.1 christos 140 1.1 christos int last_loc[string]; 141 1.1 christos 142 1.1 christos /* 143 1.1 christos * Program start 144 1.1 christos */ 145 1.1 christos dtrace:::BEGIN 146 1.1 christos { 147 1.1 christos /* starting values */ 148 1.1 christos diskcnt = 0; 149 1.1 christos diskmin = 0; 150 1.1 christos diskmax = 0; 151 1.1 christos diskran = 0; 152 1.1 christos diskr = 0; 153 1.1 christos diskw = 0; 154 1.1 christos counts = COUNTER; 155 1.1 christos secs = INTERVAL; 156 1.1 christos LINES = 20; 157 1.1 christos line = 0; 158 1.1 christos last_event[""] = 0; 159 1.1 christos } 160 1.1 christos 161 1.1 christos /* 162 1.1 christos * Print header 163 1.1 christos */ 164 1.1 christos profile:::tick-1sec 165 1.1 christos /line <= 0 / 166 1.1 christos { 167 1.1 christos /* print optional headers */ 168 1.1 christos OPT_time ? printf("%-20s ", "TIME") : 1; 169 1.1 christos OPT_device ? printf("%-9s ", "DEVICE") : 1; 170 1.1 christos OPT_mount ? printf("%-12s ", "MOUNT") : 1; 171 1.1 christos OPT_file ? printf("%-12s ", "FILE") : 1; 172 1.1 christos 173 1.1 christos /* print header */ 174 1.1 christos printf("%4s %4s %6s %6s %6s %6s %6s %6s\n", 175 1.1 christos "%RAN", "%SEQ", "COUNT", "MIN", "MAX", "AVG", "KR", "KW"); 176 1.1 christos 177 1.1 christos line = LINES; 178 1.1 christos } 179 1.1 christos 180 1.1 christos /* 181 1.1 christos * Check event is being traced 182 1.1 christos */ 183 1.1 christos io:genunix::done 184 1.1 christos { 185 1.1 christos /* default is to trace unless filtering */ 186 1.1 christos self->ok = FILTER ? 0 : 1; 187 1.1 christos 188 1.1 christos /* check each filter */ 189 1.1 christos (OPT_device == 1 && DEVICE == args[1]->dev_statname)? self->ok = 1 : 1; 190 1.1 christos (OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? self->ok = 1 : 1; 191 1.1 christos (OPT_mount == 1 && MOUNT == args[2]->fi_mount) ? self->ok = 1 : 1; 192 1.1 christos } 193 1.1 christos 194 1.1 christos /* 195 1.1 christos * Process and Print completion 196 1.1 christos */ 197 1.1 christos io:genunix::done 198 1.1 christos /self->ok/ 199 1.1 christos { 200 1.1 christos /* 201 1.1 christos * Save details 202 1.1 christos */ 203 1.1 christos this->loc = args[0]->b_blkno * 512; 204 1.1 christos this->pre = last_loc[args[1]->dev_statname]; 205 1.1 christos diskr += args[0]->b_flags & B_READ ? args[0]->b_bcount : 0; 206 1.1 christos diskw += args[0]->b_flags & B_READ ? 0 : args[0]->b_bcount; 207 1.1 christos diskran += this->pre == this->loc ? 0 : 1; 208 1.1 christos diskcnt++; 209 1.1 christos diskmin = diskmin == 0 ? args[0]->b_bcount : 210 1.1 christos (diskmin > args[0]->b_bcount ? args[0]->b_bcount : diskmin); 211 1.1 christos diskmax = diskmax < args[0]->b_bcount ? args[0]->b_bcount : diskmax; 212 1.1 christos 213 1.1 christos /* save disk location */ 214 1.1 christos last_loc[args[1]->dev_statname] = this->loc + args[0]->b_bcount; 215 1.1 christos 216 1.1 christos /* cleanup */ 217 1.1 christos self->ok = 0; 218 1.1 christos } 219 1.1 christos 220 1.1 christos /* 221 1.1 christos * Timer 222 1.1 christos */ 223 1.1 christos profile:::tick-1sec 224 1.1 christos { 225 1.1 christos secs--; 226 1.1 christos } 227 1.1 christos 228 1.1 christos /* 229 1.1 christos * Print Output 230 1.1 christos */ 231 1.1 christos profile:::tick-1sec 232 1.1 christos /secs == 0/ 233 1.1 christos { 234 1.1 christos /* calculate diskavg */ 235 1.1 christos diskavg = diskcnt > 0 ? (diskr + diskw) / diskcnt : 0; 236 1.1 christos 237 1.1 christos /* convert counters to Kbytes */ 238 1.1 christos diskr /= 1024; 239 1.1 christos diskw /= 1024; 240 1.1 christos 241 1.1 christos /* convert to percentages */ 242 1.1 christos diskran = diskcnt == 0 ? 0 : (diskran * 100) / diskcnt; 243 1.1 christos diskseq = diskcnt == 0 ? 0 : 100 - diskran; 244 1.1 christos 245 1.1 christos /* print optional fields */ 246 1.1 christos OPT_time ? printf("%-20Y ", walltimestamp) : 1; 247 1.1 christos OPT_device ? printf("%-9s ", DEVICE) : 1; 248 1.1 christos OPT_mount ? printf("%-12s ", MOUNT) : 1; 249 1.1 christos OPT_file ? printf("%-12s ", FILENAME) : 1; 250 1.1 christos 251 1.1 christos /* print data */ 252 1.1 christos printf("%4d %4d %6d %6d %6d %6d %6d %6d\n", 253 1.1 christos diskran, diskseq, diskcnt, diskmin, diskmax, diskavg, 254 1.1 christos diskr, diskw); 255 1.1 christos 256 1.1 christos /* clear data */ 257 1.1 christos diskmin = 0; 258 1.1 christos diskmax = 0; 259 1.1 christos diskcnt = 0; 260 1.1 christos diskran = 0; 261 1.1 christos diskr = 0; 262 1.1 christos diskw = 0; 263 1.1 christos 264 1.1 christos secs = INTERVAL; 265 1.1 christos counts--; 266 1.1 christos line--; 267 1.1 christos } 268 1.1 christos 269 1.1 christos /* 270 1.1 christos * End of program 271 1.1 christos */ 272 1.1 christos profile:::tick-1sec 273 1.1 christos /counts == 0/ 274 1.1 christos { 275 1.1 christos exit(0); 276 1.1 christos } 277 1.1 christos ' 278