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