]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/dtracetoolkit/rwsnoop
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / cddl / contrib / dtracetoolkit / rwsnoop
1 #!/usr/bin/ksh
2 #
3 # rwsnoop - snoop read/write events.
4 #           Written using DTrace (Solaris 10 3/05).
5 #
6 # This is measuring reads and writes at the application level. This matches
7 # the syscalls read, write, pread and pwrite.
8 #
9 # $Id: rwsnoop 3 2007-08-01 10:50:08Z brendan $
10 #
11 # USAGE:        rwsnoop [-jPtvZ] [-n name] [-p pid]
12
13 #               rwsnoop         # default output
14 #
15 #               -j              # print project ID
16 #               -P              # print parent process ID
17 #               -t              # print timestamp, us
18 #               -v              # print time, string
19 #               -Z              # print zone ID
20 #               -n name         # this process name only
21 #               -p PID          # this PID only
22 #       eg,
23 #               rwsnoop -Z              # print zone ID
24 #               rwsnoop -n bash         # monitor processes named "bash"
25 #               rwsnoop > out.txt       # recommended
26 #
27 # NOTE:
28 #       rwsnoop usually prints plenty of output, which itself will cause
29 #       more output. It can be better to redirect the output of rwsnoop
30 #       to a file to prevent this.
31 #
32 # FIELDS:
33 #               TIME            Timestamp, us
34 #               TIMESTR         Time, string
35 #               ZONE            Zone ID
36 #               PROJ            Project ID
37 #               UID             User ID
38 #               PID             Process ID
39 #               PPID            Parent Process ID
40 #               CMD             Process name
41 #               D               Direction, Read or Write
42 #               BYTES           Total bytes during sample, -1 for error
43 #               FILE            Filename, if file based
44 #
45 # Reads and writes that are not file based, for example with sockets, will
46 # print "<unknown>" as the filename.
47 #
48 # SEE ALSO:     rwtop
49 #
50 # COPYRIGHT: Copyright (c) 2005 Brendan Gregg.
51 #
52 # CDDL HEADER START
53 #
54 #  The contents of this file are subject to the terms of the
55 #  Common Development and Distribution License, Version 1.0 only
56 #  (the "License").  You may not use this file except in compliance
57 #  with the License.
58 #
59 #  You can obtain a copy of the license at Docs/cddl1.txt
60 #  or http://www.opensolaris.org/os/licensing.
61 #  See the License for the specific language governing permissions
62 #  and limitations under the License.
63 #
64 # CDDL HEADER END
65 #
66 # TODO:
67 #  Track readv and writev.
68 #
69 # Author: Brendan Gregg  [Sydney, Australia]
70 #
71 # 24-Jul-2005   Brendan Gregg   Created this.
72 # 17-Sep-2005      "      "     Increased switchrate.
73 # 17-Sep-2005      "      "     Last update.
74 #
75
76
77 ##############################
78 # --- Process Arguments ---
79 #
80
81 ### default variables
82 opt_name=0; opt_pid=0; opt_proj=0; opt_zone=0; opt_time=0; opt_timestr=0
83 opt_bytes=1; filter=0; pname=.; pid=0; opt_ppid=0
84
85 ### process options
86 while getopts n:Pp:jtvZ name
87 do
88         case $name in
89         n)      opt_name=1; pname=$OPTARG ;;
90         p)      opt_pid=1; pid=$OPTARG ;;
91         P)      opt_ppid=1 ;;
92         j)      opt_proj=1 ;;
93         t)      opt_time=1 ;;
94         v)      opt_timestr=1 ;;
95         Z)      opt_zone=1 ;;
96         h|?)    cat <<-END >&2
97                 USAGE: rwsnoop [-jPtvZ] [-n name] [-p pid]
98  
99                                 -j       # print project ID
100                                 -P       # print parent process ID
101                                 -t       # print timestamp, us
102                                 -v       # print time, string
103                                 -Z       # print zone ID
104                                 -n name  # this process name only
105                                 -p PID   # this PID only
106                    eg,
107                         rwsnoop          # default output
108                         rwsnoop -Z       # print zone ID
109                         rwsnoop -n bash  # monitor processes named "bash"
110                 END
111                 exit 1
112         esac
113 done
114
115 shift $(( $OPTIND - 1 ))
116
117 ### option logic
118 if (( opt_name || opt_pid )); then
119         filter=1
120 fi
121
122
123
124 #################################
125 # --- Main Program, DTrace ---
126 #
127 /usr/sbin/dtrace -n '
128  /*
129   * Command line arguments
130   */
131  inline int OPT_proj    = '$opt_proj';
132  inline int OPT_zone    = '$opt_zone';
133  inline int OPT_bytes   = '$opt_bytes';
134  inline int OPT_name    = '$opt_name';
135  inline int OPT_ppid    = '$opt_ppid';
136  inline int OPT_pid     = '$opt_pid';
137  inline int OPT_time    = '$opt_time';
138  inline int OPT_timestr = '$opt_timestr';
139  inline int FILTER      = '$filter';
140  inline int PID         = '$pid';
141  inline string NAME     = "'$pname'";
142  
143  #pragma D option quiet
144  #pragma D option switchrate=10hz
145
146  /*
147   * Print header
148   */
149  dtrace:::BEGIN 
150  {
151         /* print header */
152         OPT_time    ? printf("%-14s ", "TIME") : 1;
153         OPT_timestr ? printf("%-20s ", "TIMESTR") : 1;
154         OPT_proj    ? printf("%5s ", "PROJ") : 1;
155         OPT_zone    ? printf("%5s ", "ZONE") : 1;
156         OPT_ppid    ? printf("%6s ", "PPID") : 1;
157         printf("%5s %6s %-12s %1s %7s %s\n",
158             "UID", "PID", "CMD", "D", "BYTES", "FILE");
159  }
160
161  /*
162   * Check event is being traced
163   */
164  syscall::*read:entry,
165  syscall::*write:entry
166  /pid != $pid/
167  { 
168         /* default is to trace unless filtering, */
169         self->ok = FILTER ? 0 : 1;
170
171         /* check each filter, */
172         (OPT_name == 1 && NAME == execname)? self->ok = 1 : 1;
173         (OPT_pid == 1 && PID == pid) ? self->ok = 1 : 1;
174
175         /* save file descriptor */
176         self->fd = self->ok ? arg0 : 0;
177  }
178
179  /*
180   * Save read details
181   */
182  syscall::*read:return
183  /self->ok/
184  {
185         self->rw = "R";
186         self->size = arg0;
187  }
188
189  /*
190   * Save write details
191   */
192  syscall::*write:entry
193  /self->ok/
194  {
195         self->rw = "W";
196         self->size = arg2;
197  }
198
199  /*
200   * Process event
201   */
202  syscall::*read:return,
203  syscall::*write:entry
204  /self->ok/
205  {
206         /*
207          * Fetch filename
208          */
209         this->filistp = curthread->t_procp->p_user.u_finfo.fi_list;
210         this->ufentryp = (uf_entry_t *)((uint64_t)this->filistp +
211             (uint64_t)self->fd * (uint64_t)sizeof(uf_entry_t));
212         this->filep = this->ufentryp->uf_file;
213         this->vnodep = this->filep != 0 ? this->filep->f_vnode : 0;
214         self->vpath = this->vnodep ? (this->vnodep->v_path != 0 ? 
215             cleanpath(this->vnodep->v_path) : "<unknown>") : "<unknown>";
216
217         /*
218          * Print details
219          */
220         OPT_time    ? printf("%-14d ", timestamp / 1000) : 1;
221         OPT_timestr ? printf("%-20Y ", walltimestamp) : 1;
222         OPT_proj    ? printf("%5d ", curpsinfo->pr_projid) : 1;
223         OPT_zone    ? printf("%5d ", curpsinfo->pr_zoneid) : 1;
224         OPT_ppid    ? printf("%6d ", ppid) : 1;
225         printf("%5d %6d %-12.12s %1s %7d %s\n",
226             uid, pid, execname, self->rw, (int)self->size, self->vpath);
227         
228         self->ok = 0;
229         self->fd = 0;
230         self->rw = 0;
231         self->size = 0;
232         self->vpath = 0;
233  }
234 '