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 --- 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; } _