PSARC 2008/050 DTrace NFS v3 Provider
authorahl
Wed, 06 Feb 2008 17:59:23 -0800
changeset 5982 6eafe3bf5f9e
parent 5981 5645812e651f
child 5983 f2e7d94698df
PSARC 2008/050 DTrace NFS v3 Provider 6660173 PSARC 2008/050 DTrace NFS v3 Provider 6660179 fix stability of NFS v4 provider
usr/src/cmd/dtrace/test/tst/common/Makefile
usr/src/cmd/dtrace/test/tst/common/nfs/tst.call3.c
usr/src/cmd/dtrace/test/tst/common/nfs/tst.call3.d
usr/src/lib/libdtrace/common/nfs.d
usr/src/pkgdefs/SUNWdtrt/prototype_com
usr/src/uts/common/dtrace/sdt_subr.c
usr/src/uts/common/fs/nfs/nfs3_srv.c
usr/src/uts/common/fs/nfs/nfs_server.c
usr/src/uts/common/sys/sdt.h
--- a/usr/src/cmd/dtrace/test/tst/common/Makefile	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/cmd/dtrace/test/tst/common/Makefile	Wed Feb 06 17:59:23 2008 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -34,6 +34,11 @@
 SNOOPSRCS = ${SNOOPOBJS:%.o=%.c}
 CLOBBERFILES += nfs/$(SNOOPOBJS)
 
+RPCSVCDIR = $(SRC)/head/rpcsvc
+RPCSVCOBJS = nfs_prot.o
+RPCSVCSRCS = ${RPCSVCOBJS:%o=%c}
+CLOBBERFILES += nfs/$(RPCSVCOBJS) $(RPCSVCDIR)/$(RPCSVCSRCS)
+
 fasttrap/tst.fasttrap.exe := LDLIBS += -ldtrace
 fasttrap/tst.stack.exe := LDLIBS += -ldtrace
 
@@ -52,6 +57,15 @@
 nfs/tst.call.exe: nfs/tst.call.o nfs/$(SNOOPOBJS)
 	$(LINK.c) -o $@ nfs/tst.call.o nfs/$(SNOOPOBJS) $(LDLIBS) -lnsl
 	$(POST_PROCESS) ; $(STRIP_STABS)
+$(RPCSVCDIR)/%.c: $(RPCSVCDIR)/%.x
+	$(RPCGEN) -Cc $< > $@
+nfs/$(RPCSVCOBJS): $(RPCSVCDIR)/$(RPCSVCSRCS)
+	$(COMPILE.c) -o $@ $(RPCSVCDIR)/$(RPCSVCSRCS)
+	$(POST_PROCESS_O)
+nfs/tst.call3.exe: nfs/tst.call3.o nfs/$(RPCSVCOBJS)
+	$(LINK.c) -o $@ nfs/tst.call3.o nfs/$(RPCSVCOBJS) \
+	$(LDLIBS) -lnsl -lrpcsvc
+	$(POST_PROCESS) ; $(STRIP_STABS)
 
 pid/tst.gcc.exe: pid/tst.gcc.c
 	$(GCC) -o pid/tst.gcc.exe pid/tst.gcc.c $(LDFLAGS)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/nfs/tst.call3.c	Wed Feb 06 17:59:23 2008 -0800
@@ -0,0 +1,441 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <strings.h>
+#include <rpc/rpc.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <rpcsvc/mount.h>
+
+#include "rpcsvc/nfs_prot.h"
+
+char sharedpath[MAXPATHLEN];
+fhandle3 *rootfh;
+
+/*
+ * The waiting() function returns the value passed in, until something
+ * external modifies it.  In this case, the D script tst.call.d will
+ * modify the value of *a, and thus break the while loop in dotest().
+ *
+ * This serves the purpose of not making the RPC calls until tst.call.d
+ * is active.  Thus, the probes in tst.call.d can fire as a result of
+ * the RPC call in dotest().
+ */
+
+int
+waiting(volatile int *a)
+{
+	return (*a);
+}
+
+static void
+getattr_arginit(void *argp)
+{
+	GETATTR3args *args = argp;
+
+	args->object.data.data_len = rootfh->fhandle3_len;
+	args->object.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+setattr_arginit(void *argp)
+{
+	SETATTR3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->object.data.data_len = rootfh->fhandle3_len;
+	args->object.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+lookup_arginit(void *argp)
+{
+	LOOKUP3args *args = argp;
+
+	args->what.name = "giant-skunk";
+	args->what.dir.data.data_len = rootfh->fhandle3_len;
+	args->what.dir.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+access_arginit(void *argp)
+{
+	ACCESS3args *args = argp;
+
+	args->object.data.data_len = rootfh->fhandle3_len;
+	args->object.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+commit_arginit(void *argp)
+{
+	COMMIT3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->file.data.data_len = rootfh->fhandle3_len;
+	args->file.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+create_arginit(void *argp)
+{
+	CREATE3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->where.name = "pinky-blue";
+	args->where.dir.data.data_len = rootfh->fhandle3_len;
+	args->where.dir.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+fsinfo_arginit(void *argp)
+{
+	FSINFO3args *args = argp;
+
+	args->fsroot.data.data_len = rootfh->fhandle3_len;
+	args->fsroot.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+fsstat_arginit(void *argp)
+{
+	FSSTAT3args *args = argp;
+
+	args->fsroot.data.data_len = rootfh->fhandle3_len;
+	args->fsroot.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+link_arginit(void *argp)
+{
+	LINK3args *args = argp;
+
+	args->file.data.data_len = rootfh->fhandle3_len;
+	args->file.data.data_val = rootfh->fhandle3_val;
+	args->link.dir.data.data_len = rootfh->fhandle3_len;
+	args->link.dir.data.data_val = rootfh->fhandle3_val;
+	args->link.name = "samf";
+}
+
+static void
+mkdir_arginit(void *argp)
+{
+	MKDIR3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->where.dir.data.data_len = rootfh->fhandle3_len;
+	args->where.dir.data.data_val = rootfh->fhandle3_val;
+	args->where.name = "cookie";
+}
+
+static void
+mknod_arginit(void *argp)
+{
+	MKNOD3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->where.dir.data.data_len = rootfh->fhandle3_len;
+	args->where.dir.data.data_val = rootfh->fhandle3_val;
+	args->where.name = "pookie";
+}
+
+static void
+null_arginit(void *argp)
+{
+}
+
+static void
+pathconf_arginit(void *argp)
+{
+	PATHCONF3args *args = argp;
+
+	args->object.data.data_len = rootfh->fhandle3_len;
+	args->object.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+read_arginit(void *argp)
+{
+	READ3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->file.data.data_len = rootfh->fhandle3_len;
+	args->file.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+readdir_arginit(void *argp)
+{
+	READDIR3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->dir.data.data_len = rootfh->fhandle3_len;
+	args->dir.data.data_val = rootfh->fhandle3_val;
+	args->count = 1024;
+}
+
+static void
+readdirplus_arginit(void *argp)
+{
+	READDIRPLUS3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->dir.data.data_len = rootfh->fhandle3_len;
+	args->dir.data.data_val = rootfh->fhandle3_val;
+	args->dircount = 1024;
+	args->maxcount = 1024;
+}
+
+static void
+readlink_arginit(void *argp)
+{
+	READLINK3args *args = argp;
+
+	args->symlink.data.data_len = rootfh->fhandle3_len;
+	args->symlink.data.data_val = rootfh->fhandle3_val;
+}
+
+static void
+remove_arginit(void *argp)
+{
+	REMOVE3args *args = argp;
+
+	args->object.dir.data.data_len = rootfh->fhandle3_len;
+	args->object.dir.data.data_val = rootfh->fhandle3_val;
+	args->object.name = "antelope";
+}
+
+static void
+rename_arginit(void *argp)
+{
+	RENAME3args *args = argp;
+
+	args->from.dir.data.data_len = rootfh->fhandle3_len;
+	args->from.dir.data.data_val = rootfh->fhandle3_val;
+	args->from.name = "walter";
+	args->to.dir.data.data_len = rootfh->fhandle3_len;
+	args->to.dir.data.data_val = rootfh->fhandle3_val;
+	args->to.name = "wendy";
+}
+
+static void
+rmdir_arginit(void *argp)
+{
+	RMDIR3args *args = argp;
+
+	args->object.dir.data.data_len = rootfh->fhandle3_len;
+	args->object.dir.data.data_val = rootfh->fhandle3_val;
+	args->object.name = "bunny";
+}
+
+static void
+symlink_arginit(void *argp)
+{
+	SYMLINK3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->where.dir.data.data_len = rootfh->fhandle3_len;
+	args->where.dir.data.data_val = rootfh->fhandle3_val;
+	args->where.name = "parlor";
+	args->symlink.symlink_data = "interior";
+}
+
+static void
+write_arginit(void *argp)
+{
+	WRITE3args *args = argp;
+
+	bzero(args, sizeof (*args));
+	args->file.data.data_len = rootfh->fhandle3_len;
+	args->file.data.data_val = rootfh->fhandle3_val;
+}
+
+typedef void (*call3_arginit_t)(void *);
+
+typedef struct {
+	call3_arginit_t arginit;
+	rpcproc_t proc;
+	xdrproc_t xdrargs;
+	size_t argsize;
+	xdrproc_t xdrres;
+	size_t ressize;
+} call3_test_t;
+call3_test_t call3_tests[] = {
+	{getattr_arginit, NFSPROC3_GETATTR, xdr_GETATTR3args,
+	    sizeof (GETATTR3args), xdr_GETATTR3res, sizeof (GETATTR3res)},
+	{setattr_arginit, NFSPROC3_SETATTR, xdr_SETATTR3args,
+	    sizeof (SETATTR3args), xdr_SETATTR3res, sizeof (SETATTR3res)},
+	{lookup_arginit, NFSPROC3_LOOKUP, xdr_LOOKUP3args,
+	    sizeof (LOOKUP3args), xdr_LOOKUP3res, sizeof (LOOKUP3res)},
+	{access_arginit, NFSPROC3_ACCESS, xdr_ACCESS3args,
+	    sizeof (ACCESS3args), xdr_ACCESS3res, sizeof (ACCESS3res)},
+	{commit_arginit, NFSPROC3_COMMIT, xdr_COMMIT3args,
+	    sizeof (COMMIT3args), xdr_COMMIT3res, sizeof (COMMIT3res)},
+	{create_arginit, NFSPROC3_CREATE, xdr_CREATE3args,
+	    sizeof (CREATE3args), xdr_CREATE3res, sizeof (CREATE3res)},
+	{fsinfo_arginit, NFSPROC3_FSINFO, xdr_FSINFO3args,
+	    sizeof (FSINFO3args), xdr_FSINFO3res, sizeof (FSINFO3res)},
+	{fsstat_arginit, NFSPROC3_FSSTAT, xdr_FSSTAT3args,
+	    sizeof (FSSTAT3args), xdr_FSSTAT3res, sizeof (FSSTAT3res)},
+	{link_arginit, NFSPROC3_LINK, xdr_LINK3args,
+	    sizeof (LINK3args), xdr_LINK3res, sizeof (LINK3res)},
+	{mkdir_arginit, NFSPROC3_MKDIR, xdr_MKDIR3args,
+	    sizeof (MKDIR3args), xdr_MKDIR3res, sizeof (MKDIR3res)},
+	{mknod_arginit, NFSPROC3_MKNOD, xdr_MKNOD3args,
+	    sizeof (MKNOD3args), xdr_MKNOD3res, sizeof (MKNOD3res)},
+	/*
+	 * NULL proc is special.  Rather than special case its zero-sized
+	 * args/results, we give it a small nonzero size, so as to not
+	 * make realloc() do the wrong thing.
+	 */
+	{null_arginit, NFSPROC3_NULL, xdr_void, sizeof (int), xdr_void,
+	    sizeof (int)},
+	{pathconf_arginit, NFSPROC3_PATHCONF, xdr_PATHCONF3args,
+	    sizeof (PATHCONF3args), xdr_PATHCONF3res, sizeof (PATHCONF3res)},
+	{read_arginit, NFSPROC3_READ, xdr_READ3args,
+	    sizeof (READ3args), xdr_READ3res, sizeof (READ3res)},
+	{readdir_arginit, NFSPROC3_READDIR, xdr_READDIR3args,
+	    sizeof (READDIR3args), xdr_READDIR3res, sizeof (READDIR3res)},
+	{readdirplus_arginit, NFSPROC3_READDIRPLUS, xdr_READDIRPLUS3args,
+	    sizeof (READDIRPLUS3args), xdr_READDIRPLUS3res,
+	    sizeof (READDIRPLUS3res)},
+	{readlink_arginit, NFSPROC3_READLINK, xdr_READLINK3args,
+	    sizeof (READLINK3args), xdr_READLINK3res, sizeof (READLINK3res)},
+	{remove_arginit, NFSPROC3_REMOVE, xdr_REMOVE3args,
+	    sizeof (REMOVE3args), xdr_REMOVE3res, sizeof (REMOVE3res)},
+	{rename_arginit, NFSPROC3_RENAME, xdr_RENAME3args,
+	    sizeof (RENAME3args), xdr_RENAME3res, sizeof (RENAME3res)},
+	{rmdir_arginit, NFSPROC3_RMDIR, xdr_RMDIR3args,
+	    sizeof (RMDIR3args), xdr_RMDIR3res, sizeof (RMDIR3res)},
+	{symlink_arginit, NFSPROC3_SYMLINK, xdr_SYMLINK3args,
+	    sizeof (SYMLINK3args), xdr_SYMLINK3res, sizeof (SYMLINK3res)},
+	{write_arginit, NFSPROC3_WRITE, xdr_WRITE3args,
+	    sizeof (WRITE3args), xdr_WRITE3res, sizeof (WRITE3res)},
+	{NULL}
+};
+
+int
+dotest(void)
+{
+	CLIENT *client, *mountclient;
+	AUTH *auth;
+	struct timeval timeout;
+	caddr_t args, res;
+	enum clnt_stat status;
+	rpcproc_t proc;
+	call3_test_t *test;
+	void *argbuf = NULL;
+	void *resbuf = NULL;
+	struct mountres3 mountres3;
+	char *sp;
+	volatile int a = 0;
+
+	while (waiting(&a) == 0)
+		continue;
+
+	timeout.tv_sec = 30;
+	timeout.tv_usec = 0;
+
+	mountclient = clnt_create("localhost", MOUNTPROG, MOUNTVERS3, "tcp");
+	if (mountclient == NULL) {
+		clnt_pcreateerror("clnt_create mount");
+		return (1);
+	}
+	auth = authsys_create_default();
+	mountclient->cl_auth = auth;
+	sp = sharedpath;
+	bzero(&mountres3, sizeof (mountres3));
+	status = clnt_call(mountclient, MOUNTPROC_MNT,
+	    xdr_dirpath, (char *)&sp,
+	    xdr_mountres3, (char *)&mountres3,
+	    timeout);
+	if (status != RPC_SUCCESS) {
+		clnt_perror(mountclient, "mnt");
+		return (1);
+	}
+	if (mountres3.fhs_status != 0) {
+		fprintf(stderr, "MOUNTPROG/MOUNTVERS3 failed %d\n",
+		    mountres3.fhs_status);
+		return (1);
+	}
+	rootfh = &mountres3.mountres3_u.mountinfo.fhandle;
+
+	client = clnt_create("localhost", NFS3_PROGRAM, NFS_V3, "tcp");
+	if (client == NULL) {
+		clnt_pcreateerror("clnt_create");
+		return (1);
+	}
+	client->cl_auth = auth;
+
+	for (test = call3_tests; test->arginit; ++test) {
+		argbuf = realloc(argbuf, test->argsize);
+		resbuf = realloc(resbuf, test->ressize);
+		if ((argbuf == NULL) || (resbuf == NULL)) {
+			perror("realloc() failed");
+			return (1);
+		}
+		(test->arginit)(argbuf);
+		bzero(resbuf, test->ressize);
+		status = clnt_call(client, test->proc,
+		    test->xdrargs, argbuf,
+		    test->xdrres, resbuf,
+		    timeout);
+		if (status != RPC_SUCCESS)
+			clnt_perror(client, "call");
+	}
+
+	status = clnt_call(mountclient, MOUNTPROC_UMNT,
+	    xdr_dirpath, (char *)&sp,
+	    xdr_void, NULL,
+	    timeout);
+	if (status != RPC_SUCCESS)
+		clnt_perror(mountclient, "umnt");
+
+	return (0);
+}
+
+/*ARGSUSED*/
+int
+main(int argc, char **argv)
+{
+	char shareline[BUFSIZ], unshareline[BUFSIZ];
+	int rc;
+
+	(void) snprintf(sharedpath, sizeof (sharedpath),
+	    "/tmp/nfsv3test.%d", getpid());
+	(void) snprintf(shareline, sizeof (shareline),
+	    "mkdir %s ; share %s", sharedpath, sharedpath);
+	(void) snprintf(unshareline, sizeof (unshareline),
+	    "unshare %s ; rmdir %s", sharedpath, sharedpath);
+
+	(void) system(shareline);
+	rc = dotest();
+	(void) system(unshareline);
+
+	return (rc);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/nfs/tst.call3.d	Wed Feb 06 17:59:23 2008 -0800
@@ -0,0 +1,91 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+/*
+ * ASSERTION: Make sure nfsv3 provider probes are firing, and that the
+ * arguments are properly visible.
+ *
+ * SECTION: nfs3 provider
+ */
+
+#pragma D option destructive
+#pragma D option quiet
+
+pid$1:a.out:waiting:entry
+{
+	this->value = (int *)alloca(sizeof (int));
+	*this->value = 1;
+	copyout(this->value, arg0, sizeof (int));
+}
+
+nfsv3:::op-getattr-start
+{
+	printf("ci_local: %s\n", args[0]->ci_local);
+	printf("ci_remote: %s\n", args[0]->ci_remote);
+	printf("ci_protocol: %s\n", args[0]->ci_protocol);
+
+	printf("noi_xid: %d\n", args[1]->noi_xid);
+	printf("noi_cred->cr_uid: %d\n", args[1]->noi_cred->cr_uid);
+	printf("noi_curpath: %s\n", args[1]->noi_curpath);
+
+	printf("fh3_flags: %d\n", args[2]->object.fh3_flags);
+}
+
+nfsv3:::op-getattr-done
+{
+	printf("ci_local: %s\n", args[0]->ci_local);
+	printf("ci_remote: %s\n", args[0]->ci_remote);
+	printf("ci_protocol: %s\n", args[0]->ci_protocol);
+
+	printf("noi_xid: %d\n", args[1]->noi_xid);
+	printf("noi_cred->cr_uid: %d\n", args[1]->noi_cred->cr_uid);
+	printf("noi_curpath: %s\n", args[1]->noi_curpath);
+
+	printf("status: %d\n", args[2]->status);
+}
+
+nfsv3:::*-done
+/seen[probename] == 0/
+{
+	++numberseen;
+	seen[probename] = 1;
+	printf("%d ops seen, latest op is %s\n", numberseen, probename);
+}
+
+nfsv3:::*-done
+/numberseen == 22/
+{
+	exit(0);
+}
+
+tick-1s
+/tick++ == 10/
+{
+	printf("%d nfsv3 ops seen; should be 22\n", numberseen);
+	exit(1);
+}
--- a/usr/src/lib/libdtrace/common/nfs.d	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/lib/libdtrace/common/nfs.d	Wed Feb 06 17:59:23 2008 -0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -90,3 +90,19 @@
 	nci_curpath = (P->finfo->vp == NULL) ? "<unknown>" :
 	    P->finfo->vp->v_path;
 };
+
+typedef struct nfsv3opinfo {
+	uint64_t noi_xid;	/* unique transation ID */
+	cred_t *noi_cred;	/* credentials for operation */
+	string noi_curpath;	/* current file handle path (if any) */
+} nfsv3opinfo_t;
+
+typedef struct nfsv3oparg nfsv3oparg_t;
+
+#pragma D binding "1.5" translator
+translator nfsv3opinfo_t < nfsv3oparg_t *P > {
+	noi_xid = ((struct svc_req *)arg0)->rq_xprt->xp_xid;
+	noi_cred = (cred_t *)arg1;
+	noi_curpath = (arg2 == 0 || ((vnode_t *)arg2)->v_path == NULL) ?
+	    "<unknown>" : ((vnode_t *)arg2)->v_path;
+};
--- a/usr/src/pkgdefs/SUNWdtrt/prototype_com	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/pkgdefs/SUNWdtrt/prototype_com	Wed Feb 06 17:59:23 2008 -0800
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -630,6 +630,8 @@
 d none SUNWdtrt/tst/common/nfs 0755 root bin
 f none SUNWdtrt/tst/common/nfs/tst.call.d 0444 root bin
 f none SUNWdtrt/tst/common/nfs/tst.call.exe 0555 root bin
+f none SUNWdtrt/tst/common/nfs/tst.call3.d 0444 root bin
+f none SUNWdtrt/tst/common/nfs/tst.call3.exe 0555 root bin
 d none SUNWdtrt/tst/common/offsetof 0755 root bin
 f none SUNWdtrt/tst/common/offsetof/err.D_OFFSETOF_BITFIELD.bitfield.d 0444 root bin
 f none SUNWdtrt/tst/common/offsetof/err.D_OFFSETOF_TYPE.badtype.d 0444 root bin
--- a/usr/src/uts/common/dtrace/sdt_subr.c	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/uts/common/dtrace/sdt_subr.c	Wed Feb 06 17:59:23 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -59,14 +59,6 @@
 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
 };
 
-static dtrace_pattr_t nfsv4_attr = {
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-};
-
 static dtrace_pattr_t stab_attr = {
 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
@@ -101,7 +93,8 @@
 	{ "io", "__io_", &stab_attr, 0 },
 	{ "mib", "__mib_", &stab_attr, 0 },
 	{ "fsinfo", "__fsinfo_", &fsinfo_attr, 0 },
-	{ "nfsv4", "__nfsv4_", &nfsv4_attr, 0 },
+	{ "nfsv3", "__nfsv3_", &stab_attr, 0 },
+	{ "nfsv4", "__nfsv4_", &stab_attr, 0 },
 	{ "xpv", "__xpv_", &xpv_attr, 0 },
 	{ "sysevent", "__sysevent_", &stab_attr, 0 },
 	{ "sdt", NULL, &sdt_attr, 0 },
@@ -176,6 +169,235 @@
 	{ "fsinfo", NULL, 0, 0, "vnode_t *", "fileinfo_t *" },
 	{ "fsinfo", NULL, 1, 1, "int", "int" },
 
+	{ "nfsv3", "op-getattr-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-getattr-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-getattr-start", 2, 3, "GETATTR3args *" },
+	{ "nfsv3", "op-getattr-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-getattr-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-getattr-done", 2, 3, "GETATTR3res *" },
+	{ "nfsv3", "op-setattr-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-setattr-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-setattr-start", 2, 3, "SETATTR3args *" },
+	{ "nfsv3", "op-setattr-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-setattr-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-setattr-done", 2, 3, "SETATTR3res *" },
+	{ "nfsv3", "op-lookup-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-lookup-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-lookup-start", 2, 3, "LOOKUP3args *" },
+	{ "nfsv3", "op-lookup-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-lookup-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-lookup-done", 2, 3, "LOOKUP3res *" },
+	{ "nfsv3", "op-access-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-access-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-access-start", 2, 3, "ACCESS3args *" },
+	{ "nfsv3", "op-access-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-access-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-access-done", 2, 3, "ACCESS3res *" },
+	{ "nfsv3", "op-commit-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-commit-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-commit-start", 2, 3, "COMMIT3args *" },
+	{ "nfsv3", "op-commit-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-commit-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-commit-done", 2, 3, "COMMIT3res *" },
+	{ "nfsv3", "op-create-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-create-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-create-start", 2, 3, "CREATE3args *" },
+	{ "nfsv3", "op-create-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-create-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-create-done", 2, 3, "CREATE3res *" },
+	{ "nfsv3", "op-fsinfo-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-fsinfo-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-fsinfo-start", 2, 3, "FSINFO3args *" },
+	{ "nfsv3", "op-fsinfo-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-fsinfo-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-fsinfo-done", 2, 3, "FSINFO3res *" },
+	{ "nfsv3", "op-fsstat-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-fsstat-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-fsstat-start", 2, 3, "FSSTAT3args *" },
+	{ "nfsv3", "op-fsstat-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-fsstat-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-fsstat-done", 2, 3, "FSSTAT3res *" },
+	{ "nfsv3", "op-link-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-link-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-link-start", 2, 3, "LINK3args *" },
+	{ "nfsv3", "op-link-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-link-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-link-done", 2, 3, "LINK3res *" },
+	{ "nfsv3", "op-mkdir-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-mkdir-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-mkdir-start", 2, 3, "MKDIR3args *" },
+	{ "nfsv3", "op-mkdir-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-mkdir-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-mkdir-done", 2, 3, "MKDIR3res *" },
+	{ "nfsv3", "op-mknod-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-mknod-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-mknod-start", 2, 3, "MKNOD3args *" },
+	{ "nfsv3", "op-mknod-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-mknod-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-mknod-done", 2, 3, "MKNOD3res *" },
+	{ "nfsv3", "op-null-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-null-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-null-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-null-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-pathconf-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-pathconf-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-pathconf-start", 2, 3, "PATHCONF3args *" },
+	{ "nfsv3", "op-pathconf-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-pathconf-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-pathconf-done", 2, 3, "PATHCONF3res *" },
+	{ "nfsv3", "op-read-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-read-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-read-start", 2, 3, "READ3args *" },
+	{ "nfsv3", "op-read-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-read-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-read-done", 2, 3, "READ3res *" },
+	{ "nfsv3", "op-readdir-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-readdir-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-readdir-start", 2, 3, "READDIR3args *" },
+	{ "nfsv3", "op-readdir-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-readdir-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-readdir-done", 2, 3, "READDIR3res *" },
+	{ "nfsv3", "op-readdirplus-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-readdirplus-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-readdirplus-start", 2, 3, "READDIRPLUS3args *" },
+	{ "nfsv3", "op-readdirplus-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-readdirplus-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-readdirplus-done", 2, 3, "READDIRPLUS3res *" },
+	{ "nfsv3", "op-readlink-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-readlink-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-readlink-start", 2, 3, "READLINK3args *" },
+	{ "nfsv3", "op-readlink-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-readlink-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-readlink-done", 2, 3, "READLINK3res *" },
+	{ "nfsv3", "op-remove-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-remove-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-remove-start", 2, 3, "REMOVE3args *" },
+	{ "nfsv3", "op-remove-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-remove-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-remove-done", 2, 3, "REMOVE3res *" },
+	{ "nfsv3", "op-rename-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-rename-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-rename-start", 2, 3, "RENAME3args *" },
+	{ "nfsv3", "op-rename-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-rename-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-rename-done", 2, 3, "RENAME3res *" },
+	{ "nfsv3", "op-rmdir-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-rmdir-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-rmdir-start", 2, 3, "RMDIR3args *" },
+	{ "nfsv3", "op-rmdir-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-rmdir-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-rmdir-done", 2, 3, "RMDIR3res *" },
+	{ "nfsv3", "op-setattr-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-setattr-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-setattr-start", 2, 3, "SETATTR3args *" },
+	{ "nfsv3", "op-setattr-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-setattr-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-setattr-done", 2, 3, "SETATTR3res *" },
+	{ "nfsv3", "op-symlink-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-symlink-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-symlink-start", 2, 3, "SYMLINK3args *" },
+	{ "nfsv3", "op-symlink-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-symlink-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-symlink-done", 2, 3, "SYMLINK3res *" },
+	{ "nfsv3", "op-write-start", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-write-start", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-write-start", 2, 3, "WRITE3args *" },
+	{ "nfsv3", "op-write-done", 0, 0, "struct svc_req *",
+	    "conninfo_t *" },
+	{ "nfsv3", "op-write-done", 1, 1, "nfsv3oparg_t *",
+	    "nfsv3opinfo_t *" },
+	{ "nfsv3", "op-write-done", 2, 3, "WRITE3res *" },
+
 	{ "nfsv4", "null-start", 0, 0, "struct svc_req *", "conninfo_t *" },
 	{ "nfsv4", "null-done", 0, 0, "struct svc_req *", "conninfo_t *" },
 	{ "nfsv4", "compound-start", 0, 0, "struct compound_state *",
--- a/usr/src/uts/common/fs/nfs/nfs3_srv.c	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs3_srv.c	Wed Feb 06 17:59:23 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -96,6 +96,10 @@
 	struct vattr va;
 
 	vp = nfs3_fhtovp(&args->object, exi);
+
+	DTRACE_NFSV3_4(op__getattr__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, GETATTR3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -104,14 +108,18 @@
 	va.va_mask = AT_ALL;
 	error = rfs4_delegated_getattr(vp, &va, 0, cr);
 
-	VN_RELE(vp);
-
 	if (!error) {
 		/* overflow error if time or size is out of range */
 		error = vattr_to_fattr3(&va, &resp->resok.obj_attributes);
 		if (error)
 			goto out;
 		resp->status = NFS3_OK;
+
+		DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
+		    cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
+
+		VN_RELE(vp);
+
 		return;
 	}
 
@@ -121,6 +129,12 @@
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
+
+	DTRACE_NFSV3_4(op__getattr__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, GETATTR3res *, resp);
+
+	if (vp != NULL)
+		VN_RELE(vp);
 }
 
 void *
@@ -149,6 +163,10 @@
 	avap = NULL;
 
 	vp = nfs3_fhtovp(&args->object, exi);
+
+	DTRACE_NFSV3_4(op__setattr__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, SETATTR3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -316,10 +334,15 @@
 
 	if (in_crit)
 		nbl_end_crit(vp);
-	VN_RELE(vp);
 
 	resp->status = NFS3_OK;
 	vattr_to_wcc_data(bvap, avap, &resp->resok.obj_wcc);
+
+	DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -329,6 +352,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__setattr__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, SETATTR3res *, resp);
+
 	if (vp != NULL) {
 		if (in_crit)
 			nbl_end_crit(vp);
@@ -369,8 +395,15 @@
 	if (exi != NULL && (exi->exi_export.ex_flags & EX_PUBLIC)) {
 		dvp = rootdir;
 		VN_HOLD(dvp);
+
+		DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
+		    cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
 	} else {
 		dvp = nfs3_fhtovp(&args->what.dir, exi);
+
+		DTRACE_NFSV3_4(op__lookup__start, struct svc_req *, req,
+		    cred_t *, cr, vnode_t *, dvp, LOOKUP3args *, args);
+
 		if (dvp == NULL) {
 			error = ESTALE;
 			goto out;
@@ -507,8 +540,6 @@
 	if (publicfh_flag)
 		exi_rele(exi);
 
-	VN_RELE(dvp);
-
 #ifdef DEBUG
 	if (rfs3_do_post_op_attr) {
 		va.va_mask = AT_ALL;
@@ -534,6 +565,10 @@
 	if (auth_weak)
 		resp->status = (enum nfsstat3)WNFSERR_CLNT_FLAVOR;
 
+	DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
+	VN_RELE(dvp);
+
 	return;
 
 out:
@@ -543,6 +578,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__lookup__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, LOOKUP3res *, resp);
+
 	if (dvp != NULL)
 		VN_RELE(dvp);
 	vattr_to_post_op_attr(dvap, &resp->resfail.dir_attributes);
@@ -573,6 +611,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->object, exi);
+
+	DTRACE_NFSV3_4(op__access__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, ACCESS3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -691,10 +733,14 @@
 	vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
 #endif
 
-	VN_RELE(vp);
-
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
+
+	DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -703,6 +749,8 @@
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
+	DTRACE_NFSV3_4(op__access__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, ACCESS3res *, resp);
 	if (vp != NULL)
 		VN_RELE(vp);
 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
@@ -731,6 +779,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->symlink, exi);
+
+	DTRACE_NFSV3_4(op__readlink__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READLINK3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -814,12 +866,15 @@
 		goto out;
 	}
 
-	VN_RELE(vp);
-
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.symlink_attributes);
 	resp->resok.data = data;
 	*(data + MAXPATHLEN - uio.uio_resid) = '\0';
+
+	DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -829,6 +884,8 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__readlink__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READLINK3res *, resp);
 	if (vp != NULL)
 		VN_RELE(vp);
 	vattr_to_post_op_attr(vap, &resp->resfail.symlink_attributes);
@@ -870,6 +927,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->file, exi);
+
+	DTRACE_NFSV3_4(op__read__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READ3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -962,7 +1023,6 @@
 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
 		if (in_crit)
 			nbl_end_crit(vp);
-		VN_RELE(vp);
 		resp->status = NFS3_OK;
 		vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
 		resp->resok.count = 0;
@@ -970,14 +1030,13 @@
 		resp->resok.data.data_len = 0;
 		resp->resok.data.data_val = NULL;
 		resp->resok.data.mp = NULL;
-		return;
+		goto done;
 	}
 
 	if (args->count == 0) {
 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
 		if (in_crit)
 			nbl_end_crit(vp);
-		VN_RELE(vp);
 		resp->status = NFS3_OK;
 		vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
 		resp->resok.count = 0;
@@ -985,7 +1044,7 @@
 		resp->resok.data.data_len = 0;
 		resp->resok.data.data_val = NULL;
 		resp->resok.data.mp = NULL;
-		return;
+		goto done;
 	}
 
 	/*
@@ -1061,7 +1120,6 @@
 
 	if (in_crit)
 		nbl_end_crit(vp);
-	VN_RELE(vp);
 
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
@@ -1076,6 +1134,13 @@
 	resp->resok.data.mp = mp;
 
 	resp->resok.size = (uint_t)args->count;
+
+done:
+	DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READ3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -1085,6 +1150,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__read__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READ3res *, resp);
+
 	if (vp != NULL) {
 		if (need_rwunlock)
 			VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, &ct);
@@ -1144,9 +1212,13 @@
 	caller_context_t ct;
 
 	vp = nfs3_fhtovp(&args->file, exi);
+
+	DTRACE_NFSV3_4(op__write__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, WRITE3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
-		goto out;
+		goto err;
 	}
 
 	if (is_system_labeled()) {
@@ -1159,7 +1231,7 @@
 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) {
 				resp->status = NFS3ERR_ACCES;
-				goto out1;
+				goto err1;
 			}
 		}
 	}
@@ -1179,7 +1251,7 @@
 		if (nbl_conflict(vp, NBL_WRITE, args->offset, args->count, 0,
 		    NULL)) {
 			error = EACCES;
-			goto out;
+			goto err;
 		}
 	}
 
@@ -1189,7 +1261,7 @@
 	if (rwlock_ret == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
 		resp->status = NFS3ERR_JUKEBOX;
 		rwlock_ret = -1;
-		goto out1;
+		goto err1;
 	}
 
 
@@ -1201,7 +1273,7 @@
 	 * right access checking.  So, we'll fail the request.
 	 */
 	if (error)
-		goto out;
+		goto err;
 
 	bvap = &bva;
 #ifdef DEBUG
@@ -1212,37 +1284,35 @@
 
 	if (args->count != args->data.data_len) {
 		resp->status = NFS3ERR_INVAL;
-		goto out1;
+		goto err1;
 	}
 
 	if (rdonly(exi, req)) {
 		resp->status = NFS3ERR_ROFS;
-		goto out1;
+		goto err1;
 	}
 
 	if (vp->v_type != VREG) {
 		resp->status = NFS3ERR_INVAL;
-		goto out1;
+		goto err1;
 	}
 
 	if (crgetuid(cr) != bva.va_uid &&
 	    (error = VOP_ACCESS(vp, VWRITE, 0, cr, &ct)))
-		goto out;
+		goto err;
 
 	if (MANDLOCK(vp, bva.va_mode)) {
 		resp->status = NFS3ERR_ACCES;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->count == 0) {
-		VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
-		VN_RELE(vp);
 		resp->status = NFS3_OK;
 		vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
 		resp->resok.count = 0;
 		resp->resok.committed = args->stable;
 		resp->resok.verf = write3verf;
-		return;
+		goto out;
 	}
 
 	if (args->mblk != NULL) {
@@ -1290,7 +1360,7 @@
 		if (iovp != iov)
 			kmem_free(iovp, sizeof (*iovp) * iovcnt);
 		resp->status = NFS3ERR_INVAL;
-		goto out1;
+		goto err1;
 	}
 
 	/*
@@ -1309,7 +1379,7 @@
 	/* check if a monitor detected a delegation conflict */
 	if (error == EAGAIN && (ct.cc_flags & CC_WOULDBLOCK)) {
 		resp->status = NFS3ERR_JUKEBOX;
-		goto out1;
+		goto err1;
 	}
 
 	ava.va_mask = AT_ALL;
@@ -1321,12 +1391,7 @@
 #endif
 
 	if (error)
-		goto out;
-
-	VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
-	if (in_crit)
-		nbl_end_crit(vp);
-	VN_RELE(vp);
+		goto err;
 
 	/*
 	 * If we were unable to get the V_WRITELOCK_TRUE, then we
@@ -1348,15 +1413,20 @@
 	resp->resok.count = args->count - uio.uio_resid;
 	resp->resok.committed = args->stable;
 	resp->resok.verf = write3verf;
-	return;
-
-out:
+	goto out;
+
+err:
 	if (curthread->t_flag & T_WOULDBLOCK) {
 		curthread->t_flag &= ~T_WOULDBLOCK;
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
-out1:
+err1:
+	vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
+out:
+	DTRACE_NFSV3_4(op__write__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, WRITE3res *, resp);
+
 	if (vp != NULL) {
 		if (rwlock_ret != -1)
 			VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, &ct);
@@ -1364,7 +1434,6 @@
 			nbl_end_crit(vp);
 		VN_RELE(vp);
 	}
-	vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
 }
 
 void *
@@ -1398,6 +1467,10 @@
 	davap = NULL;
 
 	dvp = nfs3_fhtovp(&args->where.dir, exi);
+
+	DTRACE_NFSV3_4(op__create__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, CREATE3args *, args);
+
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -1700,7 +1773,6 @@
 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
 
 	VN_RELE(vp);
-	VN_RELE(dvp);
 	if (tvp != NULL) {
 		if (in_crit)
 			nbl_end_crit(tvp);
@@ -1710,6 +1782,11 @@
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
+
+	DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
+
+	VN_RELE(dvp);
 	return;
 
 out:
@@ -1719,6 +1796,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__create__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, CREATE3res *, resp);
+
 	if (tvp != NULL) {
 		if (in_crit)
 			nbl_end_crit(tvp);
@@ -1754,6 +1834,10 @@
 	davap = NULL;
 
 	dvp = nfs3_fhtovp(&args->where.dir, exi);
+
+	DTRACE_NFSV3_4(op__mkdir__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, MKDIR3args *, args);
+
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -1834,8 +1918,6 @@
 	if (error)
 		goto out;
 
-	VN_RELE(dvp);
-
 #ifdef DEBUG
 	if (!rfs3_do_post_op_fh3)
 		resp->resok.obj.handle_follows = FALSE;
@@ -1871,6 +1953,11 @@
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
+
+	DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
+	VN_RELE(dvp);
+
 	return;
 
 out:
@@ -1880,6 +1967,8 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__mkdir__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, MKDIR3res *, resp);
 	if (dvp != NULL)
 		VN_RELE(dvp);
 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
@@ -1910,9 +1999,13 @@
 	davap = NULL;
 
 	dvp = nfs3_fhtovp(&args->where.dir, exi);
+
+	DTRACE_NFSV3_4(op__symlink__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, SYMLINK3args *, args);
+
 	if (dvp == NULL) {
 		error = ESTALE;
-		goto out;
+		goto err;
 	}
 
 #ifdef DEBUG
@@ -1929,17 +2022,17 @@
 
 	if (args->where.name == nfs3nametoolong) {
 		resp->status = NFS3ERR_NAMETOOLONG;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->where.name == NULL || *(args->where.name) == '\0') {
 		resp->status = NFS3ERR_ACCES;
-		goto out1;
+		goto err1;
 	}
 
 	if (rdonly(exi, req)) {
 		resp->status = NFS3ERR_ROFS;
-		goto out1;
+		goto err1;
 	}
 
 	if (is_system_labeled()) {
@@ -1952,23 +2045,23 @@
 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
 			if (!do_rfs_label_check(clabel, dvp, EQUALITY_CHECK)) {
 				resp->status = NFS3ERR_ACCES;
-				goto out1;
+				goto err1;
 			}
 		}
 	}
 
 	error = sattr3_to_vattr(&args->symlink.symlink_attributes, &va);
 	if (error)
-		goto out;
+		goto err;
 
 	if (!(va.va_mask & AT_MODE)) {
 		resp->status = NFS3ERR_INVAL;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->symlink.symlink_data == nfs3nametoolong) {
 		resp->status = NFS3ERR_NAMETOOLONG;
-		goto out1;
+		goto err1;
 	}
 
 	va.va_mask |= AT_TYPE;
@@ -1989,7 +2082,7 @@
 #endif
 
 	if (error)
-		goto out;
+		goto err;
 
 	error = VOP_LOOKUP(dvp, args->where.name, &vp, NULL, 0, NULL, cr,
 	    NULL, NULL, NULL);
@@ -1999,14 +2092,13 @@
 	 */
 	(void) VOP_FSYNC(dvp, 0, cr, NULL);
 
-	VN_RELE(dvp);
 
 	resp->status = NFS3_OK;
 	if (error) {
 		resp->resok.obj.handle_follows = FALSE;
 		vattr_to_post_op_attr(NULL, &resp->resok.obj_attributes);
 		vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
-		return;
+		goto out;
 	}
 
 #ifdef DEBUG
@@ -2043,18 +2135,22 @@
 
 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
-	return;
-
-out:
+	goto out;
+
+err:
 	if (curthread->t_flag & T_WOULDBLOCK) {
 		curthread->t_flag &= ~T_WOULDBLOCK;
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
-out1:
+err1:
+	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
+out:
+	DTRACE_NFSV3_4(op__symlink__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, SYMLINK3res *, resp);
+
 	if (dvp != NULL)
 		VN_RELE(dvp);
-	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
 }
 
 void *
@@ -2084,6 +2180,10 @@
 	davap = NULL;
 
 	dvp = nfs3_fhtovp(&args->where.dir, exi);
+
+	DTRACE_NFSV3_4(op__mknod__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, MKNOD3args *, args);
+
 	if (dvp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2206,8 +2306,6 @@
 	if (error)
 		goto out;
 
-	VN_RELE(dvp);
-
 	resp->status = NFS3_OK;
 
 #ifdef DEBUG
@@ -2244,6 +2342,9 @@
 
 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 	vattr_to_wcc_data(dbvap, davap, &resp->resok.dir_wcc);
+	DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
+	VN_RELE(dvp);
 	return;
 
 out:
@@ -2253,6 +2354,8 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__mknod__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, dvp, MKNOD3res *, resp);
 	if (dvp != NULL)
 		VN_RELE(dvp);
 	vattr_to_wcc_data(dbvap, davap, &resp->resfail.dir_wcc);
@@ -2281,9 +2384,13 @@
 	avap = NULL;
 
 	vp = nfs3_fhtovp(&args->object.dir, exi);
+
+	DTRACE_NFSV3_4(op__remove__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, REMOVE3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
-		goto out;
+		goto err;
 	}
 
 #ifdef DEBUG
@@ -2300,22 +2407,22 @@
 
 	if (vp->v_type != VDIR) {
 		resp->status = NFS3ERR_NOTDIR;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->object.name == nfs3nametoolong) {
 		resp->status = NFS3ERR_NAMETOOLONG;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->object.name == NULL || *(args->object.name) == '\0') {
 		resp->status = NFS3ERR_ACCES;
-		goto out1;
+		goto err1;
 	}
 
 	if (rdonly(exi, req)) {
 		resp->status = NFS3ERR_ROFS;
-		goto out1;
+		goto err1;
 	}
 
 	if (is_system_labeled()) {
@@ -2328,7 +2435,7 @@
 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) {
 				resp->status = NFS3ERR_ACCES;
-				goto out1;
+				goto err1;
 			}
 		}
 	}
@@ -2340,11 +2447,11 @@
 	error = VOP_LOOKUP(vp, args->object.name, &targvp, NULL, 0,
 	    NULL, cr, NULL, NULL, NULL);
 	if (error != 0)
-		goto out;
+		goto err;
 
 	if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
 		resp->status = NFS3ERR_JUKEBOX;
-		goto out1;
+		goto err1;
 	}
 
 	if (!nbl_need_check(targvp)) {
@@ -2378,24 +2485,25 @@
 	(void) VOP_FSYNC(vp, 0, cr, NULL);
 
 	if (error)
-		goto out;
-
-	VN_RELE(vp);
+		goto err;
 
 	resp->status = NFS3_OK;
 	vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
-	return;
-
-out:
+	goto out;
+
+err:
 	if (curthread->t_flag & T_WOULDBLOCK) {
 		curthread->t_flag &= ~T_WOULDBLOCK;
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
-out1:
+err1:
+	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
+out:
+	DTRACE_NFSV3_4(op__remove__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, REMOVE3res *, resp);
 	if (vp != NULL)
 		VN_RELE(vp);
-	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
 }
 
 void *
@@ -2420,9 +2528,13 @@
 	avap = NULL;
 
 	vp = nfs3_fhtovp(&args->object.dir, exi);
+
+	DTRACE_NFSV3_4(op__rmdir__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, RMDIR3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
-		goto out;
+		goto err;
 	}
 
 #ifdef DEBUG
@@ -2439,22 +2551,22 @@
 
 	if (vp->v_type != VDIR) {
 		resp->status = NFS3ERR_NOTDIR;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->object.name == nfs3nametoolong) {
 		resp->status = NFS3ERR_NAMETOOLONG;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->object.name == NULL || *(args->object.name) == '\0') {
 		resp->status = NFS3ERR_ACCES;
-		goto out1;
+		goto err1;
 	}
 
 	if (rdonly(exi, req)) {
 		resp->status = NFS3ERR_ROFS;
-		goto out1;
+		goto err1;
 	}
 
 	if (is_system_labeled()) {
@@ -2467,7 +2579,7 @@
 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
 			if (!do_rfs_label_check(clabel, vp, EQUALITY_CHECK)) {
 				resp->status = NFS3ERR_ACCES;
-				goto out1;
+				goto err1;
 			}
 		}
 	}
@@ -2499,25 +2611,27 @@
 		 */
 		if (error == EEXIST)
 			error = ENOTEMPTY;
-		goto out;
+		goto err;
 	}
 
-	VN_RELE(vp);
-
 	resp->status = NFS3_OK;
 	vattr_to_wcc_data(bvap, avap, &resp->resok.dir_wcc);
-	return;
-
-out:
+	goto out;
+
+err:
 	if (curthread->t_flag & T_WOULDBLOCK) {
 		curthread->t_flag &= ~T_WOULDBLOCK;
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
-out1:
+err1:
+	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
+out:
+	DTRACE_NFSV3_4(op__rmdir__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, RMDIR3res *, resp);
 	if (vp != NULL)
 		VN_RELE(vp);
-	vattr_to_wcc_data(bvap, avap, &resp->resfail.dir_wcc);
+
 }
 
 void *
@@ -2555,9 +2669,13 @@
 	tvp = NULL;
 
 	fvp = nfs3_fhtovp(&args->from.dir, exi);
+
+	DTRACE_NFSV3_4(op__rename__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, fvp, RENAME3args *, args);
+
 	if (fvp == NULL) {
 		error = ESTALE;
-		goto out;
+		goto err;
 	}
 
 	if (is_system_labeled()) {
@@ -2569,7 +2687,7 @@
 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
 			if (!do_rfs_label_check(clabel, fvp, EQUALITY_CHECK)) {
 				resp->status = NFS3ERR_ACCES;
-				goto out1;
+				goto err1;
 			}
 		}
 	}
@@ -2590,19 +2708,19 @@
 	to_exi = checkexport(&fh3->fh3_fsid, FH3TOXFIDP(fh3));
 	if (to_exi == NULL) {
 		resp->status = NFS3ERR_ACCES;
-		goto out1;
+		goto err1;
 	}
 	exi_rele(to_exi);
 
 	if (to_exi != exi) {
 		resp->status = NFS3ERR_XDEV;
-		goto out1;
+		goto err1;
 	}
 
 	tvp = nfs3_fhtovp(&args->to.dir, exi);
 	if (tvp == NULL) {
 		error = ESTALE;
-		goto out;
+		goto err;
 	}
 
 #ifdef DEBUG
@@ -2619,30 +2737,30 @@
 
 	if (fvp->v_type != VDIR || tvp->v_type != VDIR) {
 		resp->status = NFS3ERR_NOTDIR;
-		goto out1;
+		goto err1;
 	}
 
 	if (args->from.name == nfs3nametoolong ||
 	    args->to.name == nfs3nametoolong) {
 		resp->status = NFS3ERR_NAMETOOLONG;
-		goto out1;
+		goto err1;
 	}
 	if (args->from.name == NULL || *(args->from.name) == '\0' ||
 	    args->to.name == NULL || *(args->to.name) == '\0') {
 		resp->status = NFS3ERR_ACCES;
-		goto out1;
+		goto err1;
 	}
 
 	if (rdonly(exi, req)) {
 		resp->status = NFS3ERR_ROFS;
-		goto out1;
+		goto err1;
 	}
 
 	if (is_system_labeled()) {
 		if (!blequal(&l_admin_low->tsl_label, clabel)) {
 			if (!do_rfs_label_check(clabel, tvp, EQUALITY_CHECK)) {
 				resp->status = NFS3ERR_ACCES;
-				goto out1;
+				goto err1;
 			}
 		}
 	}
@@ -2654,7 +2772,7 @@
 	error = VOP_LOOKUP(fvp, args->from.name, &srcvp, NULL, 0,
 	    NULL, cr, NULL, NULL, NULL);
 	if (error != 0)
-		goto out;
+		goto err;
 
 	/*
 	 * If we rename a delegated file we should recall the
@@ -2663,7 +2781,7 @@
 	 */
 	if (rfs4_check_delegated(FWRITE, srcvp, FALSE)) {
 		resp->status = NFS3ERR_JUKEBOX;
-		goto out1;
+		goto err1;
 	}
 
 	/*
@@ -2677,7 +2795,7 @@
 		if (rfs4_check_delegated(FWRITE, targvp, TRUE)) {
 			VN_RELE(targvp);
 			resp->status = NFS3ERR_JUKEBOX;
-			goto out1;
+			goto err1;
 		}
 		VN_RELE(targvp);
 	}
@@ -2735,29 +2853,29 @@
 	(void) VOP_FSYNC(tvp, 0, cr, NULL);
 
 	if (error)
-		goto out;
-
-	VN_RELE(tvp);
-	VN_RELE(fvp);
+		goto err;
 
 	resp->status = NFS3_OK;
 	vattr_to_wcc_data(fbvap, favap, &resp->resok.fromdir_wcc);
 	vattr_to_wcc_data(tbvap, tavap, &resp->resok.todir_wcc);
-	return;
-
-out:
+	goto out;
+
+err:
 	if (curthread->t_flag & T_WOULDBLOCK) {
 		curthread->t_flag &= ~T_WOULDBLOCK;
 		resp->status = NFS3ERR_JUKEBOX;
 	} else
 		resp->status = puterrno3(error);
-out1:
+err1:
+	vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc);
+	vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
+out:
+	DTRACE_NFSV3_4(op__rename__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, fvp, RENAME3res *, resp);
 	if (fvp != NULL)
 		VN_RELE(fvp);
 	if (tvp != NULL)
 		VN_RELE(tvp);
-	vattr_to_wcc_data(fbvap, favap, &resp->resfail.fromdir_wcc);
-	vattr_to_wcc_data(tbvap, tavap, &resp->resfail.todir_wcc);
 }
 
 void *
@@ -2790,6 +2908,10 @@
 	dvp = NULL;
 
 	vp = nfs3_fhtovp(&args->file, exi);
+
+	DTRACE_NFSV3_4(op__link__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, LINK3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -2912,11 +3034,16 @@
 		goto out;
 
 	VN_RELE(dvp);
-	VN_RELE(vp);
 
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.file_attributes);
 	vattr_to_wcc_data(bvap, avap, &resp->resok.linkdir_wcc);
+
+	DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -2926,6 +3053,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__link__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, LINK3res *, resp);
+
 	if (vp != NULL)
 		VN_RELE(vp);
 	if (dvp != NULL)
@@ -2990,6 +3120,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->dir, exi);
+
+	DTRACE_NFSV3_4(op__readdir__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READDIR3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -3145,8 +3279,6 @@
 	(void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
 #endif
 
-	VN_RELE(vp);
-
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.dir_attributes);
 	resp->resok.cookieverf = 0;
@@ -3155,6 +3287,12 @@
 	resp->resok.size = count - uio.uio_resid;
 	resp->resok.count = args->count;
 	resp->resok.freecount = count;
+
+	DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -3164,6 +3302,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__readdir__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READDIR3res *, resp);
+
 	if (vp != NULL) {
 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
 		VN_RELE(vp);
@@ -3249,6 +3390,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->dir, exi);
+
+	DTRACE_NFSV3_4(op__readdirplus__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READDIRPLUS3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -3523,8 +3668,6 @@
 	(void) VOP_FSYNC(vp, FNODSYNC, cr, NULL);
 #endif
 
-	VN_RELE(vp);
-
 	kmem_free(namlen, args->dircount);
 
 	resp->status = NFS3_OK;
@@ -3535,6 +3678,12 @@
 	resp->resok.size = nents;
 	resp->resok.count = args->dircount;
 	resp->resok.maxcount = args->maxcount;
+
+	DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -3544,6 +3693,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__readdirplus__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, READDIRPLUS3res *, resp);
+
 	if (vp != NULL) {
 		VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
 		VN_RELE(vp);
@@ -3587,6 +3739,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->fsroot, exi);
+
+	DTRACE_NFSV3_4(op__fsstat__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, FSSTAT3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -3620,9 +3776,6 @@
 	vap = VOP_GETATTR(vp, &va, 0, cr, NULL) ? NULL : &va;
 #endif
 
-	VN_RELE(vp);
-	vp = NULL;
-
 	if (error)
 		goto out;
 
@@ -3644,6 +3797,11 @@
 	resp->resok.ffiles = (size3)sb.f_ffree;
 	resp->resok.afiles = (size3)sb.f_favail;
 	resp->resok.invarsec = 0;
+
+	DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -3653,6 +3811,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__fsstat__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, FSSTAT3res *, resp);
+
 	if (vp != NULL)
 		VN_RELE(vp);
 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
@@ -3678,6 +3839,10 @@
 	int error;
 
 	vp = nfs3_fhtovp(&args->fsroot, exi);
+
+	DTRACE_NFSV3_4(op__fsinfo__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, FSINFO3args *, args);
+
 	if (vp == NULL) {
 		if (curthread->t_flag & T_WOULDBLOCK) {
 			curthread->t_flag &= ~T_WOULDBLOCK;
@@ -3685,7 +3850,7 @@
 		} else
 			resp->status = NFS3ERR_STALE;
 		vattr_to_post_op_attr(NULL, &resp->resfail.obj_attributes);
-		return;
+		goto out;
 	}
 
 	if (is_system_labeled()) {
@@ -3700,7 +3865,7 @@
 				resp->status = NFS3ERR_STALE;
 				vattr_to_post_op_attr(NULL,
 				    &resp->resfail.obj_attributes);
-				return;
+				goto out;
 			}
 		}
 	}
@@ -3733,8 +3898,6 @@
 	 */
 	error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &l, cr, NULL);
 
-	VN_RELE(vp);
-
 	if (!error && l != 0 && l <= 64)
 		resp->resok.maxfilesize = (1LL << (l-1)) - 1;
 	else
@@ -3744,6 +3907,19 @@
 	resp->resok.time_delta.nseconds = 1000;
 	resp->resok.properties = FSF3_LINK | FSF3_SYMLINK |
 	    FSF3_HOMOGENEOUS | FSF3_CANSETTIME;
+
+	DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, FSINFO3res *, resp);
+
+	VN_RELE(vp);
+
+	return;
+
+out:
+	DTRACE_NFSV3_4(op__fsinfo__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, NULL, FSINFO3res *, resp);
+	if (vp != NULL)
+		VN_RELE(vp);
 }
 
 void *
@@ -3767,6 +3943,10 @@
 	vap = NULL;
 
 	vp = nfs3_fhtovp(&args->object, exi);
+
+	DTRACE_NFSV3_4(op__pathconf__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, PATHCONF3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -3824,12 +4004,13 @@
 	else
 		resp->resok.info.chown_restricted = FALSE;
 
-	VN_RELE(vp);
-
 	resp->status = NFS3_OK;
 	vattr_to_post_op_attr(vap, &resp->resok.obj_attributes);
 	resp->resok.info.case_insensitive = FALSE;
 	resp->resok.info.case_preserving = TRUE;
+	DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
+	VN_RELE(vp);
 	return;
 
 out:
@@ -3839,6 +4020,8 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__pathconf__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, PATHCONF3res *, resp);
 	if (vp != NULL)
 		VN_RELE(vp);
 	vattr_to_post_op_attr(vap, &resp->resfail.obj_attributes);
@@ -3866,6 +4049,10 @@
 	avap = NULL;
 
 	vp = nfs3_fhtovp(&args->file, exi);
+
+	DTRACE_NFSV3_4(op__commit__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, COMMIT3args *, args);
+
 	if (vp == NULL) {
 		error = ESTALE;
 		goto out;
@@ -3937,11 +4124,15 @@
 	if (error)
 		goto out;
 
-	VN_RELE(vp);
-
 	resp->status = NFS3_OK;
 	vattr_to_wcc_data(bvap, avap, &resp->resok.file_wcc);
 	resp->resok.verf = write3verf;
+
+	DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
+
+	VN_RELE(vp);
+
 	return;
 
 out:
@@ -3951,6 +4142,9 @@
 	} else
 		resp->status = puterrno3(error);
 out1:
+	DTRACE_NFSV3_4(op__commit__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, vp, COMMIT3res *, resp);
+
 	if (vp != NULL)
 		VN_RELE(vp);
 	vattr_to_wcc_data(bvap, avap, &resp->resfail.file_wcc);
--- a/usr/src/uts/common/fs/nfs/nfs_server.c	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/uts/common/fs/nfs/nfs_server.c	Wed Feb 06 17:59:23 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -602,6 +602,17 @@
 }
 
 /* ARGSUSED */
+void
+rpc_null_v3(caddr_t *argp, caddr_t *resp, struct exportinfo *exi,
+    struct svc_req *req, cred_t *cr)
+{
+	DTRACE_NFSV3_3(op__null__start, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, NULL);
+	DTRACE_NFSV3_3(op__null__done, struct svc_req *, req,
+	    cred_t *, cr, vnode_t *, NULL);
+}
+
+/* ARGSUSED */
 static void
 rfs_error(caddr_t *argp, caddr_t *resp)
 {
@@ -817,7 +828,7 @@
 	 */
 
 	/* RFS_NULL = 0 */
-	{rpc_null,
+	{rpc_null_v3,
 	    xdr_void, NULL_xdrproc_t, 0,
 	    xdr_void, NULL_xdrproc_t, 0,
 	    nullfree, RPC_IDEMPOTENT,
--- a/usr/src/uts/common/sys/sdt.h	Wed Feb 06 15:15:14 2008 -0800
+++ b/usr/src/uts/common/sys/sdt.h	Wed Feb 06 17:59:23 2008 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -156,6 +156,15 @@
 	DTRACE_PROBE4(__io_##name, type1, arg1, type2, arg2, 		\
 	    type3, arg3, type4, arg4);
 
+#define	DTRACE_NFSV3_3(name, type1, arg1, type2, arg2, 			\
+    type3, arg3)							\
+	DTRACE_PROBE3(__nfsv3_##name, type1, arg1, type2, arg2,		\
+	    type3, arg3);
+#define	DTRACE_NFSV3_4(name, type1, arg1, type2, arg2, 			\
+    type3, arg3, type4, arg4)						\
+	DTRACE_PROBE4(__nfsv3_##name, type1, arg1, type2, arg2,		\
+	    type3, arg3, type4, arg4);
+
 #define	DTRACE_NFSV4_1(name, type1, arg1) \
 	DTRACE_PROBE1(__nfsv4_##name, type1, arg1);