]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/FS/vopstat
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / FS / vopstat
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 3 2007-08-01 10:50:08Z brendan $
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 '