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 <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_kdtrace.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bio.h>
@@ -61,6 +63,7 @@ __FBSDID("$FreeBSD$");
 #include <nfsclient/nfs.h>
 #include <nfsclient/nfsmount.h>
 #include <nfsclient/nfsnode.h>
+#include <nfsclient/nfs_kdtrace.h>
 
 #include <nfs4client/nfs4.h>
 
@@ -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 <sys/dtrace_bsd.h>
+
+/*
+ * 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 <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
@@ -69,6 +71,7 @@ __FBSDID("$FreeBSD$");
 #include <nfs/nfsproto.h>
 #include <nfsclient/nfs.h>
 #include <nfsclient/nfsnode.h>
+#include <nfsclient/nfs_kdtrace.h>
 #include <nfs/xdr_subs.h>
 #include <nfsclient/nfsm_subs.h>
 #include <nfsclient/nfsmount.h>
@@ -81,6 +84,24 @@ __FBSDID("$FreeBSD$");
  */
 #include <machine/stdarg.h>
 
+#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 <sys/param.h>
 #include <sys/kernel.h>
@@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$");
 #include <nfsclient/nfs.h>
 #include <nfsclient/nfsnode.h>
 #include <nfsclient/nfsmount.h>
+#include <nfsclient/nfs_kdtrace.h>
 #include <nfsclient/nfs_lock.h>
 #include <nfs/xdr_subs.h>
 #include <nfsclient/nfsm_subs.h>
@@ -85,6 +87,26 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in_var.h>
 #include <netinet/vinet.h>
 
+#include <machine/stdarg.h>
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+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;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to