]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/fs/nfsclient/nfs_clkdtrace.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 acess 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  * Most probes are generated from the above RPC table, but for access and
181  * attribute caches, we have specific IDs we recognize and handle specially
182  * in various spots.
183  */
184 extern uint32_t nfscl_accesscache_flush_done_id;
185 extern uint32_t nfscl_accesscache_get_hit_id;
186 extern uint32_t nfscl_accesscache_get_miss_id;
187 extern uint32_t nfscl_accesscache_load_done_id;
188
189 extern uint32_t nfscl_attrcache_flush_done_id;
190 extern uint32_t nfscl_attrcache_get_hit_id;
191 extern uint32_t nfscl_attrcache_get_miss_id;
192 extern uint32_t nfscl_attrcache_load_done_id;
193
194 /*
195  * When tracing on a procedure is enabled, the DTrace ID for an RPC event is
196  * stored in one of these two NFS client-allocated arrays; 0 indicates that
197  * the event is not being traced so probes should not be called.
198  *
199  * For simplicity, we allocate both v2, v3 and v4 arrays as NFSV41_NPROCS + 1,
200  * and the v2, v3 arrays are simply sparse.
201  */
202 extern uint32_t                 nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
203 extern uint32_t                 nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
204
205 extern uint32_t                 nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
206 extern uint32_t                 nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
207
208 extern uint32_t                 nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
209 extern uint32_t                 nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
210
211 /*
212  * Look up a DTrace probe ID to see if it's associated with a "done" event --
213  * if so, we will return a fourth argument type of "int".
214  */
215 static int
216 dtnfs234_isdoneprobe(dtrace_id_t id)
217 {
218         int i;
219
220         for (i = 0; i < NFSV41_NPROCS + 1; i++) {
221                 if (dtnfsclient_rpcs[i].nr_v4_id_done == id ||
222                     dtnfsclient_rpcs[i].nr_v3_id_done == id ||
223                     dtnfsclient_rpcs[i].nr_v2_id_done == id)
224                         return (1);
225         }
226         return (0);
227 }
228
229 static void
230 dtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg,
231     dtrace_argdesc_t *desc)
232 {
233         const char *p = NULL;
234
235         if (id == nfscl_accesscache_flush_done_id ||
236             id == nfscl_attrcache_flush_done_id ||
237             id == nfscl_attrcache_get_miss_id) {
238                 switch (desc->dtargd_ndx) {
239                 case 0:
240                         p = "struct vnode *";
241                         break;
242                 default:
243                         desc->dtargd_ndx = DTRACE_ARGNONE;
244                         break;
245                 }
246         } else if (id == nfscl_accesscache_get_hit_id ||
247             id == nfscl_accesscache_get_miss_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                 default:
259                         desc->dtargd_ndx = DTRACE_ARGNONE;
260                         break;
261                 }
262         } else if (id == nfscl_accesscache_load_done_id) {
263                 switch (desc->dtargd_ndx) {
264                 case 0:
265                         p = "struct vnode *";
266                         break;
267                 case 1:
268                         p = "uid_t";
269                         break;
270                 case 2:
271                         p = "uint32_t";
272                         break;
273                 case 3:
274                         p = "int";
275                         break;
276                 default:
277                         desc->dtargd_ndx = DTRACE_ARGNONE;
278                         break;
279                 }
280         } else if (id == nfscl_attrcache_get_hit_id) {
281                 switch (desc->dtargd_ndx) {
282                 case 0:
283                         p = "struct vnode *";
284                         break;
285                 case 1:
286                         p = "struct vattr *";
287                         break;
288                 default:
289                         desc->dtargd_ndx = DTRACE_ARGNONE;
290                         break;
291                 }
292         } else if (id == nfscl_attrcache_load_done_id) {
293                 switch (desc->dtargd_ndx) {
294                 case 0:
295                         p = "struct vnode *";
296                         break;
297                 case 1:
298                         p = "struct vattr *";
299                         break;
300                 case 2:
301                         p = "int";
302                         break;
303                 default:
304                         desc->dtargd_ndx = DTRACE_ARGNONE;
305                         break;
306                 }
307         } else {
308                 switch (desc->dtargd_ndx) {
309                 case 0:
310                         p = "struct vnode *";
311                         break;
312                 case 1:
313                         p = "struct mbuf *";
314                         break;
315                 case 2:
316                         p = "struct ucred *";
317                         break;
318                 case 3:
319                         p = "int";
320                         break;
321                 case 4:
322                         if (dtnfs234_isdoneprobe(id)) {
323                                 p = "int";
324                                 break;
325                         }
326                         /* FALLSTHROUGH */
327                 default:
328                         desc->dtargd_ndx = DTRACE_ARGNONE;
329                         break;
330                 }
331         }
332         if (p != NULL)
333                 strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
334 }
335
336 static void
337 dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
338 {
339         int i;
340
341         if (desc != NULL)
342                 return;
343
344         /*
345          * Register access cache probes.
346          */
347         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
348             dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
349                 nfscl_accesscache_flush_done_id = dtrace_probe_create(
350                     dtnfsclient_id, dtnfsclient_accesscache_str,
351                     dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
352         }
353         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
354             dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
355                 nfscl_accesscache_get_hit_id = dtrace_probe_create(
356                     dtnfsclient_id, dtnfsclient_accesscache_str,
357                     dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
358         }
359         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
360             dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
361                 nfscl_accesscache_get_miss_id = dtrace_probe_create(
362                     dtnfsclient_id, dtnfsclient_accesscache_str,
363                     dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
364         }
365         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
366             dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
367                 nfscl_accesscache_load_done_id = dtrace_probe_create(
368                     dtnfsclient_id, dtnfsclient_accesscache_str,
369                     dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
370         }
371
372         /*
373          * Register attribute cache probes.
374          */
375         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
376             dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
377                 nfscl_attrcache_flush_done_id = dtrace_probe_create(
378                     dtnfsclient_id, dtnfsclient_attrcache_str,
379                     dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
380         }
381         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
382             dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
383                 nfscl_attrcache_get_hit_id = dtrace_probe_create(
384                     dtnfsclient_id, dtnfsclient_attrcache_str,
385                     dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
386         }
387         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
388             dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
389                 nfscl_attrcache_get_miss_id = dtrace_probe_create(
390                     dtnfsclient_id, dtnfsclient_attrcache_str,
391                     dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
392         }
393         if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
394             dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
395                 nfscl_attrcache_load_done_id = dtrace_probe_create(
396                     dtnfsclient_id, dtnfsclient_attrcache_str,
397                     dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
398         }
399
400         /*
401          * Register NFSv2 RPC procedures; note sparseness check for each slot
402          * in the NFSv3, NFSv4 procnum-indexed array.
403          */
404         for (i = 0; i < NFSV41_NPROCS + 1; i++) {
405                 if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
406                     dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
407                     dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
408                     0) {
409                         dtnfsclient_rpcs[i].nr_v2_id_start =
410                             dtrace_probe_create(dtnfsclient_id,
411                             dtnfsclient_nfs2_str,
412                             dtnfsclient_rpcs[i].nr_v2_name,
413                             dtnfsclient_start_str, 0,
414                             &nfscl_nfs2_start_probes[i]);
415                 }
416                 if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
417                     dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
418                     dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) ==
419                     0) {
420                         dtnfsclient_rpcs[i].nr_v2_id_done = 
421                             dtrace_probe_create(dtnfsclient_id,
422                             dtnfsclient_nfs2_str,
423                             dtnfsclient_rpcs[i].nr_v2_name,
424                             dtnfsclient_done_str, 0,
425                             &nfscl_nfs2_done_probes[i]);
426                 }
427         }
428
429         /*
430          * Register NFSv3 RPC procedures; note sparseness check for each slot
431          * in the NFSv4 procnum-indexed array.
432          */
433         for (i = 0; i < NFSV41_NPROCS + 1; i++) {
434                 if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
435                     dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
436                     dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
437                     0) {
438                         dtnfsclient_rpcs[i].nr_v3_id_start =
439                             dtrace_probe_create(dtnfsclient_id,
440                             dtnfsclient_nfs3_str,
441                             dtnfsclient_rpcs[i].nr_v3_name,
442                             dtnfsclient_start_str, 0,
443                             &nfscl_nfs3_start_probes[i]);
444                 }
445                 if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
446                     dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
447                     dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) ==
448                     0) {
449                         dtnfsclient_rpcs[i].nr_v3_id_done = 
450                             dtrace_probe_create(dtnfsclient_id,
451                             dtnfsclient_nfs3_str,
452                             dtnfsclient_rpcs[i].nr_v3_name,
453                             dtnfsclient_done_str, 0,
454                             &nfscl_nfs3_done_probes[i]);
455                 }
456         }
457
458         /*
459          * Register NFSv4 RPC procedures.
460          */
461         for (i = 0; i < NFSV41_NPROCS + 1; i++) {
462                 if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
463                     dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_start_str) ==
464                     0) {
465                         dtnfsclient_rpcs[i].nr_v4_id_start =
466                             dtrace_probe_create(dtnfsclient_id,
467                             dtnfsclient_nfs4_str,
468                             dtnfsclient_rpcs[i].nr_v4_name,
469                             dtnfsclient_start_str, 0,
470                             &nfscl_nfs4_start_probes[i]);
471                 }
472                 if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
473                     dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_done_str) ==
474                     0) {
475                         dtnfsclient_rpcs[i].nr_v4_id_done = 
476                             dtrace_probe_create(dtnfsclient_id,
477                             dtnfsclient_nfs4_str,
478                             dtnfsclient_rpcs[i].nr_v4_name,
479                             dtnfsclient_done_str, 0,
480                             &nfscl_nfs4_done_probes[i]);
481                 }
482         }
483 }
484
485 static void
486 dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg)
487 {
488 }
489
490 static void
491 dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg)
492 {
493         uint32_t *p = parg;
494         void *f = dtrace_probe;
495
496         if (id == nfscl_accesscache_flush_done_id)
497                 dtrace_nfscl_accesscache_flush_done_probe = f;
498         else if (id == nfscl_accesscache_get_hit_id)
499                 dtrace_nfscl_accesscache_get_hit_probe = f;
500         else if (id == nfscl_accesscache_get_miss_id)
501                 dtrace_nfscl_accesscache_get_miss_probe = f;
502         else if (id == nfscl_accesscache_load_done_id)
503                 dtrace_nfscl_accesscache_load_done_probe = f;
504         else if (id == nfscl_attrcache_flush_done_id)
505                 dtrace_nfscl_attrcache_flush_done_probe = f;
506         else if (id == nfscl_attrcache_get_hit_id)
507                 dtrace_nfscl_attrcache_get_hit_probe = f;
508         else if (id == nfscl_attrcache_get_miss_id)
509                 dtrace_nfscl_attrcache_get_miss_probe = f;
510         else if (id == nfscl_attrcache_load_done_id)
511                 dtrace_nfscl_attrcache_load_done_probe = f;
512         else
513                 *p = id;
514 }
515
516 static void
517 dtnfsclient_disable(void *arg, dtrace_id_t id, void *parg)
518 {
519         uint32_t *p = parg;
520
521         if (id == nfscl_accesscache_flush_done_id)
522                 dtrace_nfscl_accesscache_flush_done_probe = NULL;
523         else if (id == nfscl_accesscache_get_hit_id)
524                 dtrace_nfscl_accesscache_get_hit_probe = NULL;
525         else if (id == nfscl_accesscache_get_miss_id)
526                 dtrace_nfscl_accesscache_get_miss_probe = NULL;
527         else if (id == nfscl_accesscache_load_done_id)
528                 dtrace_nfscl_accesscache_load_done_probe = NULL;
529         else if (id == nfscl_attrcache_flush_done_id)
530                 dtrace_nfscl_attrcache_flush_done_probe = NULL;
531         else if (id == nfscl_attrcache_get_hit_id)
532                 dtrace_nfscl_attrcache_get_hit_probe = NULL;
533         else if (id == nfscl_attrcache_get_miss_id)
534                 dtrace_nfscl_attrcache_get_miss_probe = NULL;
535         else if (id == nfscl_attrcache_load_done_id)
536                 dtrace_nfscl_attrcache_load_done_probe = NULL;
537         else
538                 *p = 0;
539 }
540
541 static void
542 dtnfsclient_load(void *dummy)
543 {
544
545         if (dtrace_register("nfscl", &dtnfsclient_attr,
546             DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL,
547             &dtnfsclient_id) != 0)
548                 return;
549
550         dtrace_nfscl_nfs234_start_probe =
551             (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe;
552         dtrace_nfscl_nfs234_done_probe =
553             (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe;
554 }
555
556
557 static int
558 dtnfsclient_unload()
559 {
560
561         dtrace_nfscl_nfs234_start_probe = NULL;
562         dtrace_nfscl_nfs234_done_probe = NULL;
563
564         return (dtrace_unregister(dtnfsclient_id));
565 }
566
567 static int
568 dtnfsclient_modevent(module_t mod __unused, int type, void *data __unused)
569 {
570         int error = 0;
571
572         switch (type) {
573         case MOD_LOAD:
574                 break;
575
576         case MOD_UNLOAD:
577                 break;
578
579         case MOD_SHUTDOWN:
580                 break;
581
582         default:
583                 error = EOPNOTSUPP;
584                 break;
585         }
586
587         return (error);
588 }
589
590 SYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
591     dtnfsclient_load, NULL);
592 SYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
593     dtnfsclient_unload, NULL);
594
595 DEV_MODULE(dtnfscl, dtnfsclient_modevent, NULL);
596 MODULE_VERSION(dtnfscl, 1);
597 MODULE_DEPEND(dtnfscl, dtrace, 1, 1, 1);
598 MODULE_DEPEND(dtnfscl, opensolaris, 1, 1, 1);
599 MODULE_DEPEND(dtnfscl, nfscl, 1, 1, 1);
600 MODULE_DEPEND(dtnfscl, nfscommon, 1, 1, 1);