Home | History | Annotate | Line # | Download | only in Bin
      1 #!/usr/bin/sh
      2 #
      3 # vopstat - Trace the vnode interface.
      4 #           Written using DTrace (Solaris 10 3/05)
      5 #
      6 # Author: Richard McDougall
      7 #
      8 # $Id: vopstat,v 1.1.1.1 2015/09/30 22:01:07 christos Exp $
      9 #
     10 # USAGE:	vopstat [-t] [/mountname]
     11 #
     12 #		vopstat		# default output, summary each 5 secs
     13 #		-t 		# trace activity as it occurs
     14 #
     15 # Example:
     16 #
     17 # ./vopstat
     18 # 
     19 # VOP Physical IO                                                   Count
     20 # fop_fsync                                                           236
     21 # 
     22 # VOP Count                                                         Count
     23 # fop_create                                                            1
     24 # fop_fid                                                               1
     25 # fop_lookup                                                            2
     26 # fop_access                                                            3
     27 # fop_read                                                              3
     28 # fop_poll                                                             11
     29 # fop_fsync                                                            31
     30 # fop_putpage                                                          32
     31 # fop_ioctl                                                           115
     32 # fop_write                                                           517
     33 # fop_rwlock                                                          520
     34 # fop_rwunlock                                                        520
     35 # fop_inactive                                                        529
     36 # fop_getattr                                                        1057
     37 # 
     38 # VOP Wall Time                                                  mSeconds
     39 # fop_fid                                                               0
     40 # fop_access                                                            0
     41 # fop_read                                                              0
     42 # fop_poll                                                              0
     43 # fop_lookup                                                            0
     44 # fop_create                                                            0
     45 # fop_ioctl                                                             0
     46 # fop_putpage                                                           1
     47 # fop_rwunlock                                                          1
     48 # fop_rwlock                                                            1
     49 # fop_inactive                                                          1
     50 # fop_getattr                                                           2
     51 # fop_write                                                            22
     52 # fop_fsync                                                           504
     53 # 
     54 # COPYRIGHT: Copyright (c) 2006 Richard McDougall
     55 #
     56 # CDDL HEADER START
     57 #
     58 #  The contents of this file are subject to the terms of the
     59 #  Common Development and Distribution License, Version 1.0 only
     60 #  (the "License").  You may not use this file except in compliance
     61 #  with the License.
     62 #
     63 #  You can obtain a copy of the license at Docs/cddl1.txt
     64 #  or http://www.opensolaris.org/os/licensing.
     65 #  See the License for the specific language governing permissions
     66 #  and limitations under the License.
     67 #
     68 # CDDL HEADER END
     69 #
     70 # Shell Wrapper Concept by Brendan Gregg
     71 #
     72 # 08-Jan-2006	Richard McDougall	Created this.
     73 # 23-Apr-2006	Brendan Gregg		Minor style tweaks.
     74 # 23-Apr-2006	   "      "		Last update.
     75 
     76 
     77 ##############################
     78 # --- Process Arguments ---
     79 #
     80 
     81 ### default variables
     82 opt_trace=0; opt_fs=0; opt_stats=1; opt_all=0
     83 
     84 ### process options
     85 while getopts t name
     86 do
     87 	case $name in
     88 	t)	opt_trace=1 ;;
     89 	h|?)	cat <<-END >&2
     90 		USAGE: voptrace [-t] [/mountpoint]
     91 		        voptrace         # default output
     92 		                 -t      # trace
     93 		   eg,
     94 		        voptrace -t      # trace all file systems
     95 		        voptrace -t /tmp # trace /tmp
     96 		        voptrace  /tmp   # summary stats for /tmp
     97 		END
     98 		exit 1
     99 	esac
    100 done
    101 shift `expr $OPTIND - 1`
    102 filesys="$1"
    103 
    104 ### option logic
    105 if [ $opt_trace -eq 1 ]; then
    106 	opt_stats=0
    107 fi
    108 if [ -z "$filesys" ]; then
    109 	opt_all=1
    110 fi
    111 
    112 #################################
    113 # --- Main Program, DTrace ---
    114 #
    115 /usr/sbin/dtrace -n '
    116  /*
    117   * Command line arguments
    118   */
    119  inline int OPT_fs 	= '$opt_fs';
    120  inline int OPT_all 	= '$opt_all';
    121  inline int OPT_trace 	= '$opt_trace';
    122  inline int OPT_stats 	= '$opt_stats';
    123  inline string FILESYS 	= "'$filesys'";
    124  
    125  #pragma D option quiet
    126 
    127  /*
    128   * Print header
    129   */
    130  dtrace:::BEGIN 
    131  {
    132 	last_event[""] = 0;
    133 
    134 	/* print main headers */
    135 	OPT_stats == 1 ?
    136 		printf("\033[H\033[2J") : 1;
    137 
    138 	OPT_trace == 1 ?
    139 		printf("%2s %-15s %-10s %51s %2s %8s %8s\n", 
    140 		    "", "Event", "Device", "Path", "RW", "Size", "Offset") : 1;
    141 	self->path = "";
    142 	self->trace = 0;
    143  }
    144 
    145  dtrace:::BEGIN
    146  /OPT_trace == 1/
    147  {
    148 	/* make D compiler happy */
    149 	@vop_iocnt[""] = count();
    150 	@vop_cnt[""]   = count();
    151 	@vop_time[""]  = sum(0);
    152 	trunc(@vop_iocnt);
    153 	trunc(@vop_cnt);
    154 	trunc(@vop_time);
    155  }
    156  
    157  fbt::fop_*:entry
    158  {
    159  	self->trace = 0;
    160 
    161  	/* Get vp: fop_open has a pointer to vp */
    162  	this->vpp = (vnode_t **)arg0;
    163  	self->vp = (vnode_t *)arg0;
    164  	self->vp = probefunc == "fop_open" ? (vnode_t *)*this->vpp : self->vp;
    165 
    166  	/* And the containing vfs */
    167          this->vfsp = self->vp ? self->vp->v_vfsp : 0;
    168 
    169  	/* And the paths for the vp and containing vfs */
    170  	this->vfsvp = this->vfsp ?
    171 	    (struct vnode *)((vfs_t *)this->vfsp)->vfs_vnodecovered : 0;
    172  	self->vfspath = this->vfsvp ? stringof(this->vfsvp->v_path) : "unknown";
    173  
    174  	/* Check if we should trace the root fs */
    175  	(OPT_all || 
    176  	    (FILESYS == "/" && this->vfsp &&
    177  	    (this->vfsp == `rootvfs))) ? self->trace = 1 : self->trace;
    178  
    179  	/* Check if we should trace the fs */
    180  	(OPT_all || (self->vfspath == FILESYS)) ? self->trace = 1 : self->trace;
    181 
    182 	self->vfspath = 0;
    183  }
    184  
    185  /*
    186   * Trace the entry point to each fop
    187   */ 
    188  fbt::fop_*:entry
    189  /self->trace/
    190  {
    191  	self->path = (self->vp != NULL && self->vp->v_path) ?
    192 	    stringof(self->vp->v_path) : "unknown";
    193  
    194  	/* Some fops has the len in arg2 */
    195  	(probefunc == "fop_getpage" ||
    196  	 probefunc == "fop_putpage" ||
    197  	 probefunc == "fop_none") ? self->len = arg2 : 1; 
    198  
    199  	/* Some fops has the len in arg3 */
    200  	(probefunc == "fop_pageio" ||
    201  	 probefunc == "fop_none") ? self->len = arg3 : 1; 
    202  
    203  	/* Some fops has the len in arg4 */
    204  	(probefunc == "fop_addmap" ||
    205  	 probefunc == "fop_map" ||
    206  	 probefunc == "fop_delmap") ? self->len = arg4 : 1; 
    207  
    208  	/* Some fops has the offset in arg1 */
    209  	(probefunc == "fop_addmap" ||
    210  	 probefunc == "fop_map" ||
    211  	 probefunc == "fop_getpage" ||
    212  	 probefunc == "fop_putpage" ||
    213  	 probefunc == "fop_seek" ||
    214  	 probefunc == "fop_delmap") ? self->off = arg1 : 1; 
    215  
    216  	/* Some fops has the offset in arg3 */
    217  	(probefunc == "fop_close" ||
    218  	 probefunc == "fop_pageio") ? self->off = arg3 : 1; 
    219  
    220  	/* Some fops has the offset in arg4 */
    221  	probefunc == "fop_frlock" ? self->off = arg4 : 1; 
    222  
    223  	/* Some fops has the pathname in arg1 */
    224  	self->path = (probefunc == "fop_create" ||
    225  	 probefunc == "fop_mkdir" ||
    226  	 probefunc == "fop_rmdir" ||
    227  	 probefunc == "fop_remove" ||
    228  	 probefunc == "fop_lookup") ?
    229  	    strjoin(self->path, strjoin("/", stringof(arg1))) : self->path;
    230  
    231 	OPT_trace ?
    232  		printf("%2s %-15s %-10s %51s %2s %8d %8d\n", 
    233  		    "->", probefunc, "-", self->path, "-",
    234 		    self->len, self->off) : 1;
    235 
    236  	self->type = probefunc;
    237  	self->vop_entry[probefunc] = timestamp;
    238  }
    239  
    240  fbt::fop_*:return
    241  /self->trace == 1/
    242  {
    243 	OPT_trace ?
    244  		printf("%2s %-15s %-10s %51s %2s %8d %8d\n", 
    245 		    "<-", probefunc, "-", self->path, "-",
    246 		    self->len, self->off) : 1;
    247 
    248 	OPT_stats == 1 ?
    249  		@vop_time[probefunc] =
    250 			sum(timestamp - self->vop_entry[probefunc]) : 1;
    251 	OPT_stats == 1 ?
    252  		@vop_cnt[probefunc] = count() : 1;
    253 
    254 	self->path = 0;
    255 	self->len = 0;
    256 	self->off = 0;
    257  }
    258 
    259  fbt::fop_*:return
    260  {
    261 	self->trace = 0;
    262 	self->type = 0;
    263 	self->vp = 0;
    264  }
    265  
    266  /* Capture any I/O within this fop */
    267  io:::start
    268  /self->trace/
    269  {
    270 	OPT_stats == 1 ?
    271  		@vop_iocnt[self->type] = count() : 1;
    272 
    273 	OPT_trace == 1?
    274 	 	printf("%2s %-15s %-10s %51s %2s %8d %8u\n",
    275 		    "--", self->type, args[1]->dev_statname,
    276 		    self->path, args[0]->b_flags & B_READ ? "R" : "W",
    277 		    args[0]->b_bcount, args[0]->b_blkno) : 1;
    278  }
    279  
    280  profile:::tick-5s
    281  /OPT_stats == 1/
    282  {
    283 	/* Print top 20 only */
    284  	trunc(@vop_iocnt, 20);
    285  	trunc(@vop_time, 20);
    286 
    287 	/* Display microseconds */
    288  	normalize(@vop_time, 1000000);
    289  	printf("\033[H\033[2J");
    290  	printf("%-60s %10s\n", "VOP Physical IO", "Count");
    291  	printa("%-60s %10@d\n", @vop_iocnt);
    292  	printf("\n");
    293  	printf("%-60s %10s\n", "VOP Count", "Count");
    294  	printa("%-60s %10@d\n", @vop_cnt);
    295  	printf("\n");
    296  	printf("%-60s %10s\n", "VOP Wall Time", "mSeconds");
    297  	printa("%-60s %10@d\n", @vop_time);
    298 
    299 	/* Clear data */
    300  	trunc(@vop_iocnt);
    301  	trunc(@vop_cnt);
    302  	trunc(@vop_time);
    303  }
    304 '
    305