#!/bin/sh
opt_device=0; opt_file=0; opt_mount=0; opt_clear=0;
opt_def=1; filter=0; device=.; filename=.; mount=.
interval=5; count=-1
while getopts cd:f:hm: name
do
case $name in
c) opt_clear=1 ;;
d) opt_device=1; device=$OPTARG ;;
f) opt_file=1; filename=$OPTARG ;;
m) opt_mount=1; mount=$OPTARG ;;
h|?) cat <<-END >&2
USAGE: iopending [-c] [-d device] [-f filename]
[-m mount_point] [interval [count]]
-c -d device -f filename -m mount_point eg,
iopending iopending 1 iopending -m / iopending 5 12 END
exit 1
esac
done
shift $(( $OPTIND - 1 ))
if [[ "$1" > 0 ]]; then
interval=$1; shift
fi
if [[ "$1" > 0 ]]; then
count=$1; shift
fi
if (( opt_device || opt_mount || opt_file )); then
filter=1
fi
if (( opt_clear )); then
clearstr=`clear`
else
clearstr=.
fi
/usr/sbin/dtrace -n '
/*
* Command line arguments
*/
inline int OPT_def = '$opt_def';
inline int OPT_clear = '$opt_clear';
inline int OPT_device = '$opt_device';
inline int OPT_mount = '$opt_mount';
inline int OPT_file = '$opt_file';
inline int INTERVAL = '$interval';
inline int COUNTER = '$count';
inline int FILTER = '$filter';
inline string DEVICE = "'$device'";
inline string FILENAME = "'"$filename"'";
inline string MOUNT = "'"$mount"'";
inline string CLEAR = "'$clearstr'";
inline int MAX_PENDING = 32; /* max pending value */
/*
* Print header
*/
dtrace:::BEGIN
{
/* starting values */
counts = COUNTER;
secs = INTERVAL;
disk_r = 0;
disk_w = 0;
pending = 0;
printf("Tracing... Please wait.\n");
}
/*
* Check event is being traced
*/
io:::start,
io:::done
{
/* default is to trace unless filtering, */
this->ok = FILTER ? 0 : 1;
/* check each filter, */
(OPT_device == 1 && DEVICE == args[1]->dev_statname)? this->ok = 1 : 1;
(OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? this->ok = 1 : 1;
(OPT_mount == 1 && MOUNT == args[2]->fi_mount) ? this->ok = 1 : 1;
}
/*
* Store entry details
*/
io:::start
/this->ok/
{
/* track bytes */
disk_r += args[0]->b_flags & B_READ ? args[0]->b_bcount : 0;
disk_w += args[0]->b_flags & B_READ ? 0 : args[0]->b_bcount;
/* increase event pending count */
pending++;
}
/*
* Process and Print completion
*/
io:::done
/this->ok/
{
/* decrease event pending count */
pending--;
}
/*
* Prevent pending from underflowing
* this can happen if this program is started during disk events.
*/
io:::done
/pending < 0/
{
pending = 0;
}
/*
* Timer
*/
profile:::tick-1sec
{
secs--;
}
profile:::profile-1000hz
{
@out = lquantize(pending, 0, MAX_PENDING, 1);
}
/*
* Print Report
*/
profile:::tick-1sec
/secs == 0/
{
/* fetch 1 min load average */
/*
this->load1a = `hp_avenrun[0] / 65536;
this->load1b = ((`hp_avenrun[0] % 65536) * 100) / 65536;
*/
this->fscale = `averunnable.fscale;
this->load1a = `averunnable.ldavg[0] / this->fscale;
this->load1b = ((`averunnable.ldavg[0] % this->fscale) * 100) / this->fscale;
/* convert counters to Kbytes */
disk_r /= 1024;
disk_w /= 1024;
/* print status */
OPT_clear ? printf("%s", CLEAR) : 1;
printf("%Y, load: %d.%02d, disk_r: %6d KB, disk_w: %6d KB",
walltimestamp, this->load1a, this->load1b, disk_r, disk_w);
/* print output */
printa(@out);
/* clear data */
trunc(@out);
disk_r = 0;
disk_w = 0;
secs = INTERVAL;
counts--;
}
/*
* End of program
*/
profile:::tick-1sec
/counts == 0/
{
exit(0);
}
/*
* Cleanup for Ctrl-C
*/
dtrace:::END
{
trunc(@out);
}
'