1#!/usr/bin/ksh 2# 3# iopending - Print a plot for the number of pending disk I/O events. 4# Written using DTrace (Solaris 10 3/05). 5# 6# This is measuring disk events that have made it past system caches. 7# By plotting a distribution graph of the number of pending events, the 8# "serialness" or "parallelness" of disk behaviour can be distinguished. 9# 10# $Id: iopending,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $ 11# 12# USAGE: iopending [-c] [-d device] [-f filename] 13# [-m mount_point] [interval [count]] 14# 15# -c # clear the screen 16# -d device # instance name to snoop (eg, dad0) 17# -f filename # full pathname of file to snoop 18# -m mount_point # this FS only (will skip raw events) 19# eg, 20# iopending # default output, 5 second intervals 21# iopending 1 # 1 second samples 22# iopending -c # clear the screen 23# iopending 5 12 # print 12 x 5 second samples 24# 25# FIELDS: 26# value number of pending events, 0 == idle 27# count number of samples @ 1000 Hz 28# load 1 min load average 29# disk_r total disk read Kbytes for sample 30# disk_w total disk write Kbytes for sample 31# 32# SEE ALSO: iosnoop, iotop 33# 34# IDEA: Dr Rex di Bona (Sydney, Australia) 35# 36# COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg. 37# 38# CDDL HEADER START 39# 40# The contents of this file are subject to the terms of the 41# Common Development and Distribution License, Version 1.0 only 42# (the "License"). You may not use this file except in compliance 43# with the License. 44# 45# You can obtain a copy of the license at Docs/cddl1.txt 46# or http://www.opensolaris.org/os/licensing. 47# See the License for the specific language governing permissions 48# and limitations under the License. 49# 50# CDDL HEADER END 51# 52# Author: Brendan Gregg [Sydney, Australia] 53# 54# 01-Nov-2005 Brendan Gregg Created this. 55# 20-Apr-2006 " " Last update. 56# 57 58 59############################## 60# --- Process Arguments --- 61# 62 63### default variables 64opt_device=0; opt_file=0; opt_mount=0; opt_clear=0; 65opt_def=1; filter=0; device=.; filename=.; mount=. 66interval=5; count=-1 67 68### process options 69while getopts cd:f:hm: name 70do 71 case $name in 72 c) opt_clear=1 ;; 73 d) opt_device=1; device=$OPTARG ;; 74 f) opt_file=1; filename=$OPTARG ;; 75 m) opt_mount=1; mount=$OPTARG ;; 76 h|?) cat <<-END >&2 77 USAGE: iopending [-c] [-d device] [-f filename] 78 [-m mount_point] [interval [count]] 79 80 -c # clear the screen 81 -d device # instance name to snoop 82 -f filename # snoop this file only 83 -m mount_point # this FS only 84 eg, 85 iopending # default output, 5 second samples 86 iopending 1 # 1 second samples 87 iopending -m / # snoop events on filesystem / only 88 iopending 5 12 # print 12 x 5 second samples 89 END 90 exit 1 91 esac 92done 93 94shift $(( $OPTIND - 1 )) 95 96### option logic 97if [[ "$1" > 0 ]]; then 98 interval=$1; shift 99fi 100if [[ "$1" > 0 ]]; then 101 count=$1; shift 102fi 103if (( opt_device || opt_mount || opt_file )); then 104 filter=1 105fi 106if (( opt_clear )); then 107 clearstr=`clear` 108else 109 clearstr=. 110fi 111 112 113 114################################# 115# --- Main Program, DTrace --- 116# 117/usr/sbin/dtrace -n ' 118 /* 119 * Command line arguments 120 */ 121 inline int OPT_def = '$opt_def'; 122 inline int OPT_clear = '$opt_clear'; 123 inline int OPT_device = '$opt_device'; 124 inline int OPT_mount = '$opt_mount'; 125 inline int OPT_file = '$opt_file'; 126 inline int INTERVAL = '$interval'; 127 inline int COUNTER = '$count'; 128 inline int FILTER = '$filter'; 129 inline string DEVICE = "'$device'"; 130 inline string FILENAME = "'$filename'"; 131 inline string MOUNT = "'$mount'"; 132 inline string CLEAR = "'$clearstr'"; 133 134 inline int MAX_PENDING = 32; /* max pending value */ 135 136 #pragma D option quiet 137 138 /* 139 * Print header 140 */ 141 dtrace:::BEGIN 142 { 143 /* starting values */ 144 counts = COUNTER; 145 secs = INTERVAL; 146 disk_r = 0; 147 disk_w = 0; 148 pending = 0; 149 150 printf("Tracing... Please wait.\n"); 151 } 152 153 /* 154 * Check event is being traced 155 */ 156 io:genunix::start, 157 io:genunix::done 158 { 159 /* default is to trace unless filtering, */ 160 this->ok = FILTER ? 0 : 1; 161 162 /* check each filter, */ 163 (OPT_device == 1 && DEVICE == args[1]->dev_statname)? this->ok = 1 : 1; 164 (OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? this->ok = 1 : 1; 165 (OPT_mount == 1 && MOUNT == args[2]->fi_mount) ? this->ok = 1 : 1; 166 } 167 168 /* 169 * Store entry details 170 */ 171 io:genunix::start 172 /this->ok/ 173 { 174 /* track bytes */ 175 disk_r += args[0]->b_flags & B_READ ? args[0]->b_bcount : 0; 176 disk_w += args[0]->b_flags & B_READ ? 0 : args[0]->b_bcount; 177 178 /* increase event pending count */ 179 pending++; 180 } 181 182 /* 183 * Process and Print completion 184 */ 185 io:genunix::done 186 /this->ok/ 187 { 188 /* decrease event pending count */ 189 pending--; 190 } 191 192 /* 193 * Prevent pending from underflowing 194 * this can happen if this program is started during disk events. 195 */ 196 io:genunix::done 197 /pending < 0/ 198 { 199 pending = 0; 200 } 201 202 /* 203 * Timer 204 */ 205 profile:::tick-1sec 206 { 207 secs--; 208 } 209 210 profile:::profile-1000hz 211 { 212 @out = lquantize(pending, 0, MAX_PENDING, 1); 213 } 214 215 /* 216 * Print Report 217 */ 218 profile:::tick-1sec 219 /secs == 0/ 220 { 221 /* fetch 1 min load average */ 222 this->load1a = `hp_avenrun[0] / 65536; 223 this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536; 224 225 /* convert counters to Kbytes */ 226 disk_r /= 1024; 227 disk_w /= 1024; 228 229 /* print status */ 230 OPT_clear ? printf("%s", CLEAR) : 1; 231 printf("%Y, load: %d.%02d, disk_r: %6d KB, disk_w: %6d KB", 232 walltimestamp, this->load1a, this->load1b, disk_r, disk_w); 233 234 /* print output */ 235 printa(@out); 236 237 /* clear data */ 238 trunc(@out); 239 disk_r = 0; 240 disk_w = 0; 241 secs = INTERVAL; 242 counts--; 243 } 244 245 /* 246 * End of program 247 */ 248 profile:::tick-1sec 249 /counts == 0/ 250 { 251 exit(0); 252 } 253 254 /* 255 * Cleanup for Ctrl-C 256 */ 257 dtrace:::END 258 { 259 trunc(@out); 260 } 261' 262