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[NFS_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 NFS_NPROCS + 1, and
200 * the v2, v3 arrays are simply sparse.
201 */
202 extern uint32_t nfscl_nfs2_start_probes[NFS_NPROCS + 1];
203 extern uint32_t nfscl_nfs2_done_probes[NFS_NPROCS + 1];
204
205 extern uint32_t nfscl_nfs3_start_probes[NFS_NPROCS + 1];
206 extern uint32_t nfscl_nfs3_done_probes[NFS_NPROCS + 1];
207
208 extern uint32_t nfscl_nfs4_start_probes[NFS_NPROCS + 1];
209 extern uint32_t nfscl_nfs4_done_probes[NFS_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 < NFS_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 < NFS_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 < NFS_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 < NFS_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);
Cache object: 27da25c71b32abd8ffc723276910f667
|