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