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 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 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 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 476 dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg) 477 { 478 } 479 480 static void 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 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 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 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 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