1#!/bin/sh 2##!/usr/bin/ksh 3# 4# iopending - Print a plot for the number of pending disk I/O events. 5# Written using DTrace (Solaris 10 3/05). 6# 7# This is measuring disk events that have made it past system caches. 8# By plotting a distribution graph of the number of pending events, the 9# "serialness" or "parallelness" of disk behaviour can be distinguished. 10# 11# 20-Apr-2006, ver 0.61 12# 13# USAGE: iopending [-c] [-d device] [-f filename] 14# [-m mount_point] [interval [count]] 15# 16# -c # clear the screen 17# -d device # instance name to snoop (eg, dad0) 18# -f filename # full pathname of file to snoop 19# -m mount_point # this FS only (will skip raw events) 20# eg, 21# iopending # default output, 5 second intervals 22# iopending 1 # 1 second samples 23# iopending -c # clear the screen 24# iopending 5 12 # print 12 x 5 second samples 25# 26# FIELDS: 27# value number of pending events, 0 == idle 28# count number of samples @ 1000 Hz 29# load 1 min load average 30# disk_r total disk read Kbytes for sample 31# disk_w total disk write Kbytes for sample 32# 33# SEE ALSO: iosnoop, iotop 34# 35# IDEA: Dr Rex di Bona (Sydney, Australia) 36# 37# COPYRIGHT: Copyright (c) 2005, 2006 Brendan Gregg. 38# 39# CDDL HEADER START 40# 41# The contents of this file are subject to the terms of the 42# Common Development and Distribution License, Version 1.0 only 43# (the "License"). You may not use this file except in compliance 44# with the License. 45# 46# You can obtain a copy of the license at Docs/cddl1.txt 47# or http://www.opensolaris.org/os/licensing. 48# See the License for the specific language governing permissions 49# and limitations under the License. 50# 51# CDDL HEADER END 52# 53# Author: Brendan Gregg [Sydney, Australia] 54# 55# 01-Nov-2005 Brendan Gregg Created this. 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:::start, 157 io:::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:::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:::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:::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 /* 223 this->load1a = `hp_avenrun[0] / 65536; 224 this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536; 225 */ 226 this->fscale = `averunnable.fscale; 227 this->load1a = `averunnable.ldavg[0] / this->fscale; 228 this->load1b = ((`averunnable.ldavg[0] % this->fscale) * 100) / this->fscale; 229 230 /* convert counters to Kbytes */ 231 disk_r /= 1024; 232 disk_w /= 1024; 233 234 /* print status */ 235 OPT_clear ? printf("%s", CLEAR) : 1; 236 printf("%Y, load: %d.%02d, disk_r: %6d KB, disk_w: %6d KB", 237 walltimestamp, this->load1a, this->load1b, disk_r, disk_w); 238 239 /* print output */ 240 printa(@out); 241 242 /* clear data */ 243 trunc(@out); 244 disk_r = 0; 245 disk_w = 0; 246 secs = INTERVAL; 247 counts--; 248 } 249 250 /* 251 * End of program 252 */ 253 profile:::tick-1sec 254 /counts == 0/ 255 { 256 exit(0); 257 } 258 259 /* 260 * Cleanup for Ctrl-C 261 */ 262 dtrace:::END 263 { 264 trunc(@out); 265 } 266' 267