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