diff usr/src/uts/common/fs/nfs/nfs_server.c @ 13814:829c00a55a37

2986 nfs: exi refcounter leak at rfs3_lookup Reviewed by: Albert Lee <trisk@nexenta.com> Reviewed by: Gordon Ross <gwr@nexenta.com> Approved by: Albert Lee <trisk@nexenta.com>
author Vitaliy Gusev <gusev.vitaliy@nexenta.com>
date Wed, 22 Aug 2012 13:03:31 +0000
parents bf40125f4b37
children ad441dd34478
line wrap: on
line diff
--- a/usr/src/uts/common/fs/nfs/nfs_server.c	Wed Sep 12 04:54:49 2012 +0000
+++ b/usr/src/uts/common/fs/nfs/nfs_server.c	Wed Aug 22 13:03:31 2012 +0000
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
+ * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*
@@ -2800,8 +2801,8 @@
 			 */
 
 			/* Release the reference on the old exi value */
-			ASSERT(*exi != NULL);
 			exi_rele(*exi);
+			*exi = NULL;
 
 			if (error = nfs_check_vpexi(mc_dvp, *vpp, kcred, exi)) {
 				VN_RELE(*vpp);
@@ -2814,6 +2815,9 @@
 	if (mc_dvp)
 		VN_RELE(mc_dvp);
 
+	if (error && *exi != NULL)
+		exi_rele(*exi);
+
 	return (error);
 }
 
@@ -2959,16 +2963,19 @@
 /*
  * Get the export information for the lookup vnode, and verify its
  * useable.
+ *
+ * Set @exip only in success
  */
 int
 nfs_check_vpexi(vnode_t *mc_dvp, vnode_t *vp, cred_t *cr,
-    struct exportinfo **exi)
+    struct exportinfo **exip)
 {
 	int walk;
 	int error = 0;
-
-	*exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE);
-	if (*exi == NULL)
+	struct exportinfo *exi;
+
+	exi = nfs_vptoexi(mc_dvp, vp, cr, &walk, NULL, FALSE);
+	if (exi == NULL)
 		error = EACCES;
 	else {
 		/*
@@ -2977,10 +2984,13 @@
 		 * must not terminate below the
 		 * exported directory.
 		 */
-		if ((*exi)->exi_export.ex_flags & EX_NOSUB && walk > 0)
+		if (exi->exi_export.ex_flags & EX_NOSUB && walk > 0) {
 			error = EACCES;
+			exi_rele(exi);
+		}
 	}
-
+	if (error == 0)
+		*exip = exi;
 	return (error);
 }