#!/usr/sbin/dtrace -s /* ** iosnoop.d - A program to print I/O events as they happen, with useful ** details such as UID, PID, inode, command, etc. ** Written in DTrace (Solaris 10 build 51). ** ** 29-Mar-2004, ver 0.60. (check for newer versions) ** ** ** USAGE: ./iosnoop.d ** ** Different styles of output can be selected by changing ** the "FORMAT" variable below. ** ** iosnoop.d reads block I/O disk events. ** ** FIELDS: ** TIME timestamp for the disk event, us ** SIZE size of operation, bytes ** DEV extended device number of the slice ** MOUNT mount point (or "0" if the data was not available) ** STIME timestamp for the disk request, us ** ... ** ** Standard Disclaimer: This is freeware, use at your own risk. ** ** ToDo: More details, modes of operation, process different I/O types... ** ** 12-Mar-2004 Brendan Gregg Created this. ** */ inline int FORMAT = 1; /* 1 - Default output (includes PPID, VNODE) ** 2 - Timestamp output (includes TIME) ** 3 - Everything, space delimited (for spreadsheets) */ #pragma D option quiet /* ** Print header */ dtrace:::BEGIN /FORMAT == 1/ { printf("%5s %5s %5s %6s %-10s %-7s %-10s %5s %s\n", "UID","PID","PPID","SIZE","MOUNT","BLOCK","VNODE","INODE","CMD"); } dtrace:::BEGIN /FORMAT == 2/ { printf("%-14s %5s %5s %6s %-10s %-7s %5s %s\n", "TIME","UID","PID","SIZE","MOUNT","BLOCK","INODE","CMD"); } dtrace:::BEGIN /FORMAT == 3/ { printf("%s %s %s %s %s %s %s %s %s %s %s %s\n","TIME","STIME","UID", "PID","PPID","SIZE","DEV","MOUNT","BLOCK","VNODE","INODE","CMD"); } fbt:genunix:bdev_strategy:entry { /* ** Process strategy event */ /* fetch details */ this->bufp = (buf_t *)arg0; this->dev = this->bufp->b_edev; blk = this->bufp->_b_blkno._f; /* store strategy details */ str_uid[this->dev,blk] = curpsinfo->pr_euid; str_pid[this->dev,blk] = pid; str_ppid[this->dev,blk] = curpsinfo->pr_ppid; str_args[this->dev,blk] = (char *)curpsinfo->pr_psargs; str_time[this->dev,blk] = timestamp; } fbt:genunix:biodone:entry { /* ** Process biodone event */ /* fetch details */ this->bufp = (buf_t *)arg0; this->dev = this->bufp->b_edev; blk = this->bufp->_b_blkno._f; this->pagep = (page_t *)this->bufp->b_pages; this->vnodep = (int)this->pagep == 0 ? 0 : (vnode_t *)this->pagep->p_vnode; this->vnode = (int)this->vnodep == 0 ? 0 : (int)this->vnodep; this->inodep = (int)this->vnodep == 0 ? 0 : (inode_t *)this->vnodep->v_data; this->inode = (int)this->inodep == 0 ? 0 : this->inodep->i_number; this->vfsp = (int)this->vnodep == 0 ? 0 : (vfs_t *)this->vnodep->v_vfsp; mountstr = (int)this->vfsp == 0 ? "0" : stringof(this->vfsp->vfs_mntpt); /* check this is a valid mount string */ first = (int)this->vfsp == 0 ? "0" : stringof(copyin((uintptr_t)this->vfsp->vfs_mntpt,1)); mountstr = first == "/" ? mountstr : "0"; /* fetch strategy values */ this->suid = str_uid[this->dev,blk]; this->spid = str_pid[this->dev,blk]; this->sppid = str_ppid[this->dev,blk]; sargs = (int)str_args[this->dev,blk] == 0 ? "" : str_args[this->dev,blk]; this->stime = str_time[this->dev,blk]; /* memory cleanup */ str_uid[this->dev,blk] = 0; str_pid[this->dev,blk] = 0; str_ppid[this->dev,blk] = 0; str_args[this->dev,blk] = 0; str_time[this->dev,blk] = 0; } /* ** Print event details */ fbt:genunix:biodone:entry /FORMAT == 1/ { printf("%5d %5d %5d %6d %-10s %-7d %-10x %5d %s\n", this->suid,this->spid,this->sppid,this->bufp->b_bcount,mountstr, this->bufp->_b_blkno._f,this->vnode,this->inode,stringof(sargs)); } fbt:genunix:biodone:entry /FORMAT == 2/ { printf("%-14d %5d %5d %6d %-10s %-7d %5d %s\n", timestamp/1000,this->suid,this->spid,this->bufp->b_bcount,mountstr, this->bufp->_b_blkno._f,this->inode,stringof(sargs)); } fbt:genunix:biodone:entry /FORMAT == 3/ { printf("%d %d %d %d %d %d %d %s %d %x %d %s\n", timestamp/1000,this->stime/1000,this->suid,this->spid,this->sppid, this->bufp->b_bcount,this->bufp->b_edev,mountstr, this->bufp->_b_blkno._f,this->vnode,this->inode,stringof(sargs)); }