Merge pull request #22 from malahal/duplex-13

Use partition size for deleting GSS contexts/Fix gss data leak
diff --git a/src/authgss_hash.c b/src/authgss_hash.c
index 4ca53b5..21ecaf9 100644
--- a/src/authgss_hash.c
+++ b/src/authgss_hash.c
@@ -44,6 +44,7 @@
 
 struct authgss_x_part {
 	uint32_t gen;
+	uint32_t size;
 	 TAILQ_HEAD(ctx_tailq, svc_rpc_gss_data) lru_q;
 };
 
@@ -119,7 +120,7 @@
 			       sizeof(struct opr_rbtree_node *));
 
 		/* partition ctx LRU */
-		axp = (struct authgss_x_part *)mem_alloc(sizeof(*axp));
+		axp = (struct authgss_x_part *)mem_zalloc(sizeof(*axp));
 		TAILQ_INIT(&axp->lru_q);
 		xp->u1 = axp;
 	}
@@ -186,7 +187,7 @@
 	gss_ctx = (gss_union_ctx_id_desc *) (gd->ctx);
 	gd->hk.k = gss_ctx_hash(gss_ctx);
 
-	++(gd->refcnt);		/* locked */
+	(void)atomic_inc_uint32_t(&gd->refcnt);
 	t = rbtx_partition_of_scalar(&authgss_hash_st.xt, gd->hk.k);
 	mutex_lock(&t->mtx);
 	rslt =
@@ -195,6 +196,7 @@
 	/* lru */
 	axp = (struct authgss_x_part *)t->u1;
 	TAILQ_INSERT_TAIL(&axp->lru_q, gd, lru_q);
+	++(axp->size);
 	mutex_unlock(&t->mtx);
 
 	/* global size */
@@ -216,6 +218,7 @@
 	rbtree_x_cached_remove(&authgss_hash_st.xt, t, &gd->node_k, gd->hk.k);
 	axp = (struct authgss_x_part *)t->u1;
 	TAILQ_REMOVE(&axp->lru_q, gd, lru_q);
+	--(axp->size);
 	mutex_unlock(&t->mtx);
 
 	/* global size */
@@ -266,13 +269,14 @@
 		/* Remove the least-recently-used entry in this hash
 		 * partition iff it is expired, or the partition size
 		 * limit is exceeded */
-		if (unlikely((authgss_hash_st.size > authgss_hash_st.max_part)
+		if (unlikely((axp->size > authgss_hash_st.max_part)
 				|| (authgss_ctx_expired(gd)))) {
 
 			/* remove entry */
 			rbtree_x_cached_remove(&authgss_hash_st.xt, xp,
 					       &gd->node_k, gd->hk.k);
 			TAILQ_REMOVE(&axp->lru_q, gd, lru_q);
+			--(axp->size);
 			(void)atomic_dec_uint32_t(&authgss_hash_st.size);
 
 			/* drop sentinel ref (may free gd) */
diff --git a/src/svc_auth_gss.c b/src/svc_auth_gss.c
index 3322ab5..cc7b1f4 100644
--- a/src/svc_auth_gss.c
+++ b/src/svc_auth_gss.c
@@ -612,7 +612,7 @@
 
 		*no_dispatch = true;
 
-		(void)authgss_ctx_hash_del(gd);	/* unrefs, can destroy gd */
+		(void)authgss_ctx_hash_del(gd);
 
 		/* avoid lock order reversal gd->lock, xprt->xp_lock */
 		mutex_unlock(&gd->lock);
@@ -622,6 +622,11 @@
 		    svc_sendreply(req->rq_xprt, req, (xdrproc_t) xdr_void,
 				  (caddr_t) NULL);
 
+		/* We acquired a reference on gd with authgss_ctx_hash_get
+		 * call.  Time to release the reference as we don't need
+		 * gd anymore.
+		 */
+		unref_svc_rpc_gss_data(gd, SVC_RPC_GSS_FLAG_NONE);
 		req->rq_auth = &svc_auth_none;
 
 		break;