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