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