

Add a list of struct rpc_auth to the common cred cache protected by the
rpc_credcache_lock. Search the list in rpcauth_create, place an rpc_auth 
on the list if not found. Remove from the list on rpcauth_destroy. 
Free the list on cache destruction.

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


diff -puN include/linux/sunrpc/auth.h~rpc-common-credcache-auth-list include/linux/sunrpc/auth.h
--- linux-2.6.18-rc5/include/linux/sunrpc/auth.h~rpc-common-credcache-auth-list	2006-10-17 12:16:37.000000000 -0400
+++ linux-2.6.18-rc5-andros/include/linux/sunrpc/auth.h	2006-10-17 12:16:37.000000000 -0400
@@ -62,6 +62,7 @@ struct rpc_cred {
 struct rpc_cred_cache {
 	struct hlist_head	hashtable[RPC_CREDCACHE_NR];
 	struct kref		ref;
+	struct list_head        auth_list; /* cred cache entry auth types */
 };
 
 static inline void
@@ -79,6 +80,7 @@ rpcauth_put_ccache(struct rpc_cred_cache
 }
 
 struct rpc_auth {
+	struct list_head        au_list;        /* cred cache auth_list */
 	unsigned int		au_cslack;	/* call cred size estimate */
 				/* guess at number of u32's auth adds before
 				 * reply data; normally the verifier size: */
diff -puN net/sunrpc/auth.c~rpc-common-credcache-auth-list net/sunrpc/auth.c
--- linux-2.6.18-rc5/net/sunrpc/auth.c~rpc-common-credcache-auth-list	2006-10-17 12:16:37.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth.c	2006-10-17 12:16:37.000000000 -0400
@@ -61,6 +61,26 @@ rpcauth_unregister(struct rpc_authops *o
 	return 0;
 }
 
+static DEFINE_SPINLOCK(rpc_credcache_lock);
+
+static struct rpc_auth *
+rpcauth_find(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
+{
+	struct rpc_auth *pos;
+
+	BUG_ON(clnt->cl_credcache == NULL);
+	spin_lock(&rpc_credcache_lock);
+	list_for_each_entry(pos, &clnt->cl_credcache->auth_list, au_list) {
+		if (pseudoflavor != pos->au_flavor)
+			continue;
+		goto done;
+	}
+	pos = NULL;
+done:
+	spin_unlock(&rpc_credcache_lock);
+	return pos;
+}
+
 struct rpc_auth *
 rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
 {
@@ -72,6 +92,10 @@ rpcauth_create(rpc_authflavor_t pseudofl
 	if (!clnt->cl_credcache || flavor >= RPC_AUTH_MAXFLAVOR)
 		goto out;
 
+	auth = rpcauth_find(pseudoflavor, clnt);
+	if (auth)
+		goto found;
+
 	/* FIXME - auth_flavors[] really needs an rw lock,
 	 * and module refcounting. */
 #ifdef CONFIG_KMOD
@@ -83,6 +107,10 @@ rpcauth_create(rpc_authflavor_t pseudofl
 	auth = ops->create(clnt, pseudoflavor);
 	if (IS_ERR(auth))
 		return auth;
+	spin_lock(&rpc_credcache_lock);
+	list_add(&auth->au_list, &clnt->cl_credcache->auth_list);
+	spin_unlock(&rpc_credcache_lock);
+found:
 	auth->au_credcache = clnt->cl_credcache;
 	clnt->cl_auth = auth;
 out:
@@ -97,8 +125,6 @@ rpcauth_destroy(struct rpc_auth *auth)
 	auth->au_ops->destroy(auth);
 }
 
-static DEFINE_SPINLOCK(rpc_credcache_lock);
-
 /*
  * Initialize RPC credential cache
  */
@@ -115,6 +141,7 @@ rpcauth_init_credcache(struct rpc_clnt *
 	for (i = 0; i < RPC_CREDCACHE_NR; i++)
 		INIT_HLIST_HEAD(&new->hashtable[i]);
 	kref_init(&new->ref);
+	INIT_LIST_HEAD(&new->auth_list);
 done:
 	clnt->cl_credcache = new;
 	return err;
@@ -157,9 +184,15 @@ rpcauth_free_ccache(struct kref *ref)
 	HLIST_HEAD(free);
 	struct hlist_node *pos, *next;
 	struct rpc_cred	*cred;
+	struct rpc_auth *auth, *n;
 	int		i;
+	LIST_HEAD(aufree);
 
+	INIT_LIST_HEAD(&aufree);
 	spin_lock(&rpc_credcache_lock);
+	list_for_each_entry_safe(auth, n, &cache->auth_list, au_list) {
+		list_move(&auth->au_list, &aufree);
+	}
 	for (i = 0; i < RPC_CREDCACHE_NR; i++) {
 		hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
 			cred = hlist_entry(pos, struct rpc_cred, cr_hash);
@@ -169,6 +202,11 @@ rpcauth_free_ccache(struct kref *ref)
 	}
 	spin_unlock(&rpc_credcache_lock);
 	rpcauth_destroy_credlist(&free);
+	while(!list_empty(&aufree)) {
+		auth = list_entry(aufree.next, struct rpc_auth, au_list);
+		list_del_init(&auth->au_list);
+		rpcauth_destroy(auth);
+	}
 	kfree(cache);
 }
 
diff -puN net/sunrpc/auth_unix.c~rpc-common-credcache-auth-list net/sunrpc/auth_unix.c
--- linux-2.6.18-rc5/net/sunrpc/auth_unix.c~rpc-common-credcache-auth-list	2006-10-17 12:16:37.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth_unix.c	2006-10-17 12:16:37.000000000 -0400
@@ -41,6 +41,7 @@ unx_create(struct rpc_clnt *clnt, rpc_au
 	dprintk("RPC: creating UNIX authenticator for client %p\n", clnt);
 	if (atomic_inc_return(&unix_auth.au_count) == 0)
 		unix_auth.au_nextgc = jiffies + (unix_auth.au_expire >> 1);
+	INIT_LIST_HEAD(&unix_auth.au_list);
 	return &unix_auth;
 }
 
diff -puN net/sunrpc/auth_gss/auth_gss.c~rpc-common-credcache-auth-list net/sunrpc/auth_gss/auth_gss.c
--- linux-2.6.18-rc5/net/sunrpc/auth_gss/auth_gss.c~rpc-common-credcache-auth-list	2006-10-17 12:16:37.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth_gss/auth_gss.c	2006-10-17 12:16:37.000000000 -0400
@@ -869,6 +869,7 @@ gss_create(struct rpc_clnt *clnt, rpc_au
 	auth->au_ops = &authgss_ops;
 	auth->au_flavor = flavor;
 	auth->au_expire = GSS_CRED_EXPIRE;
+	INIT_LIST_HEAD(&auth->au_list);
 	atomic_set(&auth->au_count, 1);
 
 	snprintf(gss_auth->key_name, sizeof(gss_auth->key_name),
diff -puN net/sunrpc/auth_null.c~rpc-common-credcache-auth-list net/sunrpc/auth_null.c
--- linux-2.6.18-rc5/net/sunrpc/auth_null.c~rpc-common-credcache-auth-list	2006-10-17 12:16:37.000000000 -0400
+++ linux-2.6.18-rc5-andros/net/sunrpc/auth_null.c	2006-10-17 12:16:37.000000000 -0400
@@ -22,7 +22,12 @@ static struct rpc_cred null_cred;
 static struct rpc_auth *
 nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
+	/*
 	atomic_inc(&null_auth.au_count);
+	*/
+	printk("%s calling rpcauth_get_ccache for cache %p\n",__FUNCTION__,clnt->cl_credcache);
+	rpcauth_get_ccache(clnt->cl_credcache);
+	INIT_LIST_HEAD(&null_auth.au_list);
 	return &null_auth;
 }
 
_
