1190293Srwatson/*- 2190293Srwatson * Copyright (c) 2009 Robert N. M. Watson 3190293Srwatson * All rights reserved. 4190293Srwatson * 5190293Srwatson * This software was developed at the University of Cambridge Computer 6190293Srwatson * Laboratory with support from a grant from Google, Inc. 7190293Srwatson * 8190293Srwatson * Redistribution and use in source and binary forms, with or without 9190293Srwatson * modification, are permitted provided that the following conditions 10190293Srwatson * are met: 11190293Srwatson * 1. Redistributions of source code must retain the above copyright 12190293Srwatson * notice, this list of conditions and the following disclaimer. 13190293Srwatson * 2. Redistributions in binary form must reproduce the above copyright 14190293Srwatson * notice, this list of conditions and the following disclaimer in the 15190293Srwatson * documentation and/or other materials provided with the distribution. 16190293Srwatson * 17190293Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18190293Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19190293Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20190293Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21190293Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22190293Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23190293Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24190293Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25190293Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26190293Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27190293Srwatson * SUCH DAMAGE. 28190293Srwatson */ 29190293Srwatson 30190293Srwatson#include <sys/cdefs.h> 31190293Srwatson__FBSDID("$FreeBSD$"); 32190293Srwatson 33190293Srwatson#include <sys/param.h> 34190293Srwatson#include <sys/systm.h> 35190293Srwatson#include <sys/conf.h> 36190293Srwatson#include <sys/kernel.h> 37190293Srwatson#include <sys/malloc.h> 38190293Srwatson#include <sys/module.h> 39190293Srwatson 40190293Srwatson#include <sys/dtrace.h> 41190293Srwatson#include <sys/dtrace_bsd.h> 42190293Srwatson 43190293Srwatson#include <nfs/nfsproto.h> 44190293Srwatson 45190293Srwatson/* 46190293Srwatson * dtnfsclient is a DTrace provider that tracks the intent to perform RPCs 47190380Srwatson * in the NFS client, as well as acess to and maintenance of the access and 48190380Srwatson * attribute caches. This is not quite the same as RPCs, because NFS may 49190293Srwatson * issue multiple RPC transactions in the event that authentication fails, 50190380Srwatson * there's a jukebox error, or none at all if the access or attribute cache 51190380Srwatson * hits. However, it cleanly represents the logical layer between RPC 52190380Srwatson * transmission and vnode/vfs operations, providing access to state linking 53190380Srwatson * the two. 54190293Srwatson */ 55190293Srwatson 56190293Srwatsonstatic int dtnfsclient_unload(void); 57190293Srwatsonstatic void dtnfsclient_getargdesc(void *, dtrace_id_t, void *, 58190293Srwatson dtrace_argdesc_t *); 59190293Srwatsonstatic void dtnfsclient_provide(void *, dtrace_probedesc_t *); 60190293Srwatsonstatic void dtnfsclient_destroy(void *, dtrace_id_t, void *); 61190293Srwatsonstatic void dtnfsclient_enable(void *, dtrace_id_t, void *); 62190293Srwatsonstatic void dtnfsclient_disable(void *, dtrace_id_t, void *); 63190293Srwatsonstatic void dtnfsclient_load(void *); 64190293Srwatson 65190293Srwatsonstatic dtrace_pattr_t dtnfsclient_attr = { 66190293Srwatson{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 67190293Srwatson{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 68190293Srwatson{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 69190293Srwatson{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 70190293Srwatson{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 71190293Srwatson}; 72190293Srwatson 73190380Srwatson/* 74191776Srwatson * Description of NFSv3 and (optional) NFSv2 probes for a procedure. 75190380Srwatson */ 76190293Srwatsonstruct dtnfsclient_rpc { 77190293Srwatson char *nr_v3_name; 78190293Srwatson char *nr_v2_name; /* Or NULL if none. */ 79190293Srwatson 80190293Srwatson /* 81190293Srwatson * IDs for the start and done cases, for both NFSv2 and NFSv3. 82190293Srwatson */ 83190293Srwatson uint32_t nr_v2_id_start, nr_v2_id_done; 84190293Srwatson uint32_t nr_v3_id_start, nr_v3_id_done; 85190293Srwatson}; 86190293Srwatson 87190293Srwatson/* 88190293Srwatson * This table is indexed by NFSv3 procedure number, but also used for NFSv2 89190293Srwatson * procedure names. 90190293Srwatson */ 91190293Srwatsonstatic struct dtnfsclient_rpc dtnfsclient_rpcs[NFS_NPROCS] = { 92190293Srwatson { "null", "null" }, 93190293Srwatson { "getattr", "getattr" }, 94190293Srwatson { "setattr", "setattr" }, 95190293Srwatson { "lookup", "lookup" }, 96190293Srwatson { "access" }, 97190293Srwatson { "readlink", "readlink" }, 98190293Srwatson { "read", "read" }, 99190293Srwatson { "write", "write" }, 100190293Srwatson { "create", "create" }, 101190293Srwatson { "mkdir", "mkdir" }, 102190293Srwatson { "symlink", "symlink" }, 103190293Srwatson { "mknod" }, 104190293Srwatson { "remove", "remove" }, 105190293Srwatson { "rmdir", "rmdir" }, 106190293Srwatson { "rename", "rename" }, 107190293Srwatson { "link", "link" }, 108190293Srwatson { "readdir", "readdir" }, 109190293Srwatson { "readdirplus" }, 110190293Srwatson { "fsstat", "statfs" }, 111190293Srwatson { "fsinfo" }, 112190293Srwatson { "pathconf" }, 113190293Srwatson { "commit" }, 114190293Srwatson { "noop" }, 115190293Srwatson}; 116190293Srwatson 117190380Srwatson/* 118190380Srwatson * Module name strings. 119190380Srwatson */ 120190380Srwatsonstatic char *dtnfsclient_accesscache_str = "accesscache"; 121190380Srwatsonstatic char *dtnfsclient_attrcache_str = "attrcache"; 122190380Srwatsonstatic char *dtnfsclient_nfs2_str = "nfs2"; 123190380Srwatsonstatic char *dtnfsclient_nfs3_str = "nfs3"; 124190293Srwatson 125190380Srwatson/* 126190380Srwatson * Function name strings. 127190380Srwatson */ 128190380Srwatsonstatic char *dtnfsclient_flush_str = "flush"; 129190380Srwatsonstatic char *dtnfsclient_load_str = "load"; 130190380Srwatsonstatic char *dtnfsclient_get_str = "get"; 131190293Srwatson 132190380Srwatson/* 133190380Srwatson * Name strings. 134190380Srwatson */ 135190380Srwatsonstatic char *dtnfsclient_done_str = "done"; 136190380Srwatsonstatic char *dtnfsclient_hit_str = "hit"; 137190380Srwatsonstatic char *dtnfsclient_miss_str = "miss"; 138190380Srwatsonstatic char *dtnfsclient_start_str = "start"; 139190380Srwatson 140190293Srwatsonstatic dtrace_pops_t dtnfsclient_pops = { 141190293Srwatson dtnfsclient_provide, 142190293Srwatson NULL, 143190293Srwatson dtnfsclient_enable, 144190293Srwatson dtnfsclient_disable, 145190293Srwatson NULL, 146190293Srwatson NULL, 147190293Srwatson dtnfsclient_getargdesc, 148190293Srwatson NULL, 149190293Srwatson NULL, 150190293Srwatson dtnfsclient_destroy 151190293Srwatson}; 152190293Srwatson 153190293Srwatsonstatic dtrace_provider_id_t dtnfsclient_id; 154190293Srwatson 155190293Srwatson/* 156190380Srwatson * Most probes are generated from the above RPC table, but for access and 157190380Srwatson * attribute caches, we have specific IDs we recognize and handle specially 158190380Srwatson * in various spots. 159190380Srwatson */ 160190380Srwatsonextern uint32_t nfsclient_accesscache_flush_done_id; 161190380Srwatsonextern uint32_t nfsclient_accesscache_get_hit_id; 162190380Srwatsonextern uint32_t nfsclient_accesscache_get_miss_id; 163190380Srwatsonextern uint32_t nfsclient_accesscache_load_done_id; 164190380Srwatson 165190380Srwatsonextern uint32_t nfsclient_attrcache_flush_done_id; 166190380Srwatsonextern uint32_t nfsclient_attrcache_get_hit_id; 167190380Srwatsonextern uint32_t nfsclient_attrcache_get_miss_id; 168190380Srwatsonextern uint32_t nfsclient_attrcache_load_done_id; 169190380Srwatson 170190380Srwatson/* 171190380Srwatson * When tracing on a procedure is enabled, the DTrace ID for an RPC event is 172190293Srwatson * stored in one of these two NFS client-allocated arrays; 0 indicates that 173190293Srwatson * the event is not being traced so probes should not be called. 174190293Srwatson * 175190293Srwatson * For simplicity, we allocate both v2 and v3 arrays as NFS_NPROCS, and the 176190293Srwatson * v2 array is simply sparse. 177190293Srwatson */ 178190293Srwatsonextern uint32_t nfsclient_nfs2_start_probes[NFS_NPROCS]; 179190293Srwatsonextern uint32_t nfsclient_nfs2_done_probes[NFS_NPROCS]; 180190293Srwatson 181190293Srwatsonextern uint32_t nfsclient_nfs3_start_probes[NFS_NPROCS]; 182190293Srwatsonextern uint32_t nfsclient_nfs3_done_probes[NFS_NPROCS]; 183190293Srwatson 184190293Srwatson/* 185190293Srwatson * Look up a DTrace probe ID to see if it's associated with a "done" event -- 186190293Srwatson * if so, we will return a fourth argument type of "int". 187190293Srwatson */ 188190293Srwatsonstatic int 189190293Srwatsondtnfs23_isdoneprobe(dtrace_id_t id) 190190293Srwatson{ 191190293Srwatson int i; 192190293Srwatson 193190293Srwatson for (i = 0; i < NFS_NPROCS; i++) { 194190293Srwatson if (dtnfsclient_rpcs[i].nr_v3_id_done == id || 195190293Srwatson dtnfsclient_rpcs[i].nr_v2_id_done == id) 196190293Srwatson return (1); 197190293Srwatson } 198190293Srwatson return (0); 199190293Srwatson} 200190293Srwatson 201190293Srwatsonstatic void 202190293Srwatsondtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg, 203190293Srwatson dtrace_argdesc_t *desc) 204190293Srwatson{ 205190293Srwatson const char *p = NULL; 206190293Srwatson 207190380Srwatson if (id == nfsclient_accesscache_flush_done_id || 208190380Srwatson id == nfsclient_attrcache_flush_done_id || 209190380Srwatson id == nfsclient_attrcache_get_miss_id) { 210190380Srwatson switch (desc->dtargd_ndx) { 211190380Srwatson case 0: 212190380Srwatson p = "struct vnode *"; 213190380Srwatson break; 214190380Srwatson default: 215190380Srwatson desc->dtargd_ndx = DTRACE_ARGNONE; 216190380Srwatson break; 217190380Srwatson } 218190380Srwatson } else if (id == nfsclient_accesscache_get_hit_id || 219190380Srwatson id == nfsclient_accesscache_get_miss_id) { 220190380Srwatson switch (desc->dtargd_ndx) { 221190380Srwatson case 0: 222190380Srwatson p = "struct vnode *"; 223190380Srwatson break; 224190380Srwatson case 1: 225190380Srwatson p = "uid_t"; 226190380Srwatson break; 227190380Srwatson case 2: 228190380Srwatson p = "uint32_t"; 229190380Srwatson break; 230190380Srwatson default: 231190380Srwatson desc->dtargd_ndx = DTRACE_ARGNONE; 232190380Srwatson break; 233190380Srwatson } 234190380Srwatson } else if (id == nfsclient_accesscache_load_done_id) { 235190380Srwatson switch (desc->dtargd_ndx) { 236190380Srwatson case 0: 237190380Srwatson p = "struct vnode *"; 238190380Srwatson break; 239190380Srwatson case 1: 240190380Srwatson p = "uid_t"; 241190380Srwatson break; 242190380Srwatson case 2: 243190380Srwatson p = "uint32_t"; 244190380Srwatson break; 245190380Srwatson case 3: 246190293Srwatson p = "int"; 247190293Srwatson break; 248190380Srwatson default: 249190380Srwatson desc->dtargd_ndx = DTRACE_ARGNONE; 250190380Srwatson break; 251190293Srwatson } 252190380Srwatson } else if (id == nfsclient_attrcache_get_hit_id) { 253190380Srwatson switch (desc->dtargd_ndx) { 254190380Srwatson case 0: 255190380Srwatson p = "struct vnode *"; 256190380Srwatson break; 257190380Srwatson case 1: 258190380Srwatson p = "struct vattr *"; 259190380Srwatson break; 260190380Srwatson default: 261190380Srwatson desc->dtargd_ndx = DTRACE_ARGNONE; 262190380Srwatson break; 263190380Srwatson } 264190380Srwatson } else if (id == nfsclient_attrcache_load_done_id) { 265190380Srwatson switch (desc->dtargd_ndx) { 266190380Srwatson case 0: 267190380Srwatson p = "struct vnode *"; 268190380Srwatson break; 269190380Srwatson case 1: 270190380Srwatson p = "struct vattr *"; 271190380Srwatson break; 272190380Srwatson case 2: 273190380Srwatson p = "int"; 274190380Srwatson break; 275190380Srwatson default: 276190380Srwatson desc->dtargd_ndx = DTRACE_ARGNONE; 277190380Srwatson break; 278190380Srwatson } 279190380Srwatson } else { 280190380Srwatson switch (desc->dtargd_ndx) { 281190380Srwatson case 0: 282190380Srwatson p = "struct vnode *"; 283190380Srwatson break; 284190380Srwatson case 1: 285190380Srwatson p = "struct mbuf *"; 286190380Srwatson break; 287190380Srwatson case 2: 288190380Srwatson p = "struct ucred *"; 289190380Srwatson break; 290190380Srwatson case 3: 291190380Srwatson p = "int"; 292190380Srwatson break; 293190380Srwatson case 4: 294190380Srwatson if (dtnfs23_isdoneprobe(id)) { 295190380Srwatson p = "int"; 296190380Srwatson break; 297190380Srwatson } 298190380Srwatson /* FALLSTHROUGH */ 299190380Srwatson default: 300190380Srwatson desc->dtargd_ndx = DTRACE_ARGNONE; 301190380Srwatson break; 302190380Srwatson } 303190293Srwatson } 304190293Srwatson if (p != NULL) 305190293Srwatson strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native)); 306190293Srwatson} 307190293Srwatson 308190293Srwatsonstatic void 309190293Srwatsondtnfsclient_provide(void *arg, dtrace_probedesc_t *desc) 310190293Srwatson{ 311190293Srwatson int i; 312190293Srwatson 313190293Srwatson if (desc != NULL) 314190293Srwatson return; 315190293Srwatson 316190293Srwatson /* 317190380Srwatson * Register access cache probes. 318190293Srwatson */ 319190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 320190380Srwatson dtnfsclient_flush_str, dtnfsclient_done_str) == 0) { 321190380Srwatson nfsclient_accesscache_flush_done_id = dtrace_probe_create( 322190380Srwatson dtnfsclient_id, dtnfsclient_accesscache_str, 323190380Srwatson dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL); 324190380Srwatson } 325190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 326190380Srwatson dtnfsclient_get_str, dtnfsclient_hit_str) == 0) { 327190380Srwatson nfsclient_accesscache_get_hit_id = dtrace_probe_create( 328190380Srwatson dtnfsclient_id, dtnfsclient_accesscache_str, 329190380Srwatson dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL); 330190380Srwatson } 331190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 332190380Srwatson dtnfsclient_get_str, dtnfsclient_miss_str) == 0) { 333190380Srwatson nfsclient_accesscache_get_miss_id = dtrace_probe_create( 334190380Srwatson dtnfsclient_id, dtnfsclient_accesscache_str, 335190380Srwatson dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL); 336190380Srwatson } 337190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 338190380Srwatson dtnfsclient_load_str, dtnfsclient_done_str) == 0) { 339190380Srwatson nfsclient_accesscache_load_done_id = dtrace_probe_create( 340190380Srwatson dtnfsclient_id, dtnfsclient_accesscache_str, 341190380Srwatson dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL); 342190380Srwatson } 343190380Srwatson 344190380Srwatson /* 345190380Srwatson * Register attribute cache probes. 346190380Srwatson */ 347190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 348190380Srwatson dtnfsclient_flush_str, dtnfsclient_done_str) == 0) { 349190380Srwatson nfsclient_attrcache_flush_done_id = dtrace_probe_create( 350190380Srwatson dtnfsclient_id, dtnfsclient_attrcache_str, 351190380Srwatson dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL); 352190380Srwatson } 353190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 354190380Srwatson dtnfsclient_get_str, dtnfsclient_hit_str) == 0) { 355190380Srwatson nfsclient_attrcache_get_hit_id = dtrace_probe_create( 356190380Srwatson dtnfsclient_id, dtnfsclient_attrcache_str, 357190380Srwatson dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL); 358190380Srwatson } 359190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 360190380Srwatson dtnfsclient_get_str, dtnfsclient_miss_str) == 0) { 361190380Srwatson nfsclient_attrcache_get_miss_id = dtrace_probe_create( 362190380Srwatson dtnfsclient_id, dtnfsclient_attrcache_str, 363190380Srwatson dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL); 364190380Srwatson } 365190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 366190380Srwatson dtnfsclient_load_str, dtnfsclient_done_str) == 0) { 367190380Srwatson nfsclient_attrcache_load_done_id = dtrace_probe_create( 368190380Srwatson dtnfsclient_id, dtnfsclient_attrcache_str, 369190380Srwatson dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL); 370190380Srwatson } 371190380Srwatson 372190380Srwatson /* 373190380Srwatson * Register NFSv2 RPC procedures; note sparseness check for each slot 374190380Srwatson * in the NFSv3 procnum-indexed array. 375190380Srwatson */ 376190293Srwatson for (i = 0; i < NFS_NPROCS; i++) { 377190293Srwatson if (dtnfsclient_rpcs[i].nr_v2_name != NULL && 378190380Srwatson dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str, 379190380Srwatson dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) == 380190380Srwatson 0) { 381190293Srwatson dtnfsclient_rpcs[i].nr_v2_id_start = 382190293Srwatson dtrace_probe_create(dtnfsclient_id, 383190380Srwatson dtnfsclient_nfs2_str, 384190293Srwatson dtnfsclient_rpcs[i].nr_v2_name, 385190380Srwatson dtnfsclient_start_str, 0, 386190293Srwatson &nfsclient_nfs2_start_probes[i]); 387190293Srwatson } 388190293Srwatson if (dtnfsclient_rpcs[i].nr_v2_name != NULL && 389190380Srwatson dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str, 390190380Srwatson dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) == 391190380Srwatson 0) { 392190293Srwatson dtnfsclient_rpcs[i].nr_v2_id_done = 393190293Srwatson dtrace_probe_create(dtnfsclient_id, 394190380Srwatson dtnfsclient_nfs2_str, 395190293Srwatson dtnfsclient_rpcs[i].nr_v2_name, 396190380Srwatson dtnfsclient_done_str, 0, 397190293Srwatson &nfsclient_nfs2_done_probes[i]); 398190293Srwatson } 399190293Srwatson } 400190293Srwatson 401190293Srwatson /* 402190380Srwatson * Register NFSv3 RPC procedures. 403190293Srwatson */ 404190293Srwatson for (i = 0; i < NFS_NPROCS; i++) { 405190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str, 406190380Srwatson dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) == 407190380Srwatson 0) { 408190293Srwatson dtnfsclient_rpcs[i].nr_v3_id_start = 409190293Srwatson dtrace_probe_create(dtnfsclient_id, 410190380Srwatson dtnfsclient_nfs3_str, 411190293Srwatson dtnfsclient_rpcs[i].nr_v3_name, 412190380Srwatson dtnfsclient_start_str, 0, 413190293Srwatson &nfsclient_nfs3_start_probes[i]); 414190293Srwatson } 415190380Srwatson if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str, 416190380Srwatson dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) == 417190380Srwatson 0) { 418190293Srwatson dtnfsclient_rpcs[i].nr_v3_id_done = 419190293Srwatson dtrace_probe_create(dtnfsclient_id, 420190380Srwatson dtnfsclient_nfs3_str, 421190293Srwatson dtnfsclient_rpcs[i].nr_v3_name, 422190380Srwatson dtnfsclient_done_str, 0, 423190293Srwatson &nfsclient_nfs3_done_probes[i]); 424190293Srwatson } 425190293Srwatson } 426190293Srwatson} 427190293Srwatson 428190293Srwatsonstatic void 429190293Srwatsondtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg) 430190293Srwatson{ 431190293Srwatson} 432190293Srwatson 433190293Srwatsonstatic void 434190293Srwatsondtnfsclient_enable(void *arg, dtrace_id_t id, void *parg) 435190293Srwatson{ 436190293Srwatson uint32_t *p = parg; 437190380Srwatson void *f = dtrace_probe; 438190293Srwatson 439190380Srwatson if (id == nfsclient_accesscache_flush_done_id) 440190380Srwatson dtrace_nfsclient_accesscache_flush_done_probe = f; 441190380Srwatson else if (id == nfsclient_accesscache_get_hit_id) 442190380Srwatson dtrace_nfsclient_accesscache_get_hit_probe = f; 443190380Srwatson else if (id == nfsclient_accesscache_get_miss_id) 444190380Srwatson dtrace_nfsclient_accesscache_get_miss_probe = f; 445190380Srwatson else if (id == nfsclient_accesscache_load_done_id) 446190380Srwatson dtrace_nfsclient_accesscache_load_done_probe = f; 447190380Srwatson else if (id == nfsclient_attrcache_flush_done_id) 448190380Srwatson dtrace_nfsclient_attrcache_flush_done_probe = f; 449190380Srwatson else if (id == nfsclient_attrcache_get_hit_id) 450190380Srwatson dtrace_nfsclient_attrcache_get_hit_probe = f; 451190380Srwatson else if (id == nfsclient_attrcache_get_miss_id) 452190380Srwatson dtrace_nfsclient_attrcache_get_miss_probe = f; 453190380Srwatson else if (id == nfsclient_attrcache_load_done_id) 454190380Srwatson dtrace_nfsclient_attrcache_load_done_probe = f; 455190380Srwatson else 456190380Srwatson *p = id; 457190293Srwatson} 458190293Srwatson 459190293Srwatsonstatic void 460190293Srwatsondtnfsclient_disable(void *arg, dtrace_id_t id, void *parg) 461190293Srwatson{ 462190293Srwatson uint32_t *p = parg; 463190293Srwatson 464190380Srwatson if (id == nfsclient_accesscache_flush_done_id) 465190380Srwatson dtrace_nfsclient_accesscache_flush_done_probe = NULL; 466190380Srwatson else if (id == nfsclient_accesscache_get_hit_id) 467190380Srwatson dtrace_nfsclient_accesscache_get_hit_probe = NULL; 468190380Srwatson else if (id == nfsclient_accesscache_get_miss_id) 469190380Srwatson dtrace_nfsclient_accesscache_get_miss_probe = NULL; 470190380Srwatson else if (id == nfsclient_accesscache_load_done_id) 471190380Srwatson dtrace_nfsclient_accesscache_load_done_probe = NULL; 472190380Srwatson else if (id == nfsclient_attrcache_flush_done_id) 473190380Srwatson dtrace_nfsclient_attrcache_flush_done_probe = NULL; 474190380Srwatson else if (id == nfsclient_attrcache_get_hit_id) 475190380Srwatson dtrace_nfsclient_attrcache_get_hit_probe = NULL; 476190380Srwatson else if (id == nfsclient_attrcache_get_miss_id) 477190380Srwatson dtrace_nfsclient_attrcache_get_miss_probe = NULL; 478190380Srwatson else if (id == nfsclient_attrcache_load_done_id) 479190380Srwatson dtrace_nfsclient_attrcache_load_done_probe = NULL; 480190380Srwatson else 481190380Srwatson *p = 0; 482190293Srwatson} 483190293Srwatson 484190293Srwatsonstatic void 485190293Srwatsondtnfsclient_load(void *dummy) 486190293Srwatson{ 487190293Srwatson 488190293Srwatson if (dtrace_register("nfsclient", &dtnfsclient_attr, 489190293Srwatson DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL, 490190293Srwatson &dtnfsclient_id) != 0) 491190293Srwatson return; 492190293Srwatson 493190293Srwatson dtrace_nfsclient_nfs23_start_probe = 494190293Srwatson (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe; 495190293Srwatson dtrace_nfsclient_nfs23_done_probe = 496190293Srwatson (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe; 497190293Srwatson} 498190293Srwatson 499190293Srwatson 500190293Srwatsonstatic int 501190293Srwatsondtnfsclient_unload() 502190293Srwatson{ 503190293Srwatson 504190293Srwatson dtrace_nfsclient_nfs23_start_probe = NULL; 505190293Srwatson dtrace_nfsclient_nfs23_done_probe = NULL; 506190293Srwatson 507204063Spjd return (dtrace_unregister(dtnfsclient_id)); 508190293Srwatson} 509190293Srwatson 510190293Srwatsonstatic int 511190293Srwatsondtnfsclient_modevent(module_t mod __unused, int type, void *data __unused) 512190293Srwatson{ 513190293Srwatson int error = 0; 514190293Srwatson 515190293Srwatson switch (type) { 516190293Srwatson case MOD_LOAD: 517190293Srwatson break; 518190293Srwatson 519190293Srwatson case MOD_UNLOAD: 520190293Srwatson break; 521190293Srwatson 522190293Srwatson case MOD_SHUTDOWN: 523190293Srwatson break; 524190293Srwatson 525190293Srwatson default: 526190293Srwatson error = EOPNOTSUPP; 527190293Srwatson break; 528190293Srwatson } 529190293Srwatson 530190293Srwatson return (error); 531190293Srwatson} 532190293Srwatson 533190293SrwatsonSYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 534190293Srwatson dtnfsclient_load, NULL); 535190293SrwatsonSYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 536190293Srwatson dtnfsclient_unload, NULL); 537190293Srwatson 538190293SrwatsonDEV_MODULE(dtnfsclient, dtnfsclient_modevent, NULL); 539190293SrwatsonMODULE_VERSION(dtnfsclient, 1); 540190293SrwatsonMODULE_DEPEND(dtnfsclient, dtrace, 1, 1, 1); 541190293SrwatsonMODULE_DEPEND(dtnfsclient, opensolaris, 1, 1, 1); 542221542SrmacklemMODULE_DEPEND(dtnfsclient, oldnfs, 1, 1, 1); 543