xref: /freebsd/sys/fs/nfsclient/nfs_clkdtrace.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
18f0e65c9SRick Macklem /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d63027b6SPedro F. Giffuni  *
48f0e65c9SRick Macklem  * Copyright (c) 2009 Robert N. M. Watson
58f0e65c9SRick Macklem  * All rights reserved.
68f0e65c9SRick Macklem  *
78f0e65c9SRick Macklem  * This software was developed at the University of Cambridge Computer
88f0e65c9SRick Macklem  * Laboratory with support from a grant from Google, Inc.
98f0e65c9SRick Macklem  *
108f0e65c9SRick Macklem  * Redistribution and use in source and binary forms, with or without
118f0e65c9SRick Macklem  * modification, are permitted provided that the following conditions
128f0e65c9SRick Macklem  * are met:
138f0e65c9SRick Macklem  * 1. Redistributions of source code must retain the above copyright
148f0e65c9SRick Macklem  *    notice, this list of conditions and the following disclaimer.
158f0e65c9SRick Macklem  * 2. Redistributions in binary form must reproduce the above copyright
168f0e65c9SRick Macklem  *    notice, this list of conditions and the following disclaimer in the
178f0e65c9SRick Macklem  *    documentation and/or other materials provided with the distribution.
188f0e65c9SRick Macklem  *
198f0e65c9SRick Macklem  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
208f0e65c9SRick Macklem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
218f0e65c9SRick Macklem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
228f0e65c9SRick Macklem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
238f0e65c9SRick Macklem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
248f0e65c9SRick Macklem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
258f0e65c9SRick Macklem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
268f0e65c9SRick Macklem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
278f0e65c9SRick Macklem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
288f0e65c9SRick Macklem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
298f0e65c9SRick Macklem  * SUCH DAMAGE.
308f0e65c9SRick Macklem  */
318f0e65c9SRick Macklem 
328f0e65c9SRick Macklem #include <sys/param.h>
338f0e65c9SRick Macklem #include <sys/systm.h>
348f0e65c9SRick Macklem #include <sys/conf.h>
358f0e65c9SRick Macklem #include <sys/kernel.h>
368f0e65c9SRick Macklem #include <sys/malloc.h>
378f0e65c9SRick Macklem #include <sys/module.h>
388f0e65c9SRick Macklem 
398f0e65c9SRick Macklem #include <sys/dtrace.h>
408f0e65c9SRick Macklem #include <sys/dtrace_bsd.h>
418f0e65c9SRick Macklem 
428f0e65c9SRick Macklem #include <fs/nfs/nfsproto.h>
438f0e65c9SRick Macklem 
448f0e65c9SRick Macklem #include <fs/nfsclient/nfs_kdtrace.h>
458f0e65c9SRick Macklem 
468f0e65c9SRick Macklem /*
478f0e65c9SRick Macklem  * dtnfscl is a DTrace provider that tracks the intent to perform RPCs
48a96c9b30SPedro F. Giffuni  * in the NFS client, as well as access to and maintenance of the access and
498f0e65c9SRick Macklem  * attribute caches.  This is not quite the same as RPCs, because NFS may
508f0e65c9SRick Macklem  * issue multiple RPC transactions in the event that authentication fails,
518f0e65c9SRick Macklem  * there's a jukebox error, or none at all if the access or attribute cache
528f0e65c9SRick Macklem  * hits.  However, it cleanly represents the logical layer between RPC
538f0e65c9SRick Macklem  * transmission and vnode/vfs operations, providing access to state linking
548f0e65c9SRick Macklem  * the two.
558f0e65c9SRick Macklem  */
568f0e65c9SRick Macklem 
578f0e65c9SRick Macklem static int	dtnfsclient_unload(void);
588f0e65c9SRick Macklem static void	dtnfsclient_getargdesc(void *, dtrace_id_t, void *,
598f0e65c9SRick Macklem 		    dtrace_argdesc_t *);
608f0e65c9SRick Macklem static void	dtnfsclient_provide(void *, dtrace_probedesc_t *);
618f0e65c9SRick Macklem static void	dtnfsclient_destroy(void *, dtrace_id_t, void *);
628f0e65c9SRick Macklem static void	dtnfsclient_enable(void *, dtrace_id_t, void *);
638f0e65c9SRick Macklem static void	dtnfsclient_disable(void *, dtrace_id_t, void *);
648f0e65c9SRick Macklem static void	dtnfsclient_load(void *);
658f0e65c9SRick Macklem 
668f0e65c9SRick Macklem static dtrace_pattr_t dtnfsclient_attr = {
678f0e65c9SRick Macklem { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
688f0e65c9SRick Macklem { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
698f0e65c9SRick Macklem { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
708f0e65c9SRick Macklem { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
718f0e65c9SRick Macklem { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
728f0e65c9SRick Macklem };
738f0e65c9SRick Macklem 
748f0e65c9SRick Macklem /*
758f0e65c9SRick Macklem  * Description of NFSv4, NFSv3 and (optional) NFSv2 probes for a procedure.
768f0e65c9SRick Macklem  */
778f0e65c9SRick Macklem struct dtnfsclient_rpc {
788f0e65c9SRick Macklem 	char		*nr_v4_name;
798f0e65c9SRick Macklem 	char		*nr_v3_name;	/* Or NULL if none. */
808f0e65c9SRick Macklem 	char		*nr_v2_name;	/* Or NULL if none. */
818f0e65c9SRick Macklem 
828f0e65c9SRick Macklem 	/*
838f0e65c9SRick Macklem 	 * IDs for the start and done cases, for NFSv2, NFSv3 and NFSv4.
848f0e65c9SRick Macklem 	 */
858f0e65c9SRick Macklem 	uint32_t	 nr_v2_id_start, nr_v2_id_done;
868f0e65c9SRick Macklem 	uint32_t	 nr_v3_id_start, nr_v3_id_done;
878f0e65c9SRick Macklem 	uint32_t	 nr_v4_id_start, nr_v4_id_done;
888f0e65c9SRick Macklem };
898f0e65c9SRick Macklem 
908f0e65c9SRick Macklem /*
918f0e65c9SRick Macklem  * This table is indexed by NFSv3 procedure number, but also used for NFSv2
928f0e65c9SRick Macklem  * procedure names and NFSv4 operations.
938f0e65c9SRick Macklem  */
941f60bfd8SRick Macklem static struct dtnfsclient_rpc	dtnfsclient_rpcs[NFSV41_NPROCS + 1] = {
958f0e65c9SRick Macklem 	{ "null", "null", "null" },
968f0e65c9SRick Macklem 	{ "getattr", "getattr", "getattr" },
978f0e65c9SRick Macklem 	{ "setattr", "setattr", "setattr" },
988f0e65c9SRick Macklem 	{ "lookup", "lookup", "lookup" },
998f0e65c9SRick Macklem 	{ "access", "access", "noop" },
1008f0e65c9SRick Macklem 	{ "readlink", "readlink", "readlink" },
1018f0e65c9SRick Macklem 	{ "read", "read", "read" },
1028f0e65c9SRick Macklem 	{ "write", "write", "write" },
1038f0e65c9SRick Macklem 	{ "create", "create", "create" },
1048f0e65c9SRick Macklem 	{ "mkdir", "mkdir", "mkdir" },
1058f0e65c9SRick Macklem 	{ "symlink", "symlink", "symlink" },
1068f0e65c9SRick Macklem 	{ "mknod", "mknod" },
1078f0e65c9SRick Macklem 	{ "remove", "remove", "remove" },
1088f0e65c9SRick Macklem 	{ "rmdir", "rmdir", "rmdir" },
1098f0e65c9SRick Macklem 	{ "rename", "rename", "rename" },
1108f0e65c9SRick Macklem 	{ "link", "link", "link" },
1118f0e65c9SRick Macklem 	{ "readdir", "readdir", "readdir" },
1128f0e65c9SRick Macklem 	{ "readdirplus", "readdirplus" },
1138f0e65c9SRick Macklem 	{ "fsstat", "fsstat", "statfs" },
1148f0e65c9SRick Macklem 	{ "fsinfo", "fsinfo" },
1158f0e65c9SRick Macklem 	{ "pathconf", "pathconf" },
1168f0e65c9SRick Macklem 	{ "commit", "commit" },
1178f0e65c9SRick Macklem 	{ "lookupp" },
1188f0e65c9SRick Macklem 	{ "setclientid" },
1198f0e65c9SRick Macklem 	{ "setclientidcfrm" },
1208f0e65c9SRick Macklem 	{ "lock" },
1218f0e65c9SRick Macklem 	{ "locku" },
1228f0e65c9SRick Macklem 	{ "open" },
1238f0e65c9SRick Macklem 	{ "close" },
1248f0e65c9SRick Macklem 	{ "openconfirm" },
1258f0e65c9SRick Macklem 	{ "lockt" },
1268f0e65c9SRick Macklem 	{ "opendowngrade" },
1278f0e65c9SRick Macklem 	{ "renew" },
1288f0e65c9SRick Macklem 	{ "putrootfh" },
1298f0e65c9SRick Macklem 	{ "releaselckown" },
1308f0e65c9SRick Macklem 	{ "delegreturn" },
1318f0e65c9SRick Macklem 	{ "retdelegremove" },
1328f0e65c9SRick Macklem 	{ "retdelegrename1" },
1338f0e65c9SRick Macklem 	{ "retdelegrename2" },
1348f0e65c9SRick Macklem 	{ "getacl" },
1358f0e65c9SRick Macklem 	{ "setacl" },
1368f0e65c9SRick Macklem 	{ "noop", "noop", "noop" }
1378f0e65c9SRick Macklem };
1388f0e65c9SRick Macklem 
1398f0e65c9SRick Macklem /*
1408f0e65c9SRick Macklem  * Module name strings.
1418f0e65c9SRick Macklem  */
1428f0e65c9SRick Macklem static char	*dtnfsclient_accesscache_str = "accesscache";
1438f0e65c9SRick Macklem static char	*dtnfsclient_attrcache_str = "attrcache";
1448f0e65c9SRick Macklem static char	*dtnfsclient_nfs2_str = "nfs2";
1458f0e65c9SRick Macklem static char	*dtnfsclient_nfs3_str = "nfs3";
1468f0e65c9SRick Macklem static char	*dtnfsclient_nfs4_str = "nfs4";
1478f0e65c9SRick Macklem 
1488f0e65c9SRick Macklem /*
1498f0e65c9SRick Macklem  * Function name strings.
1508f0e65c9SRick Macklem  */
1518f0e65c9SRick Macklem static char	*dtnfsclient_flush_str = "flush";
1528f0e65c9SRick Macklem static char	*dtnfsclient_load_str = "load";
1538f0e65c9SRick Macklem static char	*dtnfsclient_get_str = "get";
1548f0e65c9SRick Macklem 
1558f0e65c9SRick Macklem /*
1568f0e65c9SRick Macklem  * Name strings.
1578f0e65c9SRick Macklem  */
1588f0e65c9SRick Macklem static char	*dtnfsclient_done_str = "done";
1598f0e65c9SRick Macklem static char	*dtnfsclient_hit_str = "hit";
1608f0e65c9SRick Macklem static char	*dtnfsclient_miss_str = "miss";
1618f0e65c9SRick Macklem static char	*dtnfsclient_start_str = "start";
1628f0e65c9SRick Macklem 
1638f0e65c9SRick Macklem static dtrace_pops_t dtnfsclient_pops = {
16447f11baaSMark Johnston 	.dtps_provide =		dtnfsclient_provide,
16547f11baaSMark Johnston 	.dtps_provide_module =	NULL,
16647f11baaSMark Johnston 	.dtps_enable =		dtnfsclient_enable,
16747f11baaSMark Johnston 	.dtps_disable =		dtnfsclient_disable,
16847f11baaSMark Johnston 	.dtps_suspend =		NULL,
16947f11baaSMark Johnston 	.dtps_resume =		NULL,
17047f11baaSMark Johnston 	.dtps_getargdesc =	dtnfsclient_getargdesc,
17147f11baaSMark Johnston 	.dtps_getargval =	NULL,
17247f11baaSMark Johnston 	.dtps_usermode =	NULL,
17347f11baaSMark Johnston 	.dtps_destroy =		dtnfsclient_destroy
1748f0e65c9SRick Macklem };
1758f0e65c9SRick Macklem 
1768f0e65c9SRick Macklem static dtrace_provider_id_t	dtnfsclient_id;
1778f0e65c9SRick Macklem 
1788f0e65c9SRick Macklem /*
1798f0e65c9SRick Macklem  * When tracing on a procedure is enabled, the DTrace ID for an RPC event is
1808f0e65c9SRick Macklem  * stored in one of these two NFS client-allocated arrays; 0 indicates that
1818f0e65c9SRick Macklem  * the event is not being traced so probes should not be called.
1828f0e65c9SRick Macklem  *
1831f60bfd8SRick Macklem  * For simplicity, we allocate both v2, v3 and v4 arrays as NFSV41_NPROCS + 1,
1841f60bfd8SRick Macklem  * and the v2, v3 arrays are simply sparse.
1858f0e65c9SRick Macklem  */
1861f60bfd8SRick Macklem extern uint32_t			nfscl_nfs2_start_probes[NFSV41_NPROCS + 1];
1871f60bfd8SRick Macklem extern uint32_t			nfscl_nfs2_done_probes[NFSV41_NPROCS + 1];
1888f0e65c9SRick Macklem 
1891f60bfd8SRick Macklem extern uint32_t			nfscl_nfs3_start_probes[NFSV41_NPROCS + 1];
1901f60bfd8SRick Macklem extern uint32_t			nfscl_nfs3_done_probes[NFSV41_NPROCS + 1];
1918f0e65c9SRick Macklem 
1921f60bfd8SRick Macklem extern uint32_t			nfscl_nfs4_start_probes[NFSV41_NPROCS + 1];
1931f60bfd8SRick Macklem extern uint32_t			nfscl_nfs4_done_probes[NFSV41_NPROCS + 1];
1948f0e65c9SRick Macklem 
1958f0e65c9SRick Macklem /*
1968f0e65c9SRick Macklem  * Look up a DTrace probe ID to see if it's associated with a "done" event --
1978f0e65c9SRick Macklem  * if so, we will return a fourth argument type of "int".
1988f0e65c9SRick Macklem  */
1998f0e65c9SRick Macklem static int
dtnfs234_isdoneprobe(dtrace_id_t id)2008f0e65c9SRick Macklem dtnfs234_isdoneprobe(dtrace_id_t id)
2018f0e65c9SRick Macklem {
2028f0e65c9SRick Macklem 	int i;
2038f0e65c9SRick Macklem 
2041f60bfd8SRick Macklem 	for (i = 0; i < NFSV41_NPROCS + 1; i++) {
2058f0e65c9SRick Macklem 		if (dtnfsclient_rpcs[i].nr_v4_id_done == id ||
2068f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v3_id_done == id ||
2078f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v2_id_done == id)
2088f0e65c9SRick Macklem 			return (1);
2098f0e65c9SRick Macklem 	}
2108f0e65c9SRick Macklem 	return (0);
2118f0e65c9SRick Macklem }
2128f0e65c9SRick Macklem 
2138f0e65c9SRick Macklem static void
dtnfsclient_getargdesc(void * arg,dtrace_id_t id,void * parg,dtrace_argdesc_t * desc)2148f0e65c9SRick Macklem dtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg,
2158f0e65c9SRick Macklem     dtrace_argdesc_t *desc)
2168f0e65c9SRick Macklem {
2178f0e65c9SRick Macklem 	const char *p = NULL;
2188f0e65c9SRick Macklem 
2198f0e65c9SRick Macklem 	if (id == nfscl_accesscache_flush_done_id ||
2208f0e65c9SRick Macklem 	    id == nfscl_attrcache_flush_done_id ||
2218f0e65c9SRick Macklem 	    id == nfscl_attrcache_get_miss_id) {
2228f0e65c9SRick Macklem 		switch (desc->dtargd_ndx) {
2238f0e65c9SRick Macklem 		case 0:
2248f0e65c9SRick Macklem 			p = "struct vnode *";
2258f0e65c9SRick Macklem 			break;
2268f0e65c9SRick Macklem 		default:
2278f0e65c9SRick Macklem 			desc->dtargd_ndx = DTRACE_ARGNONE;
2288f0e65c9SRick Macklem 			break;
2298f0e65c9SRick Macklem 		}
2308f0e65c9SRick Macklem 	} else if (id == nfscl_accesscache_get_hit_id ||
2318f0e65c9SRick Macklem 	    id == nfscl_accesscache_get_miss_id) {
2328f0e65c9SRick Macklem 		switch (desc->dtargd_ndx) {
2338f0e65c9SRick Macklem 		case 0:
2348f0e65c9SRick Macklem 			p = "struct vnode *";
2358f0e65c9SRick Macklem 			break;
2368f0e65c9SRick Macklem 		case 1:
2378f0e65c9SRick Macklem 			p = "uid_t";
2388f0e65c9SRick Macklem 			break;
2398f0e65c9SRick Macklem 		case 2:
2408f0e65c9SRick Macklem 			p = "uint32_t";
2418f0e65c9SRick Macklem 			break;
2428f0e65c9SRick Macklem 		default:
2438f0e65c9SRick Macklem 			desc->dtargd_ndx = DTRACE_ARGNONE;
2448f0e65c9SRick Macklem 			break;
2458f0e65c9SRick Macklem 		}
2468f0e65c9SRick Macklem 	} else if (id == nfscl_accesscache_load_done_id) {
2478f0e65c9SRick Macklem 		switch (desc->dtargd_ndx) {
2488f0e65c9SRick Macklem 		case 0:
2498f0e65c9SRick Macklem 			p = "struct vnode *";
2508f0e65c9SRick Macklem 			break;
2518f0e65c9SRick Macklem 		case 1:
2528f0e65c9SRick Macklem 			p = "uid_t";
2538f0e65c9SRick Macklem 			break;
2548f0e65c9SRick Macklem 		case 2:
2558f0e65c9SRick Macklem 			p = "uint32_t";
2568f0e65c9SRick Macklem 			break;
2578f0e65c9SRick Macklem 		case 3:
2588f0e65c9SRick Macklem 			p = "int";
2598f0e65c9SRick Macklem 			break;
2608f0e65c9SRick Macklem 		default:
2618f0e65c9SRick Macklem 			desc->dtargd_ndx = DTRACE_ARGNONE;
2628f0e65c9SRick Macklem 			break;
2638f0e65c9SRick Macklem 		}
2648f0e65c9SRick Macklem 	} else if (id == nfscl_attrcache_get_hit_id) {
2658f0e65c9SRick Macklem 		switch (desc->dtargd_ndx) {
2668f0e65c9SRick Macklem 		case 0:
2678f0e65c9SRick Macklem 			p = "struct vnode *";
2688f0e65c9SRick Macklem 			break;
2698f0e65c9SRick Macklem 		case 1:
2708f0e65c9SRick Macklem 			p = "struct vattr *";
2718f0e65c9SRick Macklem 			break;
2728f0e65c9SRick Macklem 		default:
2738f0e65c9SRick Macklem 			desc->dtargd_ndx = DTRACE_ARGNONE;
2748f0e65c9SRick Macklem 			break;
2758f0e65c9SRick Macklem 		}
2768f0e65c9SRick Macklem 	} else if (id == nfscl_attrcache_load_done_id) {
2778f0e65c9SRick Macklem 		switch (desc->dtargd_ndx) {
2788f0e65c9SRick Macklem 		case 0:
2798f0e65c9SRick Macklem 			p = "struct vnode *";
2808f0e65c9SRick Macklem 			break;
2818f0e65c9SRick Macklem 		case 1:
2828f0e65c9SRick Macklem 			p = "struct vattr *";
2838f0e65c9SRick Macklem 			break;
2848f0e65c9SRick Macklem 		case 2:
2858f0e65c9SRick Macklem 			p = "int";
2868f0e65c9SRick Macklem 			break;
2878f0e65c9SRick Macklem 		default:
2888f0e65c9SRick Macklem 			desc->dtargd_ndx = DTRACE_ARGNONE;
2898f0e65c9SRick Macklem 			break;
2908f0e65c9SRick Macklem 		}
2918f0e65c9SRick Macklem 	} else {
2928f0e65c9SRick Macklem 		switch (desc->dtargd_ndx) {
2938f0e65c9SRick Macklem 		case 0:
2948f0e65c9SRick Macklem 			p = "struct vnode *";
2958f0e65c9SRick Macklem 			break;
2968f0e65c9SRick Macklem 		case 1:
2978f0e65c9SRick Macklem 			p = "struct mbuf *";
2988f0e65c9SRick Macklem 			break;
2998f0e65c9SRick Macklem 		case 2:
3008f0e65c9SRick Macklem 			p = "struct ucred *";
3018f0e65c9SRick Macklem 			break;
3028f0e65c9SRick Macklem 		case 3:
3038f0e65c9SRick Macklem 			p = "int";
3048f0e65c9SRick Macklem 			break;
3058f0e65c9SRick Macklem 		case 4:
3068f0e65c9SRick Macklem 			if (dtnfs234_isdoneprobe(id)) {
3078f0e65c9SRick Macklem 				p = "int";
3088f0e65c9SRick Macklem 				break;
3098f0e65c9SRick Macklem 			}
3108f0e65c9SRick Macklem 			/* FALLSTHROUGH */
3118f0e65c9SRick Macklem 		default:
3128f0e65c9SRick Macklem 			desc->dtargd_ndx = DTRACE_ARGNONE;
3138f0e65c9SRick Macklem 			break;
3148f0e65c9SRick Macklem 		}
3158f0e65c9SRick Macklem 	}
3168f0e65c9SRick Macklem 	if (p != NULL)
3178f0e65c9SRick Macklem 		strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
3188f0e65c9SRick Macklem }
3198f0e65c9SRick Macklem 
3208f0e65c9SRick Macklem static void
dtnfsclient_provide(void * arg,dtrace_probedesc_t * desc)3218f0e65c9SRick Macklem dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
3228f0e65c9SRick Macklem {
3238f0e65c9SRick Macklem 	int i;
3248f0e65c9SRick Macklem 
3258f0e65c9SRick Macklem 	if (desc != NULL)
3268f0e65c9SRick Macklem 		return;
3278f0e65c9SRick Macklem 
3288f0e65c9SRick Macklem 	/*
3298f0e65c9SRick Macklem 	 * Register access cache probes.
3308f0e65c9SRick Macklem 	 */
3318f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
3328f0e65c9SRick Macklem 	    dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
3338f0e65c9SRick Macklem 		nfscl_accesscache_flush_done_id = dtrace_probe_create(
3348f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_accesscache_str,
3358f0e65c9SRick Macklem 		    dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
3368f0e65c9SRick Macklem 	}
3378f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
3388f0e65c9SRick Macklem 	    dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
3398f0e65c9SRick Macklem 		nfscl_accesscache_get_hit_id = dtrace_probe_create(
3408f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_accesscache_str,
3418f0e65c9SRick Macklem 		    dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
3428f0e65c9SRick Macklem 	}
3438f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
3448f0e65c9SRick Macklem 	    dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
3458f0e65c9SRick Macklem 		nfscl_accesscache_get_miss_id = dtrace_probe_create(
3468f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_accesscache_str,
3478f0e65c9SRick Macklem 		    dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
3488f0e65c9SRick Macklem 	}
3498f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
3508f0e65c9SRick Macklem 	    dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
3518f0e65c9SRick Macklem 		nfscl_accesscache_load_done_id = dtrace_probe_create(
3528f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_accesscache_str,
3538f0e65c9SRick Macklem 		    dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
3548f0e65c9SRick Macklem 	}
3558f0e65c9SRick Macklem 
3568f0e65c9SRick Macklem 	/*
3578f0e65c9SRick Macklem 	 * Register attribute cache probes.
3588f0e65c9SRick Macklem 	 */
3598f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
3608f0e65c9SRick Macklem 	    dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
3618f0e65c9SRick Macklem 		nfscl_attrcache_flush_done_id = dtrace_probe_create(
3628f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_attrcache_str,
3638f0e65c9SRick Macklem 		    dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
3648f0e65c9SRick Macklem 	}
3658f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
3668f0e65c9SRick Macklem 	    dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
3678f0e65c9SRick Macklem 		nfscl_attrcache_get_hit_id = dtrace_probe_create(
3688f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_attrcache_str,
3698f0e65c9SRick Macklem 		    dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
3708f0e65c9SRick Macklem 	}
3718f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
3728f0e65c9SRick Macklem 	    dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
3738f0e65c9SRick Macklem 		nfscl_attrcache_get_miss_id = dtrace_probe_create(
3748f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_attrcache_str,
3758f0e65c9SRick Macklem 		    dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
3768f0e65c9SRick Macklem 	}
3778f0e65c9SRick Macklem 	if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
3788f0e65c9SRick Macklem 	    dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
3798f0e65c9SRick Macklem 		nfscl_attrcache_load_done_id = dtrace_probe_create(
3808f0e65c9SRick Macklem 		    dtnfsclient_id, dtnfsclient_attrcache_str,
3818f0e65c9SRick Macklem 		    dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
3828f0e65c9SRick Macklem 	}
3838f0e65c9SRick Macklem 
3848f0e65c9SRick Macklem 	/*
3858f0e65c9SRick Macklem 	 * Register NFSv2 RPC procedures; note sparseness check for each slot
3868f0e65c9SRick Macklem 	 * in the NFSv3, NFSv4 procnum-indexed array.
3878f0e65c9SRick Macklem 	 */
3881f60bfd8SRick Macklem 	for (i = 0; i < NFSV41_NPROCS + 1; i++) {
3898f0e65c9SRick Macklem 		if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
3908f0e65c9SRick Macklem 		    dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
3918f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
3928f0e65c9SRick Macklem 		    0) {
3938f0e65c9SRick Macklem 			dtnfsclient_rpcs[i].nr_v2_id_start =
3948f0e65c9SRick Macklem 			    dtrace_probe_create(dtnfsclient_id,
3958f0e65c9SRick Macklem 			    dtnfsclient_nfs2_str,
3968f0e65c9SRick Macklem 			    dtnfsclient_rpcs[i].nr_v2_name,
3978f0e65c9SRick Macklem 			    dtnfsclient_start_str, 0,
3988f0e65c9SRick Macklem 			    &nfscl_nfs2_start_probes[i]);
3998f0e65c9SRick Macklem 		}
4008f0e65c9SRick Macklem 		if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
4018f0e65c9SRick Macklem 		    dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
4028f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) ==
4038f0e65c9SRick Macklem 		    0) {
4048f0e65c9SRick Macklem 			dtnfsclient_rpcs[i].nr_v2_id_done =
4058f0e65c9SRick Macklem 			    dtrace_probe_create(dtnfsclient_id,
4068f0e65c9SRick Macklem 			    dtnfsclient_nfs2_str,
4078f0e65c9SRick Macklem 			    dtnfsclient_rpcs[i].nr_v2_name,
4088f0e65c9SRick Macklem 			    dtnfsclient_done_str, 0,
4098f0e65c9SRick Macklem 			    &nfscl_nfs2_done_probes[i]);
4108f0e65c9SRick Macklem 		}
4118f0e65c9SRick Macklem 	}
4128f0e65c9SRick Macklem 
4138f0e65c9SRick Macklem 	/*
4148f0e65c9SRick Macklem 	 * Register NFSv3 RPC procedures; note sparseness check for each slot
4158f0e65c9SRick Macklem 	 * in the NFSv4 procnum-indexed array.
4168f0e65c9SRick Macklem 	 */
4171f60bfd8SRick Macklem 	for (i = 0; i < NFSV41_NPROCS + 1; i++) {
4188f0e65c9SRick Macklem 		if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
4198f0e65c9SRick Macklem 		    dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
4208f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
4218f0e65c9SRick Macklem 		    0) {
4228f0e65c9SRick Macklem 			dtnfsclient_rpcs[i].nr_v3_id_start =
4238f0e65c9SRick Macklem 			    dtrace_probe_create(dtnfsclient_id,
4248f0e65c9SRick Macklem 			    dtnfsclient_nfs3_str,
4258f0e65c9SRick Macklem 			    dtnfsclient_rpcs[i].nr_v3_name,
4268f0e65c9SRick Macklem 			    dtnfsclient_start_str, 0,
4278f0e65c9SRick Macklem 			    &nfscl_nfs3_start_probes[i]);
4288f0e65c9SRick Macklem 		}
4298f0e65c9SRick Macklem 		if (dtnfsclient_rpcs[i].nr_v3_name != NULL &&
4308f0e65c9SRick Macklem 		    dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
4318f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) ==
4328f0e65c9SRick Macklem 		    0) {
4338f0e65c9SRick Macklem 			dtnfsclient_rpcs[i].nr_v3_id_done =
4348f0e65c9SRick Macklem 			    dtrace_probe_create(dtnfsclient_id,
4358f0e65c9SRick Macklem 			    dtnfsclient_nfs3_str,
4368f0e65c9SRick Macklem 			    dtnfsclient_rpcs[i].nr_v3_name,
4378f0e65c9SRick Macklem 			    dtnfsclient_done_str, 0,
4388f0e65c9SRick Macklem 			    &nfscl_nfs3_done_probes[i]);
4398f0e65c9SRick Macklem 		}
4408f0e65c9SRick Macklem 	}
4418f0e65c9SRick Macklem 
4428f0e65c9SRick Macklem 	/*
4438f0e65c9SRick Macklem 	 * Register NFSv4 RPC procedures.
4448f0e65c9SRick Macklem 	 */
4451f60bfd8SRick Macklem 	for (i = 0; i < NFSV41_NPROCS + 1; i++) {
4468f0e65c9SRick Macklem 		if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
4478f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_start_str) ==
4488f0e65c9SRick Macklem 		    0) {
4498f0e65c9SRick Macklem 			dtnfsclient_rpcs[i].nr_v4_id_start =
4508f0e65c9SRick Macklem 			    dtrace_probe_create(dtnfsclient_id,
4518f0e65c9SRick Macklem 			    dtnfsclient_nfs4_str,
4528f0e65c9SRick Macklem 			    dtnfsclient_rpcs[i].nr_v4_name,
4538f0e65c9SRick Macklem 			    dtnfsclient_start_str, 0,
4548f0e65c9SRick Macklem 			    &nfscl_nfs4_start_probes[i]);
4558f0e65c9SRick Macklem 		}
4568f0e65c9SRick Macklem 		if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str,
4578f0e65c9SRick Macklem 		    dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_done_str) ==
4588f0e65c9SRick Macklem 		    0) {
4598f0e65c9SRick Macklem 			dtnfsclient_rpcs[i].nr_v4_id_done =
4608f0e65c9SRick Macklem 			    dtrace_probe_create(dtnfsclient_id,
4618f0e65c9SRick Macklem 			    dtnfsclient_nfs4_str,
4628f0e65c9SRick Macklem 			    dtnfsclient_rpcs[i].nr_v4_name,
4638f0e65c9SRick Macklem 			    dtnfsclient_done_str, 0,
4648f0e65c9SRick Macklem 			    &nfscl_nfs4_done_probes[i]);
4658f0e65c9SRick Macklem 		}
4668f0e65c9SRick Macklem 	}
4678f0e65c9SRick Macklem }
4688f0e65c9SRick Macklem 
4698f0e65c9SRick Macklem static void
dtnfsclient_destroy(void * arg,dtrace_id_t id,void * parg)4708f0e65c9SRick Macklem dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg)
4718f0e65c9SRick Macklem {
4728f0e65c9SRick Macklem }
4738f0e65c9SRick Macklem 
4748f0e65c9SRick Macklem static void
dtnfsclient_enable(void * arg,dtrace_id_t id,void * parg)4758f0e65c9SRick Macklem dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg)
4768f0e65c9SRick Macklem {
4778f0e65c9SRick Macklem 	uint32_t *p = parg;
4788f0e65c9SRick Macklem 	void *f = dtrace_probe;
4798f0e65c9SRick Macklem 
4808f0e65c9SRick Macklem 	if (id == nfscl_accesscache_flush_done_id)
4818f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_flush_done_probe = f;
4828f0e65c9SRick Macklem 	else if (id == nfscl_accesscache_get_hit_id)
4838f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_get_hit_probe = f;
4848f0e65c9SRick Macklem 	else if (id == nfscl_accesscache_get_miss_id)
4858f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_get_miss_probe = f;
4868f0e65c9SRick Macklem 	else if (id == nfscl_accesscache_load_done_id)
4878f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_load_done_probe = f;
4888f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_flush_done_id)
4898f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_flush_done_probe = f;
4908f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_get_hit_id)
4918f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_get_hit_probe = f;
4928f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_get_miss_id)
4938f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_get_miss_probe = f;
4948f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_load_done_id)
4958f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_load_done_probe = f;
4968f0e65c9SRick Macklem 	else
4978f0e65c9SRick Macklem 		*p = id;
4988f0e65c9SRick Macklem }
4998f0e65c9SRick Macklem 
5008f0e65c9SRick Macklem static void
dtnfsclient_disable(void * arg,dtrace_id_t id,void * parg)5018f0e65c9SRick Macklem dtnfsclient_disable(void *arg, dtrace_id_t id, void *parg)
5028f0e65c9SRick Macklem {
5038f0e65c9SRick Macklem 	uint32_t *p = parg;
5048f0e65c9SRick Macklem 
5058f0e65c9SRick Macklem 	if (id == nfscl_accesscache_flush_done_id)
5068f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_flush_done_probe = NULL;
5078f0e65c9SRick Macklem 	else if (id == nfscl_accesscache_get_hit_id)
5088f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_get_hit_probe = NULL;
5098f0e65c9SRick Macklem 	else if (id == nfscl_accesscache_get_miss_id)
5108f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_get_miss_probe = NULL;
5118f0e65c9SRick Macklem 	else if (id == nfscl_accesscache_load_done_id)
5128f0e65c9SRick Macklem 		dtrace_nfscl_accesscache_load_done_probe = NULL;
5138f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_flush_done_id)
5148f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_flush_done_probe = NULL;
5158f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_get_hit_id)
5168f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_get_hit_probe = NULL;
5178f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_get_miss_id)
5188f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_get_miss_probe = NULL;
5198f0e65c9SRick Macklem 	else if (id == nfscl_attrcache_load_done_id)
5208f0e65c9SRick Macklem 		dtrace_nfscl_attrcache_load_done_probe = NULL;
5218f0e65c9SRick Macklem 	else
5228f0e65c9SRick Macklem 		*p = 0;
5238f0e65c9SRick Macklem }
5248f0e65c9SRick Macklem 
5258f0e65c9SRick Macklem static void
dtnfsclient_load(void * dummy)5268f0e65c9SRick Macklem dtnfsclient_load(void *dummy)
5278f0e65c9SRick Macklem {
5288f0e65c9SRick Macklem 
5298f0e65c9SRick Macklem 	if (dtrace_register("nfscl", &dtnfsclient_attr,
5308f0e65c9SRick Macklem 	    DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL,
5318f0e65c9SRick Macklem 	    &dtnfsclient_id) != 0)
5328f0e65c9SRick Macklem 		return;
5338f0e65c9SRick Macklem 
5348f0e65c9SRick Macklem 	dtrace_nfscl_nfs234_start_probe =
5358f0e65c9SRick Macklem 	    (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe;
5368f0e65c9SRick Macklem 	dtrace_nfscl_nfs234_done_probe =
5378f0e65c9SRick Macklem 	    (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe;
5388f0e65c9SRick Macklem }
5398f0e65c9SRick Macklem 
5408f0e65c9SRick Macklem static int
dtnfsclient_unload(void)54127609943SDimitry Andric dtnfsclient_unload(void)
5428f0e65c9SRick Macklem {
5438f0e65c9SRick Macklem 
5448f0e65c9SRick Macklem 	dtrace_nfscl_nfs234_start_probe = NULL;
5458f0e65c9SRick Macklem 	dtrace_nfscl_nfs234_done_probe = NULL;
5468f0e65c9SRick Macklem 
5478f0e65c9SRick Macklem 	return (dtrace_unregister(dtnfsclient_id));
5488f0e65c9SRick Macklem }
5498f0e65c9SRick Macklem 
5508f0e65c9SRick Macklem static int
dtnfsclient_modevent(module_t mod __unused,int type,void * data __unused)5518f0e65c9SRick Macklem dtnfsclient_modevent(module_t mod __unused, int type, void *data __unused)
5528f0e65c9SRick Macklem {
5538f0e65c9SRick Macklem 	int error = 0;
5548f0e65c9SRick Macklem 
5558f0e65c9SRick Macklem 	switch (type) {
5568f0e65c9SRick Macklem 	case MOD_LOAD:
5578f0e65c9SRick Macklem 		break;
5588f0e65c9SRick Macklem 
5598f0e65c9SRick Macklem 	case MOD_UNLOAD:
5608f0e65c9SRick Macklem 		break;
5618f0e65c9SRick Macklem 
5628f0e65c9SRick Macklem 	case MOD_SHUTDOWN:
5638f0e65c9SRick Macklem 		break;
5648f0e65c9SRick Macklem 
5658f0e65c9SRick Macklem 	default:
5668f0e65c9SRick Macklem 		error = EOPNOTSUPP;
5678f0e65c9SRick Macklem 		break;
5688f0e65c9SRick Macklem 	}
5698f0e65c9SRick Macklem 
5708f0e65c9SRick Macklem 	return (error);
5718f0e65c9SRick Macklem }
5728f0e65c9SRick Macklem 
5738f0e65c9SRick Macklem SYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
5748f0e65c9SRick Macklem     dtnfsclient_load, NULL);
5758f0e65c9SRick Macklem SYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
5768f0e65c9SRick Macklem     dtnfsclient_unload, NULL);
5778f0e65c9SRick Macklem 
5788f0e65c9SRick Macklem DEV_MODULE(dtnfscl, dtnfsclient_modevent, NULL);
5798f0e65c9SRick Macklem MODULE_VERSION(dtnfscl, 1);
5808f0e65c9SRick Macklem MODULE_DEPEND(dtnfscl, dtrace, 1, 1, 1);
5818f0e65c9SRick Macklem MODULE_DEPEND(dtnfscl, opensolaris, 1, 1, 1);
5828f0e65c9SRick Macklem MODULE_DEPEND(dtnfscl, nfscl, 1, 1, 1);
5838f0e65c9SRick Macklem MODULE_DEPEND(dtnfscl, nfscommon, 1, 1, 1);
584