1223280Srmacklem/*- 2223280Srmacklem * Copyright (c) 2009 Robert N. M. Watson 3223280Srmacklem * All rights reserved. 4223280Srmacklem * 5223280Srmacklem * This software was developed at the University of Cambridge Computer 6223280Srmacklem * Laboratory with support from a grant from Google, Inc. 7223280Srmacklem * 8223280Srmacklem * Redistribution and use in source and binary forms, with or without 9223280Srmacklem * modification, are permitted provided that the following conditions 10223280Srmacklem * are met: 11223280Srmacklem * 1. Redistributions of source code must retain the above copyright 12223280Srmacklem * notice, this list of conditions and the following disclaimer. 13223280Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14223280Srmacklem * notice, this list of conditions and the following disclaimer in the 15223280Srmacklem * documentation and/or other materials provided with the distribution. 16223280Srmacklem * 17223280Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18223280Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19223280Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20223280Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21223280Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22223280Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23223280Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24223280Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25223280Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26223280Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27223280Srmacklem * SUCH DAMAGE. 28223280Srmacklem */ 29223280Srmacklem 30223280Srmacklem#include <sys/cdefs.h> 31223280Srmacklem__FBSDID("$FreeBSD$"); 32223280Srmacklem 33223280Srmacklem#include <sys/param.h> 34223280Srmacklem#include <sys/systm.h> 35223280Srmacklem#include <sys/conf.h> 36223280Srmacklem#include <sys/kernel.h> 37223280Srmacklem#include <sys/malloc.h> 38223280Srmacklem#include <sys/module.h> 39223280Srmacklem 40223280Srmacklem#include <sys/dtrace.h> 41223280Srmacklem#include <sys/dtrace_bsd.h> 42223280Srmacklem 43223280Srmacklem#include <fs/nfs/nfsproto.h> 44223280Srmacklem 45223280Srmacklem#include <fs/nfsclient/nfs_kdtrace.h> 46223280Srmacklem 47223280Srmacklem/* 48223280Srmacklem * dtnfscl is a DTrace provider that tracks the intent to perform RPCs 49223280Srmacklem * in the NFS client, as well as acess to and maintenance of the access and 50223280Srmacklem * attribute caches. This is not quite the same as RPCs, because NFS may 51223280Srmacklem * issue multiple RPC transactions in the event that authentication fails, 52223280Srmacklem * there's a jukebox error, or none at all if the access or attribute cache 53223280Srmacklem * hits. However, it cleanly represents the logical layer between RPC 54223280Srmacklem * transmission and vnode/vfs operations, providing access to state linking 55223280Srmacklem * the two. 56223280Srmacklem */ 57223280Srmacklem 58223280Srmacklemstatic int dtnfsclient_unload(void); 59223280Srmacklemstatic void dtnfsclient_getargdesc(void *, dtrace_id_t, void *, 60223280Srmacklem dtrace_argdesc_t *); 61223280Srmacklemstatic void dtnfsclient_provide(void *, dtrace_probedesc_t *); 62223280Srmacklemstatic void dtnfsclient_destroy(void *, dtrace_id_t, void *); 63223280Srmacklemstatic void dtnfsclient_enable(void *, dtrace_id_t, void *); 64223280Srmacklemstatic void dtnfsclient_disable(void *, dtrace_id_t, void *); 65223280Srmacklemstatic void dtnfsclient_load(void *); 66223280Srmacklem 67223280Srmacklemstatic dtrace_pattr_t dtnfsclient_attr = { 68223280Srmacklem{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 69223280Srmacklem{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 70223280Srmacklem{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, 71223280Srmacklem{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 72223280Srmacklem{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, 73223280Srmacklem}; 74223280Srmacklem 75223280Srmacklem/* 76223280Srmacklem * Description of NFSv4, NFSv3 and (optional) NFSv2 probes for a procedure. 77223280Srmacklem */ 78223280Srmacklemstruct dtnfsclient_rpc { 79223280Srmacklem char *nr_v4_name; 80223280Srmacklem char *nr_v3_name; /* Or NULL if none. */ 81223280Srmacklem char *nr_v2_name; /* Or NULL if none. */ 82223280Srmacklem 83223280Srmacklem /* 84223280Srmacklem * IDs for the start and done cases, for NFSv2, NFSv3 and NFSv4. 85223280Srmacklem */ 86223280Srmacklem uint32_t nr_v2_id_start, nr_v2_id_done; 87223280Srmacklem uint32_t nr_v3_id_start, nr_v3_id_done; 88223280Srmacklem uint32_t nr_v4_id_start, nr_v4_id_done; 89223280Srmacklem}; 90223280Srmacklem 91223280Srmacklem/* 92223280Srmacklem * This table is indexed by NFSv3 procedure number, but also used for NFSv2 93223280Srmacklem * procedure names and NFSv4 operations. 94223280Srmacklem */ 95223280Srmacklemstatic struct dtnfsclient_rpc dtnfsclient_rpcs[NFS_NPROCS + 1] = { 96223280Srmacklem { "null", "null", "null" }, 97223280Srmacklem { "getattr", "getattr", "getattr" }, 98223280Srmacklem { "setattr", "setattr", "setattr" }, 99223280Srmacklem { "lookup", "lookup", "lookup" }, 100223280Srmacklem { "access", "access", "noop" }, 101223280Srmacklem { "readlink", "readlink", "readlink" }, 102223280Srmacklem { "read", "read", "read" }, 103223280Srmacklem { "write", "write", "write" }, 104223280Srmacklem { "create", "create", "create" }, 105223280Srmacklem { "mkdir", "mkdir", "mkdir" }, 106223280Srmacklem { "symlink", "symlink", "symlink" }, 107223280Srmacklem { "mknod", "mknod" }, 108223280Srmacklem { "remove", "remove", "remove" }, 109223280Srmacklem { "rmdir", "rmdir", "rmdir" }, 110223280Srmacklem { "rename", "rename", "rename" }, 111223280Srmacklem { "link", "link", "link" }, 112223280Srmacklem { "readdir", "readdir", "readdir" }, 113223280Srmacklem { "readdirplus", "readdirplus" }, 114223280Srmacklem { "fsstat", "fsstat", "statfs" }, 115223280Srmacklem { "fsinfo", "fsinfo" }, 116223280Srmacklem { "pathconf", "pathconf" }, 117223280Srmacklem { "commit", "commit" }, 118223280Srmacklem { "lookupp" }, 119223280Srmacklem { "setclientid" }, 120223280Srmacklem { "setclientidcfrm" }, 121223280Srmacklem { "lock" }, 122223280Srmacklem { "locku" }, 123223280Srmacklem { "open" }, 124223280Srmacklem { "close" }, 125223280Srmacklem { "openconfirm" }, 126223280Srmacklem { "lockt" }, 127223280Srmacklem { "opendowngrade" }, 128223280Srmacklem { "renew" }, 129223280Srmacklem { "putrootfh" }, 130223280Srmacklem { "releaselckown" }, 131223280Srmacklem { "delegreturn" }, 132223280Srmacklem { "retdelegremove" }, 133223280Srmacklem { "retdelegrename1" }, 134223280Srmacklem { "retdelegrename2" }, 135223280Srmacklem { "getacl" }, 136223280Srmacklem { "setacl" }, 137223280Srmacklem { "noop", "noop", "noop" } 138223280Srmacklem}; 139223280Srmacklem 140223280Srmacklem/* 141223280Srmacklem * Module name strings. 142223280Srmacklem */ 143223280Srmacklemstatic char *dtnfsclient_accesscache_str = "accesscache"; 144223280Srmacklemstatic char *dtnfsclient_attrcache_str = "attrcache"; 145223280Srmacklemstatic char *dtnfsclient_nfs2_str = "nfs2"; 146223280Srmacklemstatic char *dtnfsclient_nfs3_str = "nfs3"; 147223280Srmacklemstatic char *dtnfsclient_nfs4_str = "nfs4"; 148223280Srmacklem 149223280Srmacklem/* 150223280Srmacklem * Function name strings. 151223280Srmacklem */ 152223280Srmacklemstatic char *dtnfsclient_flush_str = "flush"; 153223280Srmacklemstatic char *dtnfsclient_load_str = "load"; 154223280Srmacklemstatic char *dtnfsclient_get_str = "get"; 155223280Srmacklem 156223280Srmacklem/* 157223280Srmacklem * Name strings. 158223280Srmacklem */ 159223280Srmacklemstatic char *dtnfsclient_done_str = "done"; 160223280Srmacklemstatic char *dtnfsclient_hit_str = "hit"; 161223280Srmacklemstatic char *dtnfsclient_miss_str = "miss"; 162223280Srmacklemstatic char *dtnfsclient_start_str = "start"; 163223280Srmacklem 164223280Srmacklemstatic dtrace_pops_t dtnfsclient_pops = { 165223280Srmacklem dtnfsclient_provide, 166223280Srmacklem NULL, 167223280Srmacklem dtnfsclient_enable, 168223280Srmacklem dtnfsclient_disable, 169223280Srmacklem NULL, 170223280Srmacklem NULL, 171223280Srmacklem dtnfsclient_getargdesc, 172223280Srmacklem NULL, 173223280Srmacklem NULL, 174223280Srmacklem dtnfsclient_destroy 175223280Srmacklem}; 176223280Srmacklem 177223280Srmacklemstatic dtrace_provider_id_t dtnfsclient_id; 178223280Srmacklem 179223280Srmacklem/* 180223280Srmacklem * Most probes are generated from the above RPC table, but for access and 181223280Srmacklem * attribute caches, we have specific IDs we recognize and handle specially 182223280Srmacklem * in various spots. 183223280Srmacklem */ 184223280Srmacklemextern uint32_t nfscl_accesscache_flush_done_id; 185223280Srmacklemextern uint32_t nfscl_accesscache_get_hit_id; 186223280Srmacklemextern uint32_t nfscl_accesscache_get_miss_id; 187223280Srmacklemextern uint32_t nfscl_accesscache_load_done_id; 188223280Srmacklem 189223280Srmacklemextern uint32_t nfscl_attrcache_flush_done_id; 190223280Srmacklemextern uint32_t nfscl_attrcache_get_hit_id; 191223280Srmacklemextern uint32_t nfscl_attrcache_get_miss_id; 192223280Srmacklemextern uint32_t nfscl_attrcache_load_done_id; 193223280Srmacklem 194223280Srmacklem/* 195223280Srmacklem * When tracing on a procedure is enabled, the DTrace ID for an RPC event is 196223280Srmacklem * stored in one of these two NFS client-allocated arrays; 0 indicates that 197223280Srmacklem * the event is not being traced so probes should not be called. 198223280Srmacklem * 199223280Srmacklem * For simplicity, we allocate both v2, v3 and v4 arrays as NFS_NPROCS + 1, and 200223280Srmacklem * the v2, v3 arrays are simply sparse. 201223280Srmacklem */ 202223280Srmacklemextern uint32_t nfscl_nfs2_start_probes[NFS_NPROCS + 1]; 203223280Srmacklemextern uint32_t nfscl_nfs2_done_probes[NFS_NPROCS + 1]; 204223280Srmacklem 205223280Srmacklemextern uint32_t nfscl_nfs3_start_probes[NFS_NPROCS + 1]; 206223280Srmacklemextern uint32_t nfscl_nfs3_done_probes[NFS_NPROCS + 1]; 207223280Srmacklem 208223280Srmacklemextern uint32_t nfscl_nfs4_start_probes[NFS_NPROCS + 1]; 209223280Srmacklemextern uint32_t nfscl_nfs4_done_probes[NFS_NPROCS + 1]; 210223280Srmacklem 211223280Srmacklem/* 212223280Srmacklem * Look up a DTrace probe ID to see if it's associated with a "done" event -- 213223280Srmacklem * if so, we will return a fourth argument type of "int". 214223280Srmacklem */ 215223280Srmacklemstatic int 216223280Srmacklemdtnfs234_isdoneprobe(dtrace_id_t id) 217223280Srmacklem{ 218223280Srmacklem int i; 219223280Srmacklem 220223280Srmacklem for (i = 0; i < NFS_NPROCS + 1; i++) { 221223280Srmacklem if (dtnfsclient_rpcs[i].nr_v4_id_done == id || 222223280Srmacklem dtnfsclient_rpcs[i].nr_v3_id_done == id || 223223280Srmacklem dtnfsclient_rpcs[i].nr_v2_id_done == id) 224223280Srmacklem return (1); 225223280Srmacklem } 226223280Srmacklem return (0); 227223280Srmacklem} 228223280Srmacklem 229223280Srmacklemstatic void 230223280Srmacklemdtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg, 231223280Srmacklem dtrace_argdesc_t *desc) 232223280Srmacklem{ 233223280Srmacklem const char *p = NULL; 234223280Srmacklem 235223280Srmacklem if (id == nfscl_accesscache_flush_done_id || 236223280Srmacklem id == nfscl_attrcache_flush_done_id || 237223280Srmacklem id == nfscl_attrcache_get_miss_id) { 238223280Srmacklem switch (desc->dtargd_ndx) { 239223280Srmacklem case 0: 240223280Srmacklem p = "struct vnode *"; 241223280Srmacklem break; 242223280Srmacklem default: 243223280Srmacklem desc->dtargd_ndx = DTRACE_ARGNONE; 244223280Srmacklem break; 245223280Srmacklem } 246223280Srmacklem } else if (id == nfscl_accesscache_get_hit_id || 247223280Srmacklem id == nfscl_accesscache_get_miss_id) { 248223280Srmacklem switch (desc->dtargd_ndx) { 249223280Srmacklem case 0: 250223280Srmacklem p = "struct vnode *"; 251223280Srmacklem break; 252223280Srmacklem case 1: 253223280Srmacklem p = "uid_t"; 254223280Srmacklem break; 255223280Srmacklem case 2: 256223280Srmacklem p = "uint32_t"; 257223280Srmacklem break; 258223280Srmacklem default: 259223280Srmacklem desc->dtargd_ndx = DTRACE_ARGNONE; 260223280Srmacklem break; 261223280Srmacklem } 262223280Srmacklem } else if (id == nfscl_accesscache_load_done_id) { 263223280Srmacklem switch (desc->dtargd_ndx) { 264223280Srmacklem case 0: 265223280Srmacklem p = "struct vnode *"; 266223280Srmacklem break; 267223280Srmacklem case 1: 268223280Srmacklem p = "uid_t"; 269223280Srmacklem break; 270223280Srmacklem case 2: 271223280Srmacklem p = "uint32_t"; 272223280Srmacklem break; 273223280Srmacklem case 3: 274223280Srmacklem p = "int"; 275223280Srmacklem break; 276223280Srmacklem default: 277223280Srmacklem desc->dtargd_ndx = DTRACE_ARGNONE; 278223280Srmacklem break; 279223280Srmacklem } 280223280Srmacklem } else if (id == nfscl_attrcache_get_hit_id) { 281223280Srmacklem switch (desc->dtargd_ndx) { 282223280Srmacklem case 0: 283223280Srmacklem p = "struct vnode *"; 284223280Srmacklem break; 285223280Srmacklem case 1: 286223280Srmacklem p = "struct vattr *"; 287223280Srmacklem break; 288223280Srmacklem default: 289223280Srmacklem desc->dtargd_ndx = DTRACE_ARGNONE; 290223280Srmacklem break; 291223280Srmacklem } 292223280Srmacklem } else if (id == nfscl_attrcache_load_done_id) { 293223280Srmacklem switch (desc->dtargd_ndx) { 294223280Srmacklem case 0: 295223280Srmacklem p = "struct vnode *"; 296223280Srmacklem break; 297223280Srmacklem case 1: 298223280Srmacklem p = "struct vattr *"; 299223280Srmacklem break; 300223280Srmacklem case 2: 301223280Srmacklem p = "int"; 302223280Srmacklem break; 303223280Srmacklem default: 304223280Srmacklem desc->dtargd_ndx = DTRACE_ARGNONE; 305223280Srmacklem break; 306223280Srmacklem } 307223280Srmacklem } else { 308223280Srmacklem switch (desc->dtargd_ndx) { 309223280Srmacklem case 0: 310223280Srmacklem p = "struct vnode *"; 311223280Srmacklem break; 312223280Srmacklem case 1: 313223280Srmacklem p = "struct mbuf *"; 314223280Srmacklem break; 315223280Srmacklem case 2: 316223280Srmacklem p = "struct ucred *"; 317223280Srmacklem break; 318223280Srmacklem case 3: 319223280Srmacklem p = "int"; 320223280Srmacklem break; 321223280Srmacklem case 4: 322223280Srmacklem if (dtnfs234_isdoneprobe(id)) { 323223280Srmacklem p = "int"; 324223280Srmacklem break; 325223280Srmacklem } 326223280Srmacklem /* FALLSTHROUGH */ 327223280Srmacklem default: 328223280Srmacklem desc->dtargd_ndx = DTRACE_ARGNONE; 329223280Srmacklem break; 330223280Srmacklem } 331223280Srmacklem } 332223280Srmacklem if (p != NULL) 333223280Srmacklem strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native)); 334223280Srmacklem} 335223280Srmacklem 336223280Srmacklemstatic void 337223280Srmacklemdtnfsclient_provide(void *arg, dtrace_probedesc_t *desc) 338223280Srmacklem{ 339223280Srmacklem int i; 340223280Srmacklem 341223280Srmacklem if (desc != NULL) 342223280Srmacklem return; 343223280Srmacklem 344223280Srmacklem /* 345223280Srmacklem * Register access cache probes. 346223280Srmacklem */ 347223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 348223280Srmacklem dtnfsclient_flush_str, dtnfsclient_done_str) == 0) { 349223280Srmacklem nfscl_accesscache_flush_done_id = dtrace_probe_create( 350223280Srmacklem dtnfsclient_id, dtnfsclient_accesscache_str, 351223280Srmacklem dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL); 352223280Srmacklem } 353223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 354223280Srmacklem dtnfsclient_get_str, dtnfsclient_hit_str) == 0) { 355223280Srmacklem nfscl_accesscache_get_hit_id = dtrace_probe_create( 356223280Srmacklem dtnfsclient_id, dtnfsclient_accesscache_str, 357223280Srmacklem dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL); 358223280Srmacklem } 359223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 360223280Srmacklem dtnfsclient_get_str, dtnfsclient_miss_str) == 0) { 361223280Srmacklem nfscl_accesscache_get_miss_id = dtrace_probe_create( 362223280Srmacklem dtnfsclient_id, dtnfsclient_accesscache_str, 363223280Srmacklem dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL); 364223280Srmacklem } 365223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, 366223280Srmacklem dtnfsclient_load_str, dtnfsclient_done_str) == 0) { 367223280Srmacklem nfscl_accesscache_load_done_id = dtrace_probe_create( 368223280Srmacklem dtnfsclient_id, dtnfsclient_accesscache_str, 369223280Srmacklem dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL); 370223280Srmacklem } 371223280Srmacklem 372223280Srmacklem /* 373223280Srmacklem * Register attribute cache probes. 374223280Srmacklem */ 375223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 376223280Srmacklem dtnfsclient_flush_str, dtnfsclient_done_str) == 0) { 377223280Srmacklem nfscl_attrcache_flush_done_id = dtrace_probe_create( 378223280Srmacklem dtnfsclient_id, dtnfsclient_attrcache_str, 379223280Srmacklem dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL); 380223280Srmacklem } 381223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 382223280Srmacklem dtnfsclient_get_str, dtnfsclient_hit_str) == 0) { 383223280Srmacklem nfscl_attrcache_get_hit_id = dtrace_probe_create( 384223280Srmacklem dtnfsclient_id, dtnfsclient_attrcache_str, 385223280Srmacklem dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL); 386223280Srmacklem } 387223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 388223280Srmacklem dtnfsclient_get_str, dtnfsclient_miss_str) == 0) { 389223280Srmacklem nfscl_attrcache_get_miss_id = dtrace_probe_create( 390223280Srmacklem dtnfsclient_id, dtnfsclient_attrcache_str, 391223280Srmacklem dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL); 392223280Srmacklem } 393223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, 394223280Srmacklem dtnfsclient_load_str, dtnfsclient_done_str) == 0) { 395223280Srmacklem nfscl_attrcache_load_done_id = dtrace_probe_create( 396223280Srmacklem dtnfsclient_id, dtnfsclient_attrcache_str, 397223280Srmacklem dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL); 398223280Srmacklem } 399223280Srmacklem 400223280Srmacklem /* 401223280Srmacklem * Register NFSv2 RPC procedures; note sparseness check for each slot 402223280Srmacklem * in the NFSv3, NFSv4 procnum-indexed array. 403223280Srmacklem */ 404223280Srmacklem for (i = 0; i < NFS_NPROCS + 1; i++) { 405223280Srmacklem if (dtnfsclient_rpcs[i].nr_v2_name != NULL && 406223280Srmacklem dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str, 407223280Srmacklem dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) == 408223280Srmacklem 0) { 409223280Srmacklem dtnfsclient_rpcs[i].nr_v2_id_start = 410223280Srmacklem dtrace_probe_create(dtnfsclient_id, 411223280Srmacklem dtnfsclient_nfs2_str, 412223280Srmacklem dtnfsclient_rpcs[i].nr_v2_name, 413223280Srmacklem dtnfsclient_start_str, 0, 414223280Srmacklem &nfscl_nfs2_start_probes[i]); 415223280Srmacklem } 416223280Srmacklem if (dtnfsclient_rpcs[i].nr_v2_name != NULL && 417223280Srmacklem dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str, 418223280Srmacklem dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) == 419223280Srmacklem 0) { 420223280Srmacklem dtnfsclient_rpcs[i].nr_v2_id_done = 421223280Srmacklem dtrace_probe_create(dtnfsclient_id, 422223280Srmacklem dtnfsclient_nfs2_str, 423223280Srmacklem dtnfsclient_rpcs[i].nr_v2_name, 424223280Srmacklem dtnfsclient_done_str, 0, 425223280Srmacklem &nfscl_nfs2_done_probes[i]); 426223280Srmacklem } 427223280Srmacklem } 428223280Srmacklem 429223280Srmacklem /* 430223280Srmacklem * Register NFSv3 RPC procedures; note sparseness check for each slot 431223280Srmacklem * in the NFSv4 procnum-indexed array. 432223280Srmacklem */ 433223280Srmacklem for (i = 0; i < NFS_NPROCS + 1; i++) { 434223280Srmacklem if (dtnfsclient_rpcs[i].nr_v3_name != NULL && 435223280Srmacklem dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str, 436223280Srmacklem dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) == 437223280Srmacklem 0) { 438223280Srmacklem dtnfsclient_rpcs[i].nr_v3_id_start = 439223280Srmacklem dtrace_probe_create(dtnfsclient_id, 440223280Srmacklem dtnfsclient_nfs3_str, 441223280Srmacklem dtnfsclient_rpcs[i].nr_v3_name, 442223280Srmacklem dtnfsclient_start_str, 0, 443223280Srmacklem &nfscl_nfs3_start_probes[i]); 444223280Srmacklem } 445223280Srmacklem if (dtnfsclient_rpcs[i].nr_v3_name != NULL && 446223280Srmacklem dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str, 447223280Srmacklem dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) == 448223280Srmacklem 0) { 449223280Srmacklem dtnfsclient_rpcs[i].nr_v3_id_done = 450223280Srmacklem dtrace_probe_create(dtnfsclient_id, 451223280Srmacklem dtnfsclient_nfs3_str, 452223280Srmacklem dtnfsclient_rpcs[i].nr_v3_name, 453223280Srmacklem dtnfsclient_done_str, 0, 454223280Srmacklem &nfscl_nfs3_done_probes[i]); 455223280Srmacklem } 456223280Srmacklem } 457223280Srmacklem 458223280Srmacklem /* 459223280Srmacklem * Register NFSv4 RPC procedures. 460223280Srmacklem */ 461223280Srmacklem for (i = 0; i < NFS_NPROCS + 1; i++) { 462223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str, 463223280Srmacklem dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_start_str) == 464223280Srmacklem 0) { 465223280Srmacklem dtnfsclient_rpcs[i].nr_v4_id_start = 466223280Srmacklem dtrace_probe_create(dtnfsclient_id, 467223280Srmacklem dtnfsclient_nfs4_str, 468223280Srmacklem dtnfsclient_rpcs[i].nr_v4_name, 469223280Srmacklem dtnfsclient_start_str, 0, 470223280Srmacklem &nfscl_nfs4_start_probes[i]); 471223280Srmacklem } 472223280Srmacklem if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs4_str, 473223280Srmacklem dtnfsclient_rpcs[i].nr_v4_name, dtnfsclient_done_str) == 474223280Srmacklem 0) { 475223280Srmacklem dtnfsclient_rpcs[i].nr_v4_id_done = 476223280Srmacklem dtrace_probe_create(dtnfsclient_id, 477223280Srmacklem dtnfsclient_nfs4_str, 478223280Srmacklem dtnfsclient_rpcs[i].nr_v4_name, 479223280Srmacklem dtnfsclient_done_str, 0, 480223280Srmacklem &nfscl_nfs4_done_probes[i]); 481223280Srmacklem } 482223280Srmacklem } 483223280Srmacklem} 484223280Srmacklem 485223280Srmacklemstatic void 486223280Srmacklemdtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg) 487223280Srmacklem{ 488223280Srmacklem} 489223280Srmacklem 490223280Srmacklemstatic void 491223280Srmacklemdtnfsclient_enable(void *arg, dtrace_id_t id, void *parg) 492223280Srmacklem{ 493223280Srmacklem uint32_t *p = parg; 494223280Srmacklem void *f = dtrace_probe; 495223280Srmacklem 496223280Srmacklem if (id == nfscl_accesscache_flush_done_id) 497223280Srmacklem dtrace_nfscl_accesscache_flush_done_probe = f; 498223280Srmacklem else if (id == nfscl_accesscache_get_hit_id) 499223280Srmacklem dtrace_nfscl_accesscache_get_hit_probe = f; 500223280Srmacklem else if (id == nfscl_accesscache_get_miss_id) 501223280Srmacklem dtrace_nfscl_accesscache_get_miss_probe = f; 502223280Srmacklem else if (id == nfscl_accesscache_load_done_id) 503223280Srmacklem dtrace_nfscl_accesscache_load_done_probe = f; 504223280Srmacklem else if (id == nfscl_attrcache_flush_done_id) 505223280Srmacklem dtrace_nfscl_attrcache_flush_done_probe = f; 506223280Srmacklem else if (id == nfscl_attrcache_get_hit_id) 507223280Srmacklem dtrace_nfscl_attrcache_get_hit_probe = f; 508223280Srmacklem else if (id == nfscl_attrcache_get_miss_id) 509223280Srmacklem dtrace_nfscl_attrcache_get_miss_probe = f; 510223280Srmacklem else if (id == nfscl_attrcache_load_done_id) 511223280Srmacklem dtrace_nfscl_attrcache_load_done_probe = f; 512223280Srmacklem else 513223280Srmacklem *p = id; 514223280Srmacklem} 515223280Srmacklem 516223280Srmacklemstatic void 517223280Srmacklemdtnfsclient_disable(void *arg, dtrace_id_t id, void *parg) 518223280Srmacklem{ 519223280Srmacklem uint32_t *p = parg; 520223280Srmacklem 521223280Srmacklem if (id == nfscl_accesscache_flush_done_id) 522223280Srmacklem dtrace_nfscl_accesscache_flush_done_probe = NULL; 523223280Srmacklem else if (id == nfscl_accesscache_get_hit_id) 524223280Srmacklem dtrace_nfscl_accesscache_get_hit_probe = NULL; 525223280Srmacklem else if (id == nfscl_accesscache_get_miss_id) 526223280Srmacklem dtrace_nfscl_accesscache_get_miss_probe = NULL; 527223280Srmacklem else if (id == nfscl_accesscache_load_done_id) 528223280Srmacklem dtrace_nfscl_accesscache_load_done_probe = NULL; 529223280Srmacklem else if (id == nfscl_attrcache_flush_done_id) 530223280Srmacklem dtrace_nfscl_attrcache_flush_done_probe = NULL; 531223280Srmacklem else if (id == nfscl_attrcache_get_hit_id) 532223280Srmacklem dtrace_nfscl_attrcache_get_hit_probe = NULL; 533223280Srmacklem else if (id == nfscl_attrcache_get_miss_id) 534223280Srmacklem dtrace_nfscl_attrcache_get_miss_probe = NULL; 535223280Srmacklem else if (id == nfscl_attrcache_load_done_id) 536223280Srmacklem dtrace_nfscl_attrcache_load_done_probe = NULL; 537223280Srmacklem else 538223280Srmacklem *p = 0; 539223280Srmacklem} 540223280Srmacklem 541223280Srmacklemstatic void 542223280Srmacklemdtnfsclient_load(void *dummy) 543223280Srmacklem{ 544223280Srmacklem 545223280Srmacklem if (dtrace_register("nfscl", &dtnfsclient_attr, 546223280Srmacklem DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL, 547223280Srmacklem &dtnfsclient_id) != 0) 548223280Srmacklem return; 549223280Srmacklem 550223280Srmacklem dtrace_nfscl_nfs234_start_probe = 551223280Srmacklem (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe; 552223280Srmacklem dtrace_nfscl_nfs234_done_probe = 553223280Srmacklem (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe; 554223280Srmacklem} 555223280Srmacklem 556223280Srmacklem 557223280Srmacklemstatic int 558223280Srmacklemdtnfsclient_unload() 559223280Srmacklem{ 560223280Srmacklem 561223280Srmacklem dtrace_nfscl_nfs234_start_probe = NULL; 562223280Srmacklem dtrace_nfscl_nfs234_done_probe = NULL; 563223280Srmacklem 564223280Srmacklem return (dtrace_unregister(dtnfsclient_id)); 565223280Srmacklem} 566223280Srmacklem 567223280Srmacklemstatic int 568223280Srmacklemdtnfsclient_modevent(module_t mod __unused, int type, void *data __unused) 569223280Srmacklem{ 570223280Srmacklem int error = 0; 571223280Srmacklem 572223280Srmacklem switch (type) { 573223280Srmacklem case MOD_LOAD: 574223280Srmacklem break; 575223280Srmacklem 576223280Srmacklem case MOD_UNLOAD: 577223280Srmacklem break; 578223280Srmacklem 579223280Srmacklem case MOD_SHUTDOWN: 580223280Srmacklem break; 581223280Srmacklem 582223280Srmacklem default: 583223280Srmacklem error = EOPNOTSUPP; 584223280Srmacklem break; 585223280Srmacklem } 586223280Srmacklem 587223280Srmacklem return (error); 588223280Srmacklem} 589223280Srmacklem 590223280SrmacklemSYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 591223280Srmacklem dtnfsclient_load, NULL); 592223280SrmacklemSYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, 593223280Srmacklem dtnfsclient_unload, NULL); 594223280Srmacklem 595223280SrmacklemDEV_MODULE(dtnfscl, dtnfsclient_modevent, NULL); 596223280SrmacklemMODULE_VERSION(dtnfscl, 1); 597223280SrmacklemMODULE_DEPEND(dtnfscl, dtrace, 1, 1, 1); 598223280SrmacklemMODULE_DEPEND(dtnfscl, opensolaris, 1, 1, 1); 599223280SrmacklemMODULE_DEPEND(dtnfscl, nfscl, 1, 1, 1); 600223280SrmacklemMODULE_DEPEND(dtnfscl, nfscommon, 1, 1, 1); 601