From owner-svn-src-head@FreeBSD.ORG Tue Mar 24 17:14:34 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9ECE71065B09; Tue, 24 Mar 2009 17:14:34 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 88E298FC13; Tue, 24 Mar 2009 17:14:34 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2OHEYpB051787; Tue, 24 Mar 2009 17:14:34 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2OHEYnX051781; Tue, 24 Mar 2009 17:14:34 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200903241714.n2OHEYnX051781@svn.freebsd.org> From: Robert Watson Date: Tue, 24 Mar 2009 17:14:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r190380 - in head/sys: cddl/dev/dtnfsclient nfsclient sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 Mar 2009 17:14:37 -0000 Author: rwatson Date: Tue Mar 24 17:14:34 2009 New Revision: 190380 URL: http://svn.freebsd.org/changeset/base/190380 Log: Add DTrace probes to the NFS access and attribute caches. Access cache events are: nfsclient:accesscache:flush:done nfsclient:accesscache:get:hit nfsclient:accesscache:get:miss nfsclient:accesscache:load:done They pass the vnode, uid, and requested or loaded access mode (if any); the load event may also report a load error if the RPC fails. The attribute cache events are: nfsclient:attrcache:flush:done nfsclient:attrcache:get:hit nfsclient:attrcache:get:miss nfsclient:attrcache:load:done They pass the vnode, optionally the vattr if one is present (hit or load), and in the case of a load event, also a possible RPC error. MFC after: 1 month Sponsored by: Google, Inc. Added: head/sys/nfsclient/nfs_kdtrace.h (contents, props changed) Modified: head/sys/cddl/dev/dtnfsclient/dtnfsclient.c head/sys/nfsclient/nfs_bio.c head/sys/nfsclient/nfs_subs.c head/sys/nfsclient/nfs_vnops.c head/sys/sys/dtrace_bsd.h Modified: head/sys/cddl/dev/dtnfsclient/dtnfsclient.c ============================================================================== --- head/sys/cddl/dev/dtnfsclient/dtnfsclient.c Tue Mar 24 17:10:42 2009 (r190379) +++ head/sys/cddl/dev/dtnfsclient/dtnfsclient.c Tue Mar 24 17:14:34 2009 (r190380) @@ -44,11 +44,13 @@ __FBSDID("$FreeBSD$"); /* * dtnfsclient is a DTrace provider that tracks the intent to perform RPCs - * in the NFS client. This is not quite the same as RPCs, because NFS may + * in the NFS client, as well as acess to and maintenance of the access and + * attribute caches. This is not quite the same as RPCs, because NFS may * issue multiple RPC transactions in the event that authentication fails, - * there's a jukebox error, etc. However, it cleanly represents the logical - * layer between RPC transmission and vnode/vfs operations, providing access - * to state linking the two. + * there's a jukebox error, or none at all if the access or attribute cache + * hits. However, it cleanly represents the logical layer between RPC + * transmission and vnode/vfs operations, providing access to state linking + * the two. */ static int dtnfsclient_unload(void); @@ -68,6 +70,9 @@ static dtrace_pattr_t dtnfsclient_attr = { DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON }, }; +/* + * Descrition of NFSv3 and (optional) NFSv2 probes for a procedure. + */ struct dtnfsclient_rpc { char *nr_v3_name; char *nr_v2_name; /* Or NULL if none. */ @@ -109,11 +114,28 @@ static struct dtnfsclient_rpc dtnfsclien { "noop" }, }; -static char *dtnfsclient_v2modulename = "nfs2"; -static char *dtnfsclient_v3modulename = "nfs3"; +/* + * Module name strings. + */ +static char *dtnfsclient_accesscache_str = "accesscache"; +static char *dtnfsclient_attrcache_str = "attrcache"; +static char *dtnfsclient_nfs2_str = "nfs2"; +static char *dtnfsclient_nfs3_str = "nfs3"; + +/* + * Function name strings. + */ +static char *dtnfsclient_flush_str = "flush"; +static char *dtnfsclient_load_str = "load"; +static char *dtnfsclient_get_str = "get"; -static char *dtnfsclient_start = "start"; -static char *dtnfsclient_done = "done"; +/* + * Name strings. + */ +static char *dtnfsclient_done_str = "done"; +static char *dtnfsclient_hit_str = "hit"; +static char *dtnfsclient_miss_str = "miss"; +static char *dtnfsclient_start_str = "start"; static dtrace_pops_t dtnfsclient_pops = { dtnfsclient_provide, @@ -131,7 +153,22 @@ static dtrace_pops_t dtnfsclient_pops = static dtrace_provider_id_t dtnfsclient_id; /* - * When tracing on a procedure is enabled, the DTrace ID for the event is + * Most probes are generated from the above RPC table, but for access and + * attribute caches, we have specific IDs we recognize and handle specially + * in various spots. + */ +extern uint32_t nfsclient_accesscache_flush_done_id; +extern uint32_t nfsclient_accesscache_get_hit_id; +extern uint32_t nfsclient_accesscache_get_miss_id; +extern uint32_t nfsclient_accesscache_load_done_id; + +extern uint32_t nfsclient_attrcache_flush_done_id; +extern uint32_t nfsclient_attrcache_get_hit_id; +extern uint32_t nfsclient_attrcache_get_miss_id; +extern uint32_t nfsclient_attrcache_load_done_id; + +/* + * When tracing on a procedure is enabled, the DTrace ID for an RPC event is * stored in one of these two NFS client-allocated arrays; 0 indicates that * the event is not being traced so probes should not be called. * @@ -167,28 +204,102 @@ dtnfsclient_getargdesc(void *arg, dtrace { const char *p = NULL; - switch (desc->dtargd_ndx) { - case 0: - p = "struct vnode *"; - break; - case 1: - p = "struct mbuf *"; - break; - case 2: - p = "struct ucred *"; - break; - case 3: - p = "int"; - break; - case 4: - if (dtnfs23_isdoneprobe(id)) { + if (id == nfsclient_accesscache_flush_done_id || + id == nfsclient_attrcache_flush_done_id || + id == nfsclient_attrcache_get_miss_id) { + switch (desc->dtargd_ndx) { + case 0: + p = "struct vnode *"; + break; + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + break; + } + } else if (id == nfsclient_accesscache_get_hit_id || + id == nfsclient_accesscache_get_miss_id) { + switch (desc->dtargd_ndx) { + case 0: + p = "struct vnode *"; + break; + case 1: + p = "uid_t"; + break; + case 2: + p = "uint32_t"; + break; + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + break; + } + } else if (id == nfsclient_accesscache_load_done_id) { + switch (desc->dtargd_ndx) { + case 0: + p = "struct vnode *"; + break; + case 1: + p = "uid_t"; + break; + case 2: + p = "uint32_t"; + break; + case 3: p = "int"; break; + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + break; + } + } else if (id == nfsclient_attrcache_get_hit_id) { + switch (desc->dtargd_ndx) { + case 0: + p = "struct vnode *"; + break; + case 1: + p = "struct vattr *"; + break; + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + break; + } + } else if (id == nfsclient_attrcache_load_done_id) { + switch (desc->dtargd_ndx) { + case 0: + p = "struct vnode *"; + break; + case 1: + p = "struct vattr *"; + break; + case 2: + p = "int"; + break; + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + break; + } + } else { + switch (desc->dtargd_ndx) { + case 0: + p = "struct vnode *"; + break; + case 1: + p = "struct mbuf *"; + break; + case 2: + p = "struct ucred *"; + break; + case 3: + p = "int"; + break; + case 4: + if (dtnfs23_isdoneprobe(id)) { + p = "int"; + break; + } + /* FALLSTHROUGH */ + default: + desc->dtargd_ndx = DTRACE_ARGNONE; + break; } - /* FALLSTHROUGH */ - default: - desc->dtargd_ndx = DTRACE_ARGNONE; - break; } if (p != NULL) strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native)); @@ -203,56 +314,112 @@ dtnfsclient_provide(void *arg, dtrace_pr return; /* - * First, register NFSv2 RPC procedures; note sparseness check for - * each slot in the NFSv3 procnum-indexed array. + * Register access cache probes. + */ + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_flush_str, dtnfsclient_done_str) == 0) { + nfsclient_accesscache_flush_done_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL); + } + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_get_str, dtnfsclient_hit_str) == 0) { + nfsclient_accesscache_get_hit_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL); + } + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_get_str, dtnfsclient_miss_str) == 0) { + nfsclient_accesscache_get_miss_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL); + } + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_load_str, dtnfsclient_done_str) == 0) { + nfsclient_accesscache_load_done_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_accesscache_str, + dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL); + } + + /* + * Register attribute cache probes. + */ + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_flush_str, dtnfsclient_done_str) == 0) { + nfsclient_attrcache_flush_done_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL); + } + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_get_str, dtnfsclient_hit_str) == 0) { + nfsclient_attrcache_get_hit_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL); + } + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_get_str, dtnfsclient_miss_str) == 0) { + nfsclient_attrcache_get_miss_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL); + } + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_load_str, dtnfsclient_done_str) == 0) { + nfsclient_attrcache_load_done_id = dtrace_probe_create( + dtnfsclient_id, dtnfsclient_attrcache_str, + dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL); + } + + /* + * Register NFSv2 RPC procedures; note sparseness check for each slot + * in the NFSv3 procnum-indexed array. */ for (i = 0; i < NFS_NPROCS; i++) { if (dtnfsclient_rpcs[i].nr_v2_name != NULL && - dtrace_probe_lookup(dtnfsclient_id, - dtnfsclient_v2modulename, dtnfsclient_rpcs[i].nr_v2_name, - dtnfsclient_start) == 0) { + dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str, + dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) == + 0) { dtnfsclient_rpcs[i].nr_v2_id_start = dtrace_probe_create(dtnfsclient_id, - dtnfsclient_v2modulename, + dtnfsclient_nfs2_str, dtnfsclient_rpcs[i].nr_v2_name, - dtnfsclient_start, 0, + dtnfsclient_start_str, 0, &nfsclient_nfs2_start_probes[i]); } if (dtnfsclient_rpcs[i].nr_v2_name != NULL && - dtrace_probe_lookup(dtnfsclient_id, - dtnfsclient_v2modulename, dtnfsclient_rpcs[i].nr_v2_name, - dtnfsclient_done) == 0) { + dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str, + dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) == + 0) { dtnfsclient_rpcs[i].nr_v2_id_done = dtrace_probe_create(dtnfsclient_id, - dtnfsclient_v2modulename, + dtnfsclient_nfs2_str, dtnfsclient_rpcs[i].nr_v2_name, - dtnfsclient_done, 0, + dtnfsclient_done_str, 0, &nfsclient_nfs2_done_probes[i]); } } /* - * Now, register NFSv3 RPC procedures. + * Register NFSv3 RPC procedures. */ for (i = 0; i < NFS_NPROCS; i++) { - if (dtrace_probe_lookup(dtnfsclient_id, - dtnfsclient_v3modulename, dtnfsclient_rpcs[i].nr_v3_name, - dtnfsclient_start) == 0) { + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str, + dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) == + 0) { dtnfsclient_rpcs[i].nr_v3_id_start = dtrace_probe_create(dtnfsclient_id, - dtnfsclient_v3modulename, + dtnfsclient_nfs3_str, dtnfsclient_rpcs[i].nr_v3_name, - dtnfsclient_start, 0, + dtnfsclient_start_str, 0, &nfsclient_nfs3_start_probes[i]); } - if (dtrace_probe_lookup(dtnfsclient_id, - dtnfsclient_v3modulename, dtnfsclient_rpcs[i].nr_v3_name, - dtnfsclient_done) == 0) { + if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str, + dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) == + 0) { dtnfsclient_rpcs[i].nr_v3_id_done = dtrace_probe_create(dtnfsclient_id, - dtnfsclient_v3modulename, + dtnfsclient_nfs3_str, dtnfsclient_rpcs[i].nr_v3_name, - dtnfsclient_done, 0, + dtnfsclient_done_str, 0, &nfsclient_nfs3_done_probes[i]); } } @@ -267,8 +434,26 @@ static void dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg) { uint32_t *p = parg; + void *f = dtrace_probe; - *p = id; + if (id == nfsclient_accesscache_flush_done_id) + dtrace_nfsclient_accesscache_flush_done_probe = f; + else if (id == nfsclient_accesscache_get_hit_id) + dtrace_nfsclient_accesscache_get_hit_probe = f; + else if (id == nfsclient_accesscache_get_miss_id) + dtrace_nfsclient_accesscache_get_miss_probe = f; + else if (id == nfsclient_accesscache_load_done_id) + dtrace_nfsclient_accesscache_load_done_probe = f; + else if (id == nfsclient_attrcache_flush_done_id) + dtrace_nfsclient_attrcache_flush_done_probe = f; + else if (id == nfsclient_attrcache_get_hit_id) + dtrace_nfsclient_attrcache_get_hit_probe = f; + else if (id == nfsclient_attrcache_get_miss_id) + dtrace_nfsclient_attrcache_get_miss_probe = f; + else if (id == nfsclient_attrcache_load_done_id) + dtrace_nfsclient_attrcache_load_done_probe = f; + else + *p = id; } static void @@ -276,7 +461,24 @@ dtnfsclient_disable(void *arg, dtrace_id { uint32_t *p = parg; - *p = 0; + if (id == nfsclient_accesscache_flush_done_id) + dtrace_nfsclient_accesscache_flush_done_probe = NULL; + else if (id == nfsclient_accesscache_get_hit_id) + dtrace_nfsclient_accesscache_get_hit_probe = NULL; + else if (id == nfsclient_accesscache_get_miss_id) + dtrace_nfsclient_accesscache_get_miss_probe = NULL; + else if (id == nfsclient_accesscache_load_done_id) + dtrace_nfsclient_accesscache_load_done_probe = NULL; + else if (id == nfsclient_attrcache_flush_done_id) + dtrace_nfsclient_attrcache_flush_done_probe = NULL; + else if (id == nfsclient_attrcache_get_hit_id) + dtrace_nfsclient_attrcache_get_hit_probe = NULL; + else if (id == nfsclient_attrcache_get_miss_id) + dtrace_nfsclient_attrcache_get_miss_probe = NULL; + else if (id == nfsclient_attrcache_load_done_id) + dtrace_nfsclient_attrcache_load_done_probe = NULL; + else + *p = 0; } static void Modified: head/sys/nfsclient/nfs_bio.c ============================================================================== --- head/sys/nfsclient/nfs_bio.c Tue Mar 24 17:10:42 2009 (r190379) +++ head/sys/nfsclient/nfs_bio.c Tue Mar 24 17:14:34 2009 (r190380) @@ -35,6 +35,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_kdtrace.h" + #include #include #include @@ -61,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -403,6 +406,7 @@ nfs_bioread_check_cons(struct vnode *vp, goto out; } np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); error = VOP_GETATTR(vp, &vattr, cred); if (error) goto out; @@ -915,6 +919,7 @@ nfs_write(struct vop_write_args *ap) #endif flush_and_restart: np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); error = nfs_vinvalbuf(vp, V_SAVE, td, 1); if (error) return (error); @@ -928,6 +933,7 @@ flush_and_restart: */ if (ioflag & IO_APPEND) { np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); error = VOP_GETATTR(vp, &vattr, cred); if (error) return (error); @@ -1756,6 +1762,7 @@ nfs_doio(struct vnode *vp, struct buf *b mtx_lock(&np->n_mtx); np->n_flag |= NWRITEERR; np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); mtx_unlock(&np->n_mtx); } bp->b_dirtyoff = bp->b_dirtyend = 0; Added: head/sys/nfsclient/nfs_kdtrace.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/nfsclient/nfs_kdtrace.h Tue Mar 24 17:14:34 2009 (r190380) @@ -0,0 +1,121 @@ +/*- + * Copyright (c) 2009 Robert N. M. Watson + * All rights reserved. + * + * This software was developed at the University of Cambridge Computer + * Laboratory with support from a grant from Google, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NFSCLIENT_NFS_KDTRACE_H_ +#define _NFSCLIENT_NFS_KDTRACE_H_ + +#ifdef KDTRACE_HOOKS +#include + +/* + * Definitions for NFS access cache probes. + */ +extern uint32_t nfsclient_accesscache_flush_done_id; +extern uint32_t nfsclient_accesscache_get_hit_id; +extern uint32_t nfsclient_accesscache_get_miss_id; +extern uint32_t nfsclient_accesscache_load_done_id; + +#define KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp) do { \ + if (dtrace_nfsclient_accesscache_flush_done_probe != NULL) \ + (dtrace_nfsclient_accesscache_flush_done_probe)( \ + nfsclient_accesscache_flush_done_id, (vp)); \ +} while (0) + +#define KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, uid, mode) do { \ + if (dtrace_nfsclient_accesscache_get_hit_probe != NULL) \ + (dtrace_nfsclient_accesscache_get_hit_probe)( \ + nfsclient_accesscache_get_hit_id, (vp), (uid), \ + (mode)); \ +} while (0) + +#define KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, uid, mode) do { \ + if (dtrace_nfsclient_accesscache_get_miss_probe != NULL) \ + (dtrace_nfsclient_accesscache_get_miss_probe)( \ + nfsclient_accesscache_get_miss_id, (vp), (uid), \ + (mode)); \ +} while (0) + +#define KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, uid, rmode, error) do { \ + if (error && dtrace_nfsclient_accesscache_load_done_probe != \ + NULL) \ + (dtrace_nfsclient_accesscache_load_done_probe)( \ + nfsclient_accesscache_load_done_id, (vp), (uid), \ + (rmode), (error)); \ +} while (0) + +/* + * Definitions for NFS attribute cache probes. + */ +extern uint32_t nfsclient_attrcache_flush_done_id; +extern uint32_t nfsclient_attrcache_get_hit_id; +extern uint32_t nfsclient_attrcache_get_miss_id; +extern uint32_t nfsclient_attrcache_load_done_id; + +#define KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp) do { \ + if (dtrace_nfsclient_attrcache_flush_done_probe != NULL) \ + (dtrace_nfsclient_attrcache_flush_done_probe)( \ + nfsclient_attrcache_flush_done_id, (vp)); \ +} while (0) + +#define KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap) do { \ + if (dtrace_nfsclient_attrcache_get_hit_probe != NULL) \ + (dtrace_nfsclient_attrcache_get_hit_probe)( \ + nfsclient_attrcache_get_hit_id, (vp), (vap)); \ +} while (0) + +#define KDTRACE_NFS_ATTRCACHE_GET_MISS(vp) do { \ + if (dtrace_nfsclient_attrcache_get_miss_probe != NULL) \ + (dtrace_nfsclient_attrcache_get_miss_probe)( \ + nfsclient_attrcache_get_miss_id, (vp)); \ +} while (0) + +#define KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error) do { \ + if (dtrace_nfsclient_attrcache_load_done_probe != NULL) \ + (dtrace_nfsclient_attrcache_load_done_probe)( \ + nfsclient_attrcache_load_done_id, (vp), (vap), \ + (error)); \ +} while (0) + +#else /* !KDTRACE_HOOKS */ + +#define KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp) +#define KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, uid, mode) +#define KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, uid, mode) +#define KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, uid, rmode, error) + +#define KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp) +#define KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap) +#define KDTRACE_NFS_ATTRCACHE_GET_MISS(vp) +#define KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error) + +#endif /* KDTRACE_HOOKS */ + +#endif /* !_NFSCLIENT_NFS_KDTRACE_H_ */ Modified: head/sys/nfsclient/nfs_subs.c ============================================================================== --- head/sys/nfsclient/nfs_subs.c Tue Mar 24 17:10:42 2009 (r190379) +++ head/sys/nfsclient/nfs_subs.c Tue Mar 24 17:14:34 2009 (r190380) @@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$"); * copy data between mbuf chains and uio lists. */ +#include "opt_kdtrace.h" + #include #include #include @@ -69,6 +71,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -81,6 +84,24 @@ __FBSDID("$FreeBSD$"); */ #include +#ifdef KDTRACE_HOOKS +dtrace_nfsclient_attrcache_flush_probe_func_t + dtrace_nfsclient_attrcache_flush_done_probe; +uint32_t nfsclient_attrcache_flush_done_id; + +dtrace_nfsclient_attrcache_get_hit_probe_func_t + dtrace_nfsclient_attrcache_get_hit_probe; +uint32_t nfsclient_attrcache_get_hit_id; + +dtrace_nfsclient_attrcache_get_miss_probe_func_t + dtrace_nfsclient_attrcache_get_miss_probe; +uint32_t nfsclient_attrcache_get_miss_id; + +dtrace_nfsclient_attrcache_load_probe_func_t + dtrace_nfsclient_attrcache_load_done_probe; +uint32_t nfsclient_attrcache_load_done_id; +#endif /* !KDTRACE_HOOKS */ + /* * Data items converted to xdr at startup, since they are constant * This is kinda hokey, but may save a little time doing byte swaps @@ -556,7 +577,7 @@ nfs_loadattrcache(struct vnode **vpp, st struct vnode *vp = *vpp; struct vattr *vap; struct nfs_fattr *fp; - struct nfsnode *np; + struct nfsnode *np = NULL; int32_t t1; caddr_t cp2; int rdev; @@ -566,12 +587,15 @@ nfs_loadattrcache(struct vnode **vpp, st struct timespec mtime, mtime_save; int v3 = NFS_ISV3(vp); struct thread *td = curthread; + int error = 0; md = *mdp; t1 = (mtod(md, caddr_t) + md->m_len) - *dposp; cp2 = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, M_WAIT); - if (cp2 == NULL) - return EBADRPC; + if (cp2 == NULL) { + error = EBADRPC; + goto out; + } fp = (struct nfs_fattr *)cp2; if (v3) { vtyp = nfsv3tov_type(fp->fa_type); @@ -684,6 +708,7 @@ nfs_loadattrcache(struct vnode **vpp, st */ vap->va_size = np->n_size; np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); } else if (np->n_flag & NMODIFIED) { /* * We've modified the file: Use the larger @@ -716,9 +741,11 @@ nfs_loadattrcache(struct vnode **vpp, st * We detect this by for the mtime moving back. We invalidate the * attrcache when this happens. */ - if (timespeccmp(&mtime_save, &vap->va_mtime, >)) + if (timespeccmp(&mtime_save, &vap->va_mtime, >)) { /* Size changed or mtime went backwards */ np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); + } if (vaper != NULL) { bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap)); if (np->n_flag & NCHG) { @@ -729,7 +756,13 @@ nfs_loadattrcache(struct vnode **vpp, st } } mtx_unlock(&np->n_mtx); - return (0); +out: +#ifdef KDRACE_HOOKS + if (np != NULL) + KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, error == 0 ? &np->n_vattr + : NULL, error); +#endif + return (error); } #ifdef NFS_ACDEBUG @@ -794,7 +827,8 @@ nfs_getattrcache(struct vnode *vp, struc if ((time_second - np->n_attrstamp) >= timeo) { nfsstats.attrcache_misses++; mtx_unlock(&np->n_mtx); - return( ENOENT); + KDTRACE_NFS_ATTRCACHE_GET_MISS(vp); + return (ENOENT); } nfsstats.attrcache_hits++; if (vap->va_size != np->n_size) { @@ -823,6 +857,7 @@ nfs_getattrcache(struct vnode *vp, struc #ifdef NFS_ACDEBUG mtx_unlock(&Giant); /* nfs_printf() */ #endif + KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap); return (0); } Modified: head/sys/nfsclient/nfs_vnops.c ============================================================================== --- head/sys/nfsclient/nfs_vnops.c Tue Mar 24 17:10:42 2009 (r190379) +++ head/sys/nfsclient/nfs_vnops.c Tue Mar 24 17:14:34 2009 (r190380) @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); */ #include "opt_inet.h" +#include "opt_kdtrace.h" #include #include @@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -85,6 +87,26 @@ __FBSDID("$FreeBSD$"); #include #include +#include + +#ifdef KDTRACE_HOOKS +#include + +dtrace_nfsclient_accesscache_flush_probe_func_t + dtrace_nfsclient_accesscache_flush_done_probe; +uint32_t nfsclient_accesscache_flush_done_id; + +dtrace_nfsclient_accesscache_get_probe_func_t + dtrace_nfsclient_accesscache_get_hit_probe, + dtrace_nfsclient_accesscache_get_miss_probe; +uint32_t nfsclient_accesscache_get_hit_id; +uint32_t nfsclient_accesscache_get_miss_id; + +dtrace_nfsclient_accesscache_load_probe_func_t + dtrace_nfsclient_accesscache_load_done_probe; +uint32_t nfsclient_accesscache_load_done_id; +#endif /* !KDTRACE_HOOKS */ + /* Defs */ #define TRUE 1 #define FALSE 0 @@ -313,9 +335,11 @@ nfs3_access_otw(struct vnode *vp, int wm mtx_unlock(&np->n_mtx); if (retmode != NULL) *retmode = rmode; + KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, rmode, 0); } m_freem(mrep); nfsmout: + KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, 0, error); return (error); } @@ -401,6 +425,14 @@ nfs_access(struct vop_access_args *ap) } } mtx_unlock(&np->n_mtx); +#ifdef KDTRACE_HOOKS + if (gotahit) + KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, + ap->a_cred->cr_uid, mode); + else + KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, + ap->a_cred->cr_uid, mode); +#endif if (gotahit == 0) { /* * Either a no, or a don't know. Go to the wire. @@ -494,6 +526,7 @@ nfs_open(struct vop_open_args *ap) if (error == EINTR || error == EIO) return (error); np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); if (vp->v_type == VDIR) np->n_direofoffset = 0; error = VOP_GETATTR(vp, &vattr, ap->a_cred); @@ -510,6 +543,7 @@ nfs_open(struct vop_open_args *ap) td->td_proc == NULL || np->n_ac_ts_pid != td->td_proc->p_pid) { np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); } mtx_unlock(&np->n_mtx); error = VOP_GETATTR(vp, &vattr, ap->a_cred); @@ -868,6 +902,7 @@ nfs_setattrrpc(struct vnode *vp, struct for (i = 0; i < NFS_ACCESSCACHESIZE; i++) np->n_accesscache[i].stamp = 0; mtx_unlock(&np->n_mtx); + KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp); nfsm_wcc_data(vp, wccflag); } else nfsm_loadattr(vp, NULL); @@ -1421,8 +1456,10 @@ nfsmout: } mtx_lock(&(VTONFS(dvp))->n_mtx); VTONFS(dvp)->n_flag |= NMODIFIED; - if (!wccflag) + if (!wccflag) { VTONFS(dvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); + } mtx_unlock(&(VTONFS(dvp))->n_mtx); return (error); } @@ -1553,8 +1590,10 @@ nfsmout: } mtx_lock(&(VTONFS(dvp))->n_mtx); VTONFS(dvp)->n_flag |= NMODIFIED; - if (!wccflag) + if (!wccflag) { VTONFS(dvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); + } mtx_unlock(&(VTONFS(dvp))->n_mtx); return (error); } @@ -1618,6 +1657,7 @@ nfs_remove(struct vop_remove_args *ap) } else if (!np->n_sillyrename) error = nfs_sillyrename(dvp, vp, cnp); np->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); return (error); } @@ -1663,8 +1703,10 @@ nfs_removerpc(struct vnode *dvp, const c nfsmout: mtx_lock(&(VTONFS(dvp))->n_mtx); VTONFS(dvp)->n_flag |= NMODIFIED; - if (!wccflag) + if (!wccflag) { VTONFS(dvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); + } mtx_unlock(&(VTONFS(dvp))->n_mtx); return (error); } @@ -1809,10 +1851,14 @@ nfsmout: mtx_lock(&(VTONFS(tdvp))->n_mtx); VTONFS(tdvp)->n_flag |= NMODIFIED; mtx_unlock(&(VTONFS(tdvp))->n_mtx); - if (!fwccflag) + if (!fwccflag) { VTONFS(fdvp)->n_attrstamp = 0; - if (!twccflag) + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(fdvp); + } + if (!twccflag) { VTONFS(tdvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp); + } return (error); } @@ -1860,10 +1906,14 @@ nfsmout: mtx_lock(&(VTONFS(tdvp))->n_mtx); VTONFS(tdvp)->n_flag |= NMODIFIED; mtx_unlock(&(VTONFS(tdvp))->n_mtx); - if (!attrflag) + if (!attrflag) { VTONFS(vp)->n_attrstamp = 0; - if (!wccflag) + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); + } + if (!wccflag) { VTONFS(tdvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp); + } return (error); } @@ -1948,8 +1998,10 @@ nfsmout: mtx_lock(&(VTONFS(dvp))->n_mtx); VTONFS(dvp)->n_flag |= NMODIFIED; mtx_unlock(&(VTONFS(dvp))->n_mtx); - if (!wccflag) + if (!wccflag) { VTONFS(dvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); + } return (error); } @@ -2004,8 +2056,10 @@ nfsmout: mtx_lock(&(VTONFS(dvp))->n_mtx); VTONFS(dvp)->n_flag |= NMODIFIED; mtx_unlock(&(VTONFS(dvp))->n_mtx); - if (!wccflag) + if (!wccflag) { VTONFS(dvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); + } if (error == 0 && newvp == NULL) { error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, cnp->cn_thread, &np); @@ -2054,8 +2108,10 @@ nfsmout: mtx_lock(&(VTONFS(dvp))->n_mtx); VTONFS(dvp)->n_flag |= NMODIFIED; mtx_unlock(&(VTONFS(dvp))->n_mtx); - if (!wccflag) + if (!wccflag) { VTONFS(dvp)->n_attrstamp = 0; + KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); + } cache_purge(dvp); cache_purge(vp); /* Modified: head/sys/sys/dtrace_bsd.h ============================================================================== --- head/sys/sys/dtrace_bsd.h Tue Mar 24 17:10:42 2009 (r190379) +++ head/sys/sys/dtrace_bsd.h Tue Mar 24 17:14:34 2009 (r190380) @@ -35,6 +35,8 @@ struct mbuf; struct trapframe; struct thread; +struct vattr; +struct vnode; /* * Cyclic clock function type definition used to hook the cyclic @@ -94,14 +96,52 @@ typedef void (*dtrace_malloc_probe_func_ extern dtrace_malloc_probe_func_t dtrace_malloc_probe; -/* The dtnfsclient provider hooks into the NFS[23] client. */ -typedef void (*dtrace_nfsclient_nfs23_start_probe_func_t)(u_int32_t, - struct vnode *, struct mbuf *, struct ucred *, int); -typedef void (*dtrace_nfsclient_nfs23_done_probe_func_t)(u_int32_t, - struct vnode *, struct mbuf *, struct ucred *, int, int); +/* dtnfsclient NFSv3 access cache provider hooks. */ +typedef void (*dtrace_nfsclient_accesscache_flush_probe_func_t)(uint32_t, + struct vnode *); +extern dtrace_nfsclient_accesscache_flush_probe_func_t + dtrace_nfsclient_accesscache_flush_done_probe; + +typedef void (*dtrace_nfsclient_accesscache_get_probe_func_t)(uint32_t, + struct vnode *, uid_t, uint32_t); +extern dtrace_nfsclient_accesscache_get_probe_func_t + dtrace_nfsclient_accesscache_get_hit_probe, + dtrace_nfsclient_accesscache_get_miss_probe; + +typedef void (*dtrace_nfsclient_accesscache_load_probe_func_t)(uint32_t, + struct vnode *, uid_t, uint32_t, int); +extern dtrace_nfsclient_accesscache_load_probe_func_t + dtrace_nfsclient_accesscache_load_done_probe; + +/* dtnfsclient NFSv[23] attribute cache provider hooks. */ +typedef void (*dtrace_nfsclient_attrcache_flush_probe_func_t)(uint32_t, + struct vnode *); +extern dtrace_nfsclient_attrcache_flush_probe_func_t + dtrace_nfsclient_attrcache_flush_done_probe; + +typedef void (*dtrace_nfsclient_attrcache_get_hit_probe_func_t)(uint32_t, + struct vnode *, struct vattr *); +extern dtrace_nfsclient_attrcache_get_hit_probe_func_t + dtrace_nfsclient_attrcache_get_hit_probe; + +typedef void (*dtrace_nfsclient_attrcache_get_miss_probe_func_t)(uint32_t, + struct vnode *); +extern dtrace_nfsclient_attrcache_get_miss_probe_func_t + dtrace_nfsclient_attrcache_get_miss_probe; + +typedef void (*dtrace_nfsclient_attrcache_load_probe_func_t)(uint32_t, + struct vnode *, struct vattr *, int); +extern dtrace_nfsclient_attrcache_load_probe_func_t + dtrace_nfsclient_attrcache_load_done_probe; +/* dtnfsclient NFSv[23] RPC provider hooks. */ +typedef void (*dtrace_nfsclient_nfs23_start_probe_func_t)(uint32_t, + struct vnode *, struct mbuf *, struct ucred *, int); extern dtrace_nfsclient_nfs23_start_probe_func_t dtrace_nfsclient_nfs23_start_probe; + +typedef void (*dtrace_nfsclient_nfs23_done_probe_func_t)(uint32_t, + struct vnode *, struct mbuf *, struct ucred *, int, int); extern dtrace_nfsclient_nfs23_done_probe_func_t dtrace_nfsclient_nfs23_done_probe;