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