
---

Use the new upcall info for gss upcalls. Free the struct rpc_upcall_info in
rpcauth_free_ccache().


Signed-off-by: Andy Adamson <andros@citi.umich.edu>

---


diff -puN net/sunrpc/auth_gss/auth_gss.c~gss-alloc-find-free-upcall-info net/sunrpc/auth_gss/auth_gss.c
--- linux-2.6.18-rc5/net/sunrpc/auth_gss/auth_gss.c~gss-alloc-find-free-upcall-info	2006-10-17 15:34:58.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth_gss/auth_gss.c	2006-10-17 15:34:58.000000000 -0400
@@ -485,7 +485,6 @@ gss_alloc_msg(struct gss_auth *gss_auth,
 	if (gss_msg != NULL) {
 		INIT_LIST_HEAD(&gss_msg->list);
 		rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
-		init_waitqueue_head(&gss_msg->auth->info->waitqueue);
 		atomic_set(&gss_msg->count, 1);
 #ifdef CONFIG_RPCSEC_GSS_KEYRING
 		if (gss_init_msg_upcall_info(gss_msg, krinfo)) {
@@ -833,6 +832,40 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg
 	}
 }
 
+static int
+gss_create_upcall_info(struct rpc_clnt *clnt, struct gss_auth *gss_auth)
+{
+	struct rpc_upcall_info *info;
+	int err;
+
+	info = rpcauth_create_upcall_info();
+	if (IS_ERR(info)) {
+		err = PTR_ERR(info);
+		goto out;
+	}
+
+	info->dentry = rpc_mkpipe(clnt->cl_dentry,
+#ifdef CONFIG_RPCSEC_GSS_KEYRING
+			"keyring",
+#else
+			"gss_upcall",
+#endif
+			clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
+	if (IS_ERR(info->dentry)) {
+		err = PTR_ERR(info->dentry);
+		goto err_free_info;
+	}
+	gss_auth->dentry = info->dentry;
+	clnt->cl_credcache->info = info;
+	err = 0;
+out:
+	return err;
+
+err_free_info:
+	kfree(info);
+	goto out;
+}
+
 /* 
  * NOTE: we have the opportunity to use different 
  * parameters based on the input flavor (which must be a pseudoflavor)
@@ -861,8 +894,6 @@ gss_create(struct rpc_clnt *clnt, rpc_au
 	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
 	if (gss_auth->service == 0)
 		goto err_put_mech;
-	INIT_LIST_HEAD(&gss_auth->info->upcalls);
-	spin_lock_init(&gss_auth->info->lock);
 	auth = &gss_auth->rpc_auth;
 	auth->au_cslack = GSS_CRED_SLACK >> 2;
 	auth->au_rslack = GSS_VERF_SLACK >> 2;
@@ -872,25 +903,23 @@ gss_create(struct rpc_clnt *clnt, rpc_au
 	INIT_LIST_HEAD(&auth->au_list);
 	atomic_set(&auth->au_count, 1);
 
-	snprintf(gss_auth->key_name, sizeof(gss_auth->key_name),
-			"mechanism=\"%s\" pseudoflavor=\"%s\" service=\"%s%u\" host=\"%s\"",
-			gss_auth->mech->gm_name,
-			gss_auth->mech->gm_pfs[gss_auth->service-RPC_GSS_SVC_NONE].name,
-			clnt->cl_protname,
-			clnt->cl_vers,
-			clnt->cl_server);
-
-	gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry,
-#ifdef CONFIG_RPCSEC_GSS_KEYRING
-			"keyring",
-#else
-			gss_auth->mech->gm_name,
-#endif
-			clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
-	if (IS_ERR(gss_auth->dentry)) {
-		err = PTR_ERR(gss_auth->dentry);
-		goto err_put_mech;
+	if (clnt->cl_credcache->info == NULL) {
+		err = gss_create_upcall_info(clnt, gss_auth);
+		if (err < 0)
+			goto err_put_mech;
+	} else {
+		/* Already an upcall channel, use it */
+		dget(clnt->cl_credcache->info->dentry);
+		gss_auth->dentry = clnt->cl_credcache->info->dentry;
 	}
+	snprintf(gss_auth->key_name, sizeof(gss_auth->key_name),
+		"mechanism=\"%s\" pseudoflavor=\"%s\" service=\"%s%u\" host=\"%s\"",
+		gss_auth->mech->gm_name,
+		gss_auth->mech->gm_pfs[gss_auth->service-RPC_GSS_SVC_NONE].name,
+		clnt->cl_protname,
+		clnt->cl_vers,
+		clnt->cl_server);
+	gss_auth->info = clnt->cl_credcache->info;
 
 	return auth;
 err_put_mech:
@@ -911,7 +940,6 @@ gss_destroy(struct rpc_auth *auth)
 		auth, auth->au_flavor);
 
 	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	rpc_unlink(gss_auth->dentry);
 	gss_auth->dentry = NULL;
 	gss_mech_put(gss_auth->mech);
 
diff -puN net/sunrpc/auth.c~gss-alloc-find-free-upcall-info net/sunrpc/auth.c
--- linux-2.6.18-rc5/net/sunrpc/auth.c~gss-alloc-find-free-upcall-info	2006-10-17 15:34:58.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth.c	2006-10-17 15:34:58.000000000 -0400
@@ -214,6 +214,7 @@ rpcauth_free_ccache(struct kref *ref)
 	struct hlist_node *pos, *next;
 	struct rpc_cred	*cred;
 	struct rpc_auth *auth, *n;
+	struct rpc_upcall_info *info;
 	int		i;
 	LIST_HEAD(aufree);
 
@@ -229,6 +230,8 @@ rpcauth_free_ccache(struct kref *ref)
 			hlist_add_head(&cred->cr_hash, &free);
 		}
 	}
+	info = cache->info;
+	cache->info = NULL;
 	spin_unlock(&rpc_credcache_lock);
 	rpcauth_destroy_credlist(&free);
 	while(!list_empty(&aufree)) {
@@ -236,6 +239,8 @@ rpcauth_free_ccache(struct kref *ref)
 		list_del_init(&auth->au_list);
 		rpcauth_destroy(auth);
 	}
+	if (info)
+		rpcauth_free_upcall_info(info);
 	kfree(cache);
 }
 
_
