1N/A# iosnoop - A program to print disk I/O events as they happen, with useful 1N/A# details such as UID, PID, filename, command, etc. 1N/A# Written using DTrace (Solaris 10 3/05). 1N/A# This is measuring disk events that have made it past system caches. 1N/A# $Id: iosnoop 8 2007-08-06 05:55:26Z brendan $ 1N/A# USAGE: iosnoop [-a|-A|-DeghiNostv] [-d device] [-f filename] 1N/A# [-m mount_point] [-n name] [-p PID] 1N/A# iosnoop # default output 1N/A# -a # print all data (mostly) 1N/A# -A # dump all data, space delimited 1N/A# -D # print time delta, us (elapsed) 1N/A# -e # print device name 1N/A# -g # print command arguments 1N/A# -i # print device instance 1N/A# -N # print major and minor numbers 1N/A# -o # print disk delta time, us 1N/A# -s # print start time, us 1N/A# -t # print completion time, us 1N/A# -v # print completion time, string 1N/A# -d device # instance name to snoop (eg, dad0) 1N/A# -f filename # full pathname of file to snoop 1N/A# -m mount_point # this FS only (will skip raw events) 1N/A# -n name # this process name only 1N/A# -p PID # this PID only 1N/A# iosnoop -v # human readable timestamps 1N/A# iosnoop -N # print major and minor numbers 1N/A# iosnoop -m / # snoop events on the root filesystem only 1N/A# PPID parennt process ID 1N/A# COMM command name for the process 1N/A# ARGS argument listing for the process 1N/A# SIZE size of operation, bytes 1N/A# BLOCK disk block for the operation (location) 1N/A# STIME timestamp for the disk request, us 1N/A# TIME timestamp for the disk completion, us 1N/A# DELTA elapsed time from request to completion, us 1N/A# DTIME time for disk to complete request, us 1N/A# STRTIME timestamp for the disk completion, string 1N/A# INS device instance number 1N/A# D direction, Read or Write 1N/A# FILE filename (basename) for io operation 1N/A# - There are two different delta times reported. -D prints the 1N/A# elapsed time from the disk request (strategy) to the disk completion 1N/A# (iodone); -o prints the time for the disk to complete that event 1N/A# since it's last event (time between iodones), or, the time to the 1N/A# strategy if the disk had been idle. 1N/A# - When filtering on PID or process name, be aware that poor disk event 1N/A# times may be due to events that have been filtered away, for example 1N/A# another process that may be seeking the disk heads elsewhere. 1N/A# COPYRIGHT: Copyright (c) 2005 Brendan Gregg. 1N/A# The contents of this file are subject to the terms of the 1N/A# Common Development and Distribution License, Version 1.0 only 1N/A# (the "License"). You may not use this file except in compliance 1N/A# See the License for the specific language governing permissions 1N/A# and limitations under the License. 1N/A# Author: Brendan Gregg [Sydney, Australia] 1N/A# 12-Mar-2004 Brendan Gregg Created this, build 51. 1N/A# 23-May-2004 " " Fixed mntpt bug. 1N/A# 10-Oct-2004 " " Rewritten to use the io provider, build 63. 1N/A# 04-Jan-2005 " " Wrapped in sh to provide options. 1N/A# 08-May-2005 " " Rewritten for perfromance. 1N/A# 15-Jul-2005 " " Improved DTIME calculation. 1N/A# 25-Jul-2005 " " Added -p, -n. Improved code. 1N/A# 17-Sep-2005 " " Increased switchrate. 1N/A# 17-Sep-2005 " " Last update. 1N/A############################## 1N/A# --- Process Arguments --- 1N/A### default variables 1N/A USAGE: iosnoop [-a|-A|-DeghiNostv] [-d device] [-f filename] 1N/A [-m mount_point] [-n name] [-p PID] 1N/A iosnoop # default output 1N/A -a # print all data (mostly) 1N/A -A # dump all data, space delimited 1N/A -D # print time delta, us (elapsed) 1N/A -e # print device name 1N/A -g # print command arguments 1N/A -i # print device instance 1N/A -N # print major and minor numbers 1N/A -o # print disk delta time, us 1N/A -s # print start time, us 1N/A -t # print completion time, us 1N/A -v # print completion time, string 1N/A -d device # instance name to snoop 1N/A -f filename # snoop this file only 1N/A -m mount_point # this FS only 1N/A -n name # this process name only 1N/A -p PID # this PID only 1N/A iosnoop -v # human readable timestamps 1N/A iosnoop -N # print major and minor numbers 1N/A iosnoop -m / # snoop events on filesystem / only 1N/Aif [ $opt_dump -eq 1 ]; then 1N/A opt_delta=0; opt_devname=0; opt_args=2; opt_start=0; 1N/A opt_end=0; opt_endstr=0; opt_nums=0; opt_ins=0; opt_dtime=0 1N/Aif [ $opt_device -eq 1 -o $opt_file -eq 1 -o $opt_mount -eq 1 -o \ 1N/A $opt_name -eq 1 -o $opt_pid -eq 1 ]; then 1N/A################################# 1N/A# --- Main Program, DTrace --- 1N/A/usr/sbin/dtrace -n ' 1N/A * Command line arguments 1N/A inline int OPT_dump = '$opt_dump'; 1N/A inline int OPT_device = '$opt_device'; 1N/A inline int OPT_delta = '$opt_delta'; 1N/A inline int OPT_devname = '$opt_devname'; 1N/A inline int OPT_file = '$opt_file'; 1N/A inline int OPT_args = '$opt_args'; 1N/A inline int OPT_ins = '$opt_ins'; 1N/A inline int OPT_nums = '$opt_nums'; 1N/A inline int OPT_dtime = '$opt_dtime'; 1N/A inline int OPT_mount = '$opt_mount'; 1N/A inline int OPT_start = '$opt_start'; 1N/A inline int OPT_pid = '$opt_pid'; 1N/A inline int OPT_name = '$opt_name'; 1N/A inline int OPT_end = '$opt_end'; 1N/A inline int OPT_endstr = '$opt_endstr'; 1N/A inline int FILTER = '$filter'; 1N/A inline int PID = '$pid'; 1N/A inline string DEVICE = "'$device'"; 1N/A inline string FILENAME = "'$filename'"; 1N/A inline string MOUNT = "'$mount'"; 1N/A inline string NAME = "'$pname'"; 1N/A #pragma D option quiet 1N/A #pragma D option switchrate=10hz 1N/A /* print optional headers */ 1N/A OPT_start ? printf("%-14s ","STIME") : 1; 1N/A OPT_end ? printf("%-14s ","TIME") : 1; 1N/A OPT_endstr ? printf("%-20s ","STRTIME") : 1; 1N/A OPT_devname ? printf("%-7s ","DEVICE") : 1; 1N/A OPT_ins ? printf("%-3s ","INS") : 1; 1N/A OPT_nums ? printf("%-3s %-3s ","MAJ","MIN") : 1; 1N/A OPT_delta ? printf("%-10s ","DELTA") : 1; 1N/A OPT_dtime ? printf("%-10s ","DTIME") : 1; 1N/A /* print main headers */ 1N/A printf("%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", 1N/A "TIME", "STIME", "DELTA", "DEVICE", "INS", "MAJ", "MIN", "UID", 1N/A "PID", "PPID", "D", "BLOCK", "SIZE", "MOUNT", "FILE", "PATH", 1N/A printf("%5s %5s %1s %8s %6s ", "UID", "PID", "D", "BLOCK", "SIZE"); 1N/A OPT_args == 0 ? printf("%10s %s\n", "COMM", "PATHNAME") : 1; 1N/A OPT_args == 1 ? printf("%28s %s\n", "PATHNAME", "ARGS") : 1; 1N/A * Check event is being traced 1N/A /* default is to trace unless filtering, */ 1N/A self->ok = FILTER ? 0 : 1; 1N/A /* check each filter, */ 1N/A (OPT_device == 1 && DEVICE == args[1]->dev_statname)? self->ok = 1 : 1; 1N/A (OPT_file == 1 && FILENAME == args[2]->fi_pathname) ? self->ok = 1 : 1; 1N/A (OPT_mount == 1 && MOUNT == args[2]->fi_mount) ? self->ok = 1 : 1; 1N/A (OPT_name == 1 && NAME == execname) ? self->ok = 1 : 1; 1N/A (OPT_pid == 1 && PID == pid) ? self->ok = 1 : 1; 1N/A * Reset last_event for disk idle -> start 1N/A * this prevents idle time being counted as disk time. 1N/A /! pending[args[1]->dev_statname]/ 1N/A /* save last disk event */ 1N/A last_event[args[1]->dev_statname] = timestamp; 1N/A * Store entry details 1N/A /* these are used as a unique disk event key, */ 1N/A this->dev = args[0]->b_edev; 1N/A this->blk = args[0]->b_blkno; 1N/A /* save disk event details, */ 1N/A start_uid[this->dev, this->blk] = uid; 1N/A start_pid[this->dev, this->blk] = pid; 1N/A start_ppid[this->dev, this->blk] = ppid; 1N/A start_args[this->dev, this->blk] = (char *)curpsinfo->pr_psargs; 1N/A start_comm[this->dev, this->blk] = execname; 1N/A start_time[this->dev, this->blk] = timestamp; 1N/A /* increase disk event pending count */ 1N/A pending[args[1]->dev_statname]++; 1N/A * Process and Print completion 1N/A /start_time[args[0]->b_edev, args[0]->b_blkno]/ 1N/A /* decrease disk event pending count */ 1N/A pending[args[1]->dev_statname]--; 1N/A /* fetch entry values */ 1N/A this->dev = args[0]->b_edev; 1N/A this->blk = args[0]->b_blkno; 1N/A this->suid = start_uid[this->dev, this->blk]; 1N/A this->spid = start_pid[this->dev, this->blk]; 1N/A this->sppid = start_ppid[this->dev, this->blk]; 1N/A self->sargs = (int)start_args[this->dev, this->blk] == 0 ? 1N/A "" : start_args[this->dev, this->blk]; 1N/A self->scomm = start_comm[this->dev, this->blk]; 1N/A this->stime = start_time[this->dev, this->blk]; 1N/A this->etime = timestamp; /* endtime */ 1N/A this->delta = this->etime - this->stime; 1N/A this->dtime = last_event[args[1]->dev_statname] == 0 ? 0 : 1N/A timestamp - last_event[args[1]->dev_statname]; 1N/A /* memory cleanup */ 1N/A start_uid[this->dev, this->blk] = 0; 1N/A start_pid[this->dev, this->blk] = 0; 1N/A start_ppid[this->dev, this->blk] = 0; 1N/A start_args[this->dev, this->blk] = 0; 1N/A start_time[this->dev, this->blk] = 0; 1N/A start_comm[this->dev, this->blk] = 0; 1N/A start_rw[this->dev, this->blk] = 0; 1N/A /* print optional fields */ 1N/A OPT_start ? printf("%-14d ", this->stime/1000) : 1; 1N/A OPT_end ? printf("%-14d ", this->etime/1000) : 1; 1N/A OPT_endstr ? printf("%-20Y ", walltimestamp) : 1; 1N/A OPT_devname ? printf("%-7s ", args[1]->dev_statname) : 1; 1N/A OPT_ins ? printf("%3d ", args[1]->dev_instance) : 1; 1N/A OPT_nums ? printf("%3d %3d ", 1N/A args[1]->dev_major, args[1]->dev_minor) : 1; 1N/A OPT_delta ? printf("%-10d ", this->delta/1000) : 1; 1N/A OPT_dtime ? printf("%-10d ", this->dtime/1000) : 1; 1N/A /* print main fields */ 1N/A printf("%d %d %d %s %d %d %d %d %d %d %s %d %d %s %s %s %s %S\n", 1N/A this->etime/1000, this->stime/1000, this->delta/1000, 1N/A args[1]->dev_statname, args[1]->dev_instance, args[1]->dev_major, 1N/A args[1]->dev_minor, this->suid, this->spid, this->sppid, 1N/A args[0]->b_flags & B_READ ? "R" : "W", 1N/A args[0]->b_blkno, args[0]->b_bcount, args[2]->fi_mount, 1N/A args[2]->fi_name, args[2]->fi_pathname, self->scomm, self->sargs) : 1N/A printf("%5d %5d %1s %8d %6d ", 1N/A this->suid, this->spid, args[0]->b_flags & B_READ ? "R" : "W", 1N/A args[0]->b_blkno, args[0]->b_bcount); 1N/A OPT_args == 0 ? printf("%10s %s\n", self->scomm, args[2]->fi_pathname) 1N/A OPT_args == 1 ? printf("%28s %S\n", 1N/A args[2]->fi_pathname, self->sargs) : 1; 1N/A /* save last disk event */ 1N/A last_event[args[1]->dev_statname] = timestamp; 1N/A * Prevent pending from underflowing 1N/A * this can happen if this program is started during disk events. 1N/A /pending[args[1]->dev_statname] < 0/ 1N/A pending[args[1]->dev_statname] = 0;