nfs_clkdtrace.c revision 1.1 1 1.1 pgoyette /* $NetBSD: nfs_clkdtrace.c,v 1.1 2016/11/18 07:49:10 pgoyette Exp $ */
2 1.1 pgoyette /*-
3 1.1 pgoyette * Copyright (c) 2009 Robert N. M. Watson
4 1.1 pgoyette * All rights reserved.
5 1.1 pgoyette *
6 1.1 pgoyette * This software was developed at the University of Cambridge Computer
7 1.1 pgoyette * Laboratory with support from a grant from Google, Inc.
8 1.1 pgoyette *
9 1.1 pgoyette * Redistribution and use in source and binary forms, with or without
10 1.1 pgoyette * modification, are permitted provided that the following conditions
11 1.1 pgoyette * are met:
12 1.1 pgoyette * 1. Redistributions of source code must retain the above copyright
13 1.1 pgoyette * notice, this list of conditions and the following disclaimer.
14 1.1 pgoyette * 2. Redistributions in binary form must reproduce the above copyright
15 1.1 pgoyette * notice, this list of conditions and the following disclaimer in the
16 1.1 pgoyette * documentation and/or other materials provided with the distribution.
17 1.1 pgoyette *
18 1.1 pgoyette * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 1.1 pgoyette * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 1.1 pgoyette * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 1.1 pgoyette * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 1.1 pgoyette * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 1.1 pgoyette * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 1.1 pgoyette * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 1.1 pgoyette * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 1.1 pgoyette * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 1.1 pgoyette * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 1.1 pgoyette * SUCH DAMAGE.
29 1.1 pgoyette */
30 1.1 pgoyette
31 1.1 pgoyette #include <sys/cdefs.h>
32 1.1 pgoyette /* __FBSDID("FreeBSD: head/sys/fs/nfsclient/nfs_clkdtrace.c 298788 2016-04-29 16:07:25Z pfg "); */
33 1.1 pgoyette __RCSID("$NetBSD: nfs_clkdtrace.c,v 1.1 2016/11/18 07:49:10 pgoyette Exp $");
34 1.1 pgoyette
35 1.1 pgoyette #include <sys/param.h>
36 1.1 pgoyette #include <sys/systm.h>
37 1.1 pgoyette #include <sys/conf.h>
38 1.1 pgoyette #include <sys/kernel.h>
39 1.1 pgoyette #include <sys/malloc.h>
40 1.1 pgoyette #include <sys/module.h>
41 1.1 pgoyette
42 1.1 pgoyette #include <sys/dtrace.h>
43 1.1 pgoyette #include <sys/dtrace_bsd.h>
44 1.1 pgoyette
45 1.1 pgoyette #include <fs/nfs/nfsproto.h>
46 1.1 pgoyette
47 1.1 pgoyette #include <fs/nfsclient/nfs_kdtrace.h>
48 1.1 pgoyette
49 1.1 pgoyette /*
50 1.1 pgoyette * dtnfscl is a DTrace provider that tracks the intent to perform RPCs
51 1.1 pgoyette * in the NFS client, as well as access to and maintenance of the access and
52 1.1 pgoyette * attribute caches. This is not quite the same as RPCs, because NFS may
53 1.1 pgoyette * issue multiple RPC transactions in the event that authentication fails,
54 1.1 pgoyette * there's a jukebox error, or none at all if the access or attribute cache
55 1.1 pgoyette * hits. However, it cleanly represents the logical layer between RPC
56 1.1 pgoyette * transmission and vnode/vfs operations, providing access to state linking
57 1.1 pgoyette * the two.
58 1.1 pgoyette */
59 1.1 pgoyette
60 1.1 pgoyette static int dtnfsclient_unload(void);
61 1.1 pgoyette static void dtnfsclient_getargdesc(void *, dtrace_id_t, void *,
62 1.1 pgoyette dtrace_argdesc_t *);
63 1.1 pgoyette static void dtnfsclient_provide(void *, dtrace_probedesc_t *);
64 1.1 pgoyette static void dtnfsclient_destroy(void *, dtrace_id_t, void *);
65 1.1 pgoyette static void dtnfsclient_enable(void *, dtrace_id_t, void *);
66 1.1 pgoyette static void dtnfsclient_disable(void *, dtrace_id_t, void *);
67 1.1 pgoyette static void dtnfsclient_load(void *);
68 1.1 pgoyette
69 1.1 pgoyette static dtrace_pattr_t dtnfsclient_attr = {
70 1.1 pgoyette { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
71 1.1 pgoyette { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
72 1.1 pgoyette { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
73 1.1 pgoyette { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
74 1.1 pgoyette { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
75 1.1 pgoyette };
76 1.1 pgoyette
77 1.1 pgoyette /*
78 1.1 pgoyette * Description of NFSv4, NFSv3 and (optional) NFSv2 probes for a procedure.
79 1.1 pgoyette */
80 1.1 pgoyette struct dtnfsclient_rpc {
81 1.1 pgoyette char *nr_v4_name;
82 1.1 pgoyette char *nr_v3_name; /* Or NULL if none. */
83 1.1 pgoyette char *nr_v2_name; /* Or NULL if none. */
84 1.1 pgoyette
85 1.1 pgoyette /*
86 1.1 pgoyette * IDs for the start and done cases, for NFSv2, NFSv3 and NFSv4.
87 1.1 pgoyette */
88 1.1 pgoyette uint32_t nr_v2_id_start, nr_v2_id_done;
89 1.1 pgoyette uint32_t nr_v3_id_start, nr_v3_id_done;
90 1.1 pgoyette uint32_t nr_v4_id_start, nr_v4_id_done;
91 1.1 pgoyette };
92 1.1 pgoyette
93 1.1 pgoyette /*
94 1.1 pgoyette * This table is indexed by NFSv3 procedure number, but also used for NFSv2
95 1.1 pgoyette * procedure names and NFSv4 operations.
96 1.1 pgoyette */
97 1.1 pgoyette static struct dtnfsclient_rpc dtnfsclient_rpcs[NFSV41_NPROCS + 1] = {
98 1.1 pgoyette { "null", "null", "null" },
99 1.1 pgoyette { "getattr", "getattr", "getattr" },
100 1.1 pgoyette { "setattr", "setattr", "setattr" },
101 1.1 pgoyette { "lookup", "lookup", "lookup" },
102 1.1 pgoyette { "access", "access", "noop" },
103 1.1 pgoyette { "readlink", "readlink", "readlink" },
104 1.1 pgoyette { "read", "read", "read" },
105 1.1 pgoyette { "write", "write", "write" },
106 1.1 pgoyette { "create", "create", "create" },
107 1.1 pgoyette { "mkdir", "mkdir", "mkdir" },
108 1.1 pgoyette { "symlink", "symlink", "symlink" },
109 1.1 pgoyette { "mknod", "mknod" },
110 1.1 pgoyette { "remove", "remove", "remove" },
111 1.1 pgoyette { "rmdir", "rmdir", "rmdir" },
112 1.1 pgoyette { "rename", "rename", "rename" },
113 1.1 pgoyette { "link", "link", "link" },
114 1.1 pgoyette { "readdir", "readdir", "readdir" },
115 1.1 pgoyette { "readdirplus", "readdirplus" },
116 1.1 pgoyette { "fsstat", "fsstat", "statfs" },
117 1.1 pgoyette { "fsinfo", "fsinfo" },
118 1.1 pgoyette { "pathconf", "pathconf" },
119 1.1 pgoyette { "commit", "commit" },
120 1.1 pgoyette { "lookupp" },
121 1.1 pgoyette { "setclientid" },
122 1.1 pgoyette { "setclientidcfrm" },
123 1.1 pgoyette { "lock" },
124 1.1 pgoyette { "locku" },
125 1.1 pgoyette { "open" },
126 1.1 pgoyette { "close" },
127 1.1 pgoyette { "openconfirm" },
128 1.1 pgoyette { "lockt" },
129 1.1 pgoyette { "opendowngrade" },
130 1.1 pgoyette { "renew" },
131 1.1 pgoyette { "putrootfh" },
132 1.1 pgoyette { "releaselckown" },
133 1.1 pgoyette { "delegreturn" },
134 1.1 pgoyette { "retdelegremove" },
135 1.1 pgoyette { "retdelegrename1" },
136 1.1 pgoyette { "retdelegrename2" },
137 1.1 pgoyette { "getacl" },
138 1.1 pgoyette { "setacl" },
139 1.1 pgoyette { "noop", "noop", "noop" }
140 1.1 pgoyette };
141 1.1 pgoyette
142 1.1 pgoyette /*
143 1.1 pgoyette * Module name strings.
144 1.1 pgoyette */
145 1.1 pgoyette static char *dtnfsclient_accesscache_str = "accesscache";
146 1.1 pgoyette static char *dtnfsclient_attrcache_str = "attrcache";
147 1.1 pgoyette static char *dtnfsclient_nfs2_str = "nfs2";
148 1.1 pgoyette static char *dtnfsclient_nfs3_str = "nfs3";
149 1.1 pgoyette static char *dtnfsclient_nfs4_str = "nfs4";
150 1.1 pgoyette
151 1.1 pgoyette /*
152 1.1 pgoyette * Function name strings.
153 1.1 pgoyette */
154 1.1 pgoyette static char *dtnfsclient_flush_str = "flush";
155 1.1 pgoyette static char *dtnfsclient_load_str = "load";
156 1.1 pgoyette static char *dtnfsclient_get_str = "get";
157 1.1 pgoyette
158 1.1 pgoyette /*
159 1.1 pgoyette * Name strings.
160 1.1 pgoyette */
161 1.1 pgoyette static char *dtnfsclient_done_str = "done";
162 1.1 pgoyette static char *dtnfsclient_hit_str = "hit";
163 1.1 pgoyette static char *dtnfsclient_miss_str = "miss";
164 1.1 pgoyette static char *dtnfsclient_start_str = "start";
165 1.1 pgoyette
166 1.1 pgoyette static dtrace_pops_t dtnfsclient_pops = {
167 1.1 pgoyette dtnfsclient_provide,
168 1.1 pgoyette NULL,
169 1.1 pgoyette dtnfsclient_enable,
170 1.1 pgoyette dtnfsclient_disable,
171 1.1 pgoyette NULL,
172 1.1 pgoyette NULL,
173 1.1 pgoyette dtnfsclient_getargdesc,
174 1.1 pgoyette NULL,
175 1.1 pgoyette NULL,
176 1.1 pgoyette dtnfsclient_destroy
177 1.1 pgoyette };
178 1.1 pgoyette
179 1.1 pgoyette static dtrace_provider_id_t dtnfsclient_id;
180 1.1 pgoyette
181 1.1 pgoyette /*
182 1.1 pgoyette * When tracing on a procedure is enabled, the DTrace ID for an RPC event is
183 1.1 pgoyette * stored in one of these two NFS client-allocated arrays; 0 indicates that
184 1.1 pgoyette * the event is not being traced so probes should not be called.
185 1.1 pgoyette *
186 1.1 pgoyette * For simplicity, we allocate both v2, v3 and v4 arrays as NFSV41_NPROCS + 1,
187 1.1 pgoyette * and the v2, v3 arrays are simply sparse.
188 1.1 pgoyette */
189 1.1 pgoyette extern uint32_t nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
190 1.1 pgoyette extern uint32_t nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
191 1.1 pgoyette
192 1.1 pgoyette extern uint32_t nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
193 1.1 pgoyette extern uint32_t nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
194 1.1 pgoyette
195 1.1 pgoyette extern uint32_t nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
196 1.1 pgoyette extern uint32_t nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
197 1.1 pgoyette
198 1.1 pgoyette /*
199 1.1 pgoyette * Look up a DTrace probe ID to see if it's associated with a "done" event --
200 1.1 pgoyette * if so, we will return a fourth argument type of "int".
201 1.1 pgoyette */
202 1.1 pgoyette static int
203 1.1 pgoyette dtnfs234_isdoneprobe(dtrace_id_t id)
204 1.1 pgoyette {
205 1.1 pgoyette int i;
206 1.1 pgoyette
207 1.1 pgoyette for (i = 0; i < NFSV41_NPROCS + 1; i++) {
208 1.1 pgoyette if (dtnfsclient_rpcs[i].nr_v4_id_done == id ||
209 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_id_done == id ||
210 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_id_done == id)
211 1.1 pgoyette return (1);
212 1.1 pgoyette }
213 1.1 pgoyette return (0);
214 1.1 pgoyette }
215 1.1 pgoyette
216 1.1 pgoyette static void
217 1.1 pgoyette dtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg,
218 1.1 pgoyette dtrace_argdesc_t *desc)
219 1.1 pgoyette {
220 1.1 pgoyette const char *p = NULL;
221 1.1 pgoyette
222 1.1 pgoyette if (id == nfscl_accesscache_flush_done_id ||
223 1.1 pgoyette id == nfscl_attrcache_flush_done_id ||
224 1.1 pgoyette id == nfscl_attrcache_get_miss_id) {
225 1.1 pgoyette switch (desc->dtargd_ndx) {
226 1.1 pgoyette case 0:
227 1.1 pgoyette p = "struct vnode *";
228 1.1 pgoyette break;
229 1.1 pgoyette default:
230 1.1 pgoyette desc->dtargd_ndx = DTRACE_ARGNONE;
231 1.1 pgoyette break;
232 1.1 pgoyette }
233 1.1 pgoyette } else if (id == nfscl_accesscache_get_hit_id ||
234 1.1 pgoyette id == nfscl_accesscache_get_miss_id) {
235 1.1 pgoyette switch (desc->dtargd_ndx) {
236 1.1 pgoyette case 0:
237 1.1 pgoyette p = "struct vnode *";
238 1.1 pgoyette break;
239 1.1 pgoyette case 1:
240 1.1 pgoyette p = "uid_t";
241 1.1 pgoyette break;
242 1.1 pgoyette case 2:
243 1.1 pgoyette p = "uint32_t";
244 1.1 pgoyette break;
245 1.1 pgoyette default:
246 1.1 pgoyette desc->dtargd_ndx = DTRACE_ARGNONE;
247 1.1 pgoyette break;
248 1.1 pgoyette }
249 1.1 pgoyette } else if (id == nfscl_accesscache_load_done_id) {
250 1.1 pgoyette switch (desc->dtargd_ndx) {
251 1.1 pgoyette case 0:
252 1.1 pgoyette p = "struct vnode *";
253 1.1 pgoyette break;
254 1.1 pgoyette case 1:
255 1.1 pgoyette p = "uid_t";
256 1.1 pgoyette break;
257 1.1 pgoyette case 2:
258 1.1 pgoyette p = "uint32_t";
259 1.1 pgoyette break;
260 1.1 pgoyette case 3:
261 1.1 pgoyette p = "int";
262 1.1 pgoyette break;
263 1.1 pgoyette default:
264 1.1 pgoyette desc->dtargd_ndx = DTRACE_ARGNONE;
265 1.1 pgoyette break;
266 1.1 pgoyette }
267 1.1 pgoyette } else if (id == nfscl_attrcache_get_hit_id) {
268 1.1 pgoyette switch (desc->dtargd_ndx) {
269 1.1 pgoyette case 0:
270 1.1 pgoyette p = "struct vnode *";
271 1.1 pgoyette break;
272 1.1 pgoyette case 1:
273 1.1 pgoyette p = "struct vattr *";
274 1.1 pgoyette break;
275 1.1 pgoyette default:
276 1.1 pgoyette desc->dtargd_ndx = DTRACE_ARGNONE;
277 1.1 pgoyette break;
278 1.1 pgoyette }
279 1.1 pgoyette } else if (id == nfscl_attrcache_load_done_id) {
280 1.1 pgoyette switch (desc->dtargd_ndx) {
281 1.1 pgoyette case 0:
282 1.1 pgoyette p = "struct vnode *";
283 1.1 pgoyette break;
284 1.1 pgoyette case 1:
285 1.1 pgoyette p = "struct vattr *";
286 1.1 pgoyette break;
287 1.1 pgoyette case 2:
288 1.1 pgoyette p = "int";
289 1.1 pgoyette break;
290 1.1 pgoyette default:
291 1.1 pgoyette desc->dtargd_ndx = DTRACE_ARGNONE;
292 1.1 pgoyette break;
293 1.1 pgoyette }
294 1.1 pgoyette } else {
295 1.1 pgoyette switch (desc->dtargd_ndx) {
296 1.1 pgoyette case 0:
297 1.1 pgoyette p = "struct vnode *";
298 1.1 pgoyette break;
299 1.1 pgoyette case 1:
300 1.1 pgoyette p = "struct mbuf *";
301 1.1 pgoyette break;
302 1.1 pgoyette case 2:
303 1.1 pgoyette p = "struct ucred *";
304 1.1 pgoyette break;
305 1.1 pgoyette case 3:
306 1.1 pgoyette p = "int";
307 1.1 pgoyette break;
308 1.1 pgoyette case 4:
309 1.1 pgoyette if (dtnfs234_isdoneprobe(id)) {
310 1.1 pgoyette p = "int";
311 1.1 pgoyette break;
312 1.1 pgoyette }
313 1.1 pgoyette /* FALLSTHROUGH */
314 1.1 pgoyette default:
315 1.1 pgoyette desc->dtargd_ndx = DTRACE_ARGNONE;
316 1.1 pgoyette break;
317 1.1 pgoyette }
318 1.1 pgoyette }
319 1.1 pgoyette if (p != NULL)
320 1.1 pgoyette strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
321 1.1 pgoyette }
322 1.1 pgoyette
323 1.1 pgoyette static void
324 1.1 pgoyette dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
325 1.1 pgoyette {
326 1.1 pgoyette int i;
327 1.1 pgoyette
328 1.1 pgoyette if (desc != NULL)
329 1.1 pgoyette return;
330 1.1 pgoyette
331 1.1 pgoyette /*
332 1.1 pgoyette * Register access cache probes.
333 1.1 pgoyette */
334 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
335 1.1 pgoyette dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
336 1.1 pgoyette nfscl_accesscache_flush_done_id = dtrace_probe_create(
337 1.1 pgoyette dtnfsclient_id, dtnfsclient_accesscache_str,
338 1.1 pgoyette dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
339 1.1 pgoyette }
340 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
341 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
342 1.1 pgoyette nfscl_accesscache_get_hit_id = dtrace_probe_create(
343 1.1 pgoyette dtnfsclient_id, dtnfsclient_accesscache_str,
344 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
345 1.1 pgoyette }
346 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
347 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
348 1.1 pgoyette nfscl_accesscache_get_miss_id = dtrace_probe_create(
349 1.1 pgoyette dtnfsclient_id, dtnfsclient_accesscache_str,
350 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
351 1.1 pgoyette }
352 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
353 1.1 pgoyette dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
354 1.1 pgoyette nfscl_accesscache_load_done_id = dtrace_probe_create(
355 1.1 pgoyette dtnfsclient_id, dtnfsclient_accesscache_str,
356 1.1 pgoyette dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
357 1.1 pgoyette }
358 1.1 pgoyette
359 1.1 pgoyette /*
360 1.1 pgoyette * Register attribute cache probes.
361 1.1 pgoyette */
362 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
363 1.1 pgoyette dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
364 1.1 pgoyette nfscl_attrcache_flush_done_id = dtrace_probe_create(
365 1.1 pgoyette dtnfsclient_id, dtnfsclient_attrcache_str,
366 1.1 pgoyette dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
367 1.1 pgoyette }
368 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
369 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
370 1.1 pgoyette nfscl_attrcache_get_hit_id = dtrace_probe_create(
371 1.1 pgoyette dtnfsclient_id, dtnfsclient_attrcache_str,
372 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
373 1.1 pgoyette }
374 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
375 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
376 1.1 pgoyette nfscl_attrcache_get_miss_id = dtrace_probe_create(
377 1.1 pgoyette dtnfsclient_id, dtnfsclient_attrcache_str,
378 1.1 pgoyette dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
379 1.1 pgoyette }
380 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
381 1.1 pgoyette dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
382 1.1 pgoyette nfscl_attrcache_load_done_id = dtrace_probe_create(
383 1.1 pgoyette dtnfsclient_id, dtnfsclient_attrcache_str,
384 1.1 pgoyette dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
385 1.1 pgoyette }
386 1.1 pgoyette
387 1.1 pgoyette /*
388 1.1 pgoyette * Register NFSv2 RPC procedures; note sparseness check for each slot
389 1.1 pgoyette * in the NFSv3, NFSv4 procnum-indexed array.
390 1.1 pgoyette */
391 1.1 pgoyette for (i = 0; i < NFSV41_NPROCS + 1; i++) {
392 1.1 pgoyette if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
393 1.1 pgoyette dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
394 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
395 1.1 pgoyette 0) {
396 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_id_start =
397 1.1 pgoyette dtrace_probe_create(dtnfsclient_id,
398 1.1 pgoyette dtnfsclient_nfs2_str,
399 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_name,
400 1.1 pgoyette dtnfsclient_start_str, 0,
401 1.1 pgoyette &nfscl_nfs2_start_probes[i]);
402 1.1 pgoyette }
403 1.1 pgoyette if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
404 1.1 pgoyette dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
405 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) ==
406 1.1 pgoyette 0) {
407 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_id_done =
408 1.1 pgoyette dtrace_probe_create(dtnfsclient_id,
409 1.1 pgoyette dtnfsclient_nfs2_str,
410 1.1 pgoyette dtnfsclient_rpcs[i].nr_v2_name,
411 1.1 pgoyette dtnfsclient_done_str, 0,
412 1.1 pgoyette &nfscl_nfs2_done_probes[i]);
413 1.1 pgoyette }
414 1.1 pgoyette }
415 1.1 pgoyette
416 1.1 pgoyette /*
417 1.1 pgoyette * Register NFSv3 RPC procedures; note sparseness check for each slot
418 1.1 pgoyette * in the NFSv4 procnum-indexed array.
419 1.1 pgoyette */
420 1.1 pgoyette for (i = 0; i < NFSV41_NPROCS + 1; i++) {
421 1.1 pgoyette if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
422 1.1 pgoyette dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
423 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
424 1.1 pgoyette 0) {
425 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_id_start =
426 1.1 pgoyette dtrace_probe_create(dtnfsclient_id,
427 1.1 pgoyette dtnfsclient_nfs3_str,
428 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_name,
429 1.1 pgoyette dtnfsclient_start_str, 0,
430 1.1 pgoyette &nfscl_nfs3_start_probes[i]);
431 1.1 pgoyette }
432 1.1 pgoyette if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
433 1.1 pgoyette dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
434 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) ==
435 1.1 pgoyette 0) {
436 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_id_done =
437 1.1 pgoyette dtrace_probe_create(dtnfsclient_id,
438 1.1 pgoyette dtnfsclient_nfs3_str,
439 1.1 pgoyette dtnfsclient_rpcs[i].nr_v3_name,
440 1.1 pgoyette dtnfsclient_done_str, 0,
441 1.1 pgoyette &nfscl_nfs3_done_probes[i]);
442 1.1 pgoyette }
443 1.1 pgoyette }
444 1.1 pgoyette
445 1.1 pgoyette /*
446 1.1 pgoyette * Register NFSv4 RPC procedures.
447 1.1 pgoyette */
448 1.1 pgoyette for (i = 0; i < NFSV41_NPROCS + 1; i++) {
449 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
450 1.1 pgoyette dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_start_str) ==
451 1.1 pgoyette 0) {
452 1.1 pgoyette dtnfsclient_rpcs[i].nr_v4_id_start =
453 1.1 pgoyette dtrace_probe_create(dtnfsclient_id,
454 1.1 pgoyette dtnfsclient_nfs4_str,
455 1.1 pgoyette dtnfsclient_rpcs[i].nr_v4_name,
456 1.1 pgoyette dtnfsclient_start_str, 0,
457 1.1 pgoyette &nfscl_nfs4_start_probes[i]);
458 1.1 pgoyette }
459 1.1 pgoyette if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
460 1.1 pgoyette dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_done_str) ==
461 1.1 pgoyette 0) {
462 1.1 pgoyette dtnfsclient_rpcs[i].nr_v4_id_done =
463 1.1 pgoyette dtrace_probe_create(dtnfsclient_id,
464 1.1 pgoyette dtnfsclient_nfs4_str,
465 1.1 pgoyette dtnfsclient_rpcs[i].nr_v4_name,
466 1.1 pgoyette dtnfsclient_done_str, 0,
467 1.1 pgoyette &nfscl_nfs4_done_probes[i]);
468 1.1 pgoyette }
469 1.1 pgoyette }
470 1.1 pgoyette }
471 1.1 pgoyette
472 1.1 pgoyette static void
473 1.1 pgoyette dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg)
474 1.1 pgoyette {
475 1.1 pgoyette }
476 1.1 pgoyette
477 1.1 pgoyette static void
478 1.1 pgoyette dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg)
479 1.1 pgoyette {
480 1.1 pgoyette uint32_t *p = parg;
481 1.1 pgoyette void *f = dtrace_probe;
482 1.1 pgoyette
483 1.1 pgoyette if (id == nfscl_accesscache_flush_done_id)
484 1.1 pgoyette dtrace_nfscl_accesscache_flush_done_probe = f;
485 1.1 pgoyette else if (id == nfscl_accesscache_get_hit_id)
486 1.1 pgoyette dtrace_nfscl_accesscache_get_hit_probe = f;
487 1.1 pgoyette else if (id == nfscl_accesscache_get_miss_id)
488 1.1 pgoyette dtrace_nfscl_accesscache_get_miss_probe = f;
489 1.1 pgoyette else if (id == nfscl_accesscache_load_done_id)
490 1.1 pgoyette dtrace_nfscl_accesscache_load_done_probe = f;
491 1.1 pgoyette else if (id == nfscl_attrcache_flush_done_id)
492 1.1 pgoyette dtrace_nfscl_attrcache_flush_done_probe = f;
493 1.1 pgoyette else if (id == nfscl_attrcache_get_hit_id)
494 1.1 pgoyette dtrace_nfscl_attrcache_get_hit_probe = f;
495 1.1 pgoyette else if (id == nfscl_attrcache_get_miss_id)
496 1.1 pgoyette dtrace_nfscl_attrcache_get_miss_probe = f;
497 1.1 pgoyette else if (id == nfscl_attrcache_load_done_id)
498 1.1 pgoyette dtrace_nfscl_attrcache_load_done_probe = f;
499 1.1 pgoyette else
500 1.1 pgoyette *p = id;
501 1.1 pgoyette }
502 1.1 pgoyette
503 1.1 pgoyette static void
504 1.1 pgoyette dtnfsclient_disable(void *arg, dtrace_id_t id, void *parg)
505 1.1 pgoyette {
506 1.1 pgoyette uint32_t *p = parg;
507 1.1 pgoyette
508 1.1 pgoyette if (id == nfscl_accesscache_flush_done_id)
509 1.1 pgoyette dtrace_nfscl_accesscache_flush_done_probe = NULL;
510 1.1 pgoyette else if (id == nfscl_accesscache_get_hit_id)
511 1.1 pgoyette dtrace_nfscl_accesscache_get_hit_probe = NULL;
512 1.1 pgoyette else if (id == nfscl_accesscache_get_miss_id)
513 1.1 pgoyette dtrace_nfscl_accesscache_get_miss_probe = NULL;
514 1.1 pgoyette else if (id == nfscl_accesscache_load_done_id)
515 1.1 pgoyette dtrace_nfscl_accesscache_load_done_probe = NULL;
516 1.1 pgoyette else if (id == nfscl_attrcache_flush_done_id)
517 1.1 pgoyette dtrace_nfscl_attrcache_flush_done_probe = NULL;
518 1.1 pgoyette else if (id == nfscl_attrcache_get_hit_id)
519 1.1 pgoyette dtrace_nfscl_attrcache_get_hit_probe = NULL;
520 1.1 pgoyette else if (id == nfscl_attrcache_get_miss_id)
521 1.1 pgoyette dtrace_nfscl_attrcache_get_miss_probe = NULL;
522 1.1 pgoyette else if (id == nfscl_attrcache_load_done_id)
523 1.1 pgoyette dtrace_nfscl_attrcache_load_done_probe = NULL;
524 1.1 pgoyette else
525 1.1 pgoyette *p = 0;
526 1.1 pgoyette }
527 1.1 pgoyette
528 1.1 pgoyette static void
529 1.1 pgoyette dtnfsclient_load(void *dummy)
530 1.1 pgoyette {
531 1.1 pgoyette
532 1.1 pgoyette if (dtrace_register("nfscl", &dtnfsclient_attr,
533 1.1 pgoyette DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL,
534 1.1 pgoyette &dtnfsclient_id) != 0)
535 1.1 pgoyette return;
536 1.1 pgoyette
537 1.1 pgoyette dtrace_nfscl_nfs234_start_probe =
538 1.1 pgoyette (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe;
539 1.1 pgoyette dtrace_nfscl_nfs234_done_probe =
540 1.1 pgoyette (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe;
541 1.1 pgoyette }
542 1.1 pgoyette
543 1.1 pgoyette
544 1.1 pgoyette static int
545 1.1 pgoyette dtnfsclient_unload()
546 1.1 pgoyette {
547 1.1 pgoyette
548 1.1 pgoyette dtrace_nfscl_nfs234_start_probe = NULL;
549 1.1 pgoyette dtrace_nfscl_nfs234_done_probe = NULL;
550 1.1 pgoyette
551 1.1 pgoyette return (dtrace_unregister(dtnfsclient_id));
552 1.1 pgoyette }
553 1.1 pgoyette
554 1.1 pgoyette static int
555 1.1 pgoyette dtnfsclient_modevent(module_t mod __unused, int type, void *data __unused)
556 1.1 pgoyette {
557 1.1 pgoyette int error = 0;
558 1.1 pgoyette
559 1.1 pgoyette switch (type) {
560 1.1 pgoyette case MOD_LOAD:
561 1.1 pgoyette break;
562 1.1 pgoyette
563 1.1 pgoyette case MOD_UNLOAD:
564 1.1 pgoyette break;
565 1.1 pgoyette
566 1.1 pgoyette case MOD_SHUTDOWN:
567 1.1 pgoyette break;
568 1.1 pgoyette
569 1.1 pgoyette default:
570 1.1 pgoyette error = EOPNOTSUPP;
571 1.1 pgoyette break;
572 1.1 pgoyette }
573 1.1 pgoyette
574 1.1 pgoyette return (error);
575 1.1 pgoyette }
576 1.1 pgoyette
577 1.1 pgoyette SYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
578 1.1 pgoyette dtnfsclient_load, NULL);
579 1.1 pgoyette SYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
580 1.1 pgoyette dtnfsclient_unload, NULL);
581 1.1 pgoyette
582 1.1 pgoyette DEV_MODULE(dtnfscl, dtnfsclient_modevent, NULL);
583 1.1 pgoyette MODULE_VERSION(dtnfscl, 1);
584 1.1 pgoyette MODULE_DEPEND(dtnfscl, dtrace, 1, 1, 1);
585 1.1 pgoyette MODULE_DEPEND(dtnfscl, opensolaris, 1, 1, 1);
586 1.1 pgoyette MODULE_DEPEND(dtnfscl, nfscl, 1, 1, 1);
587 1.1 pgoyette MODULE_DEPEND(dtnfscl, nfscommon, 1, 1, 1);
588