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