RPC: Make rpc_auth credential cache optional. Some RPC authentication flavours are not related to the uid (AUTH_NULL springs to mind). This patch moves control over the caching mechanism into the auth-specific code. Also ensure that expired creds are removed from the cache. Signed-off-by: Trond Myklebust --- include/linux/sunrpc/auth.h | 1 + net/sunrpc/auth.c | 22 +++++++++++----------- net/sunrpc/auth_gss/auth_gss.c | 10 ++++++++++ net/sunrpc/auth_null.c | 10 ++++++++++ net/sunrpc/auth_unix.c | 10 ++++++++++ 5 files changed, 42 insertions(+), 11 deletions(-) Index: linux-2.6.11-rc3/net/sunrpc/auth.c =================================================================== --- linux-2.6.11-rc3.orig/net/sunrpc/auth.c +++ linux-2.6.11-rc3/net/sunrpc/auth.c @@ -137,16 +137,17 @@ rpcauth_free_credcache(struct rpc_auth * rpcauth_destroy_credlist(&free); } -static inline int +static void rpcauth_prune_expired(struct rpc_cred *cred, struct list_head *free) { if (atomic_read(&cred->cr_count) != 1) - return 0; - if (time_before(jiffies, cred->cr_expire + cred->cr_auth->au_expire)) - return 0; - cred->cr_auth = NULL; - list_move(&cred->cr_hash, free); - return 1; + return; + if (time_after(jiffies, cred->cr_expire + cred->cr_auth->au_expire)) + cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE; + if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) { + cred->cr_auth = NULL; + list_move(&cred->cr_hash, free); + } } /* @@ -191,13 +192,12 @@ retry: list_for_each_safe(pos, next, &auth->au_credcache[nr]) { struct rpc_cred *entry; entry = list_entry(pos, struct rpc_cred, cr_hash); - if (rpcauth_prune_expired(entry, &free)) - continue; if (entry->cr_ops->crmatch(acred, entry, taskflags)) { list_del(&entry->cr_hash); cred = entry; break; } + rpcauth_prune_expired(entry, &free); } if (new) { if (cred) @@ -240,7 +240,7 @@ rpcauth_lookupcred(struct rpc_auth *auth dprintk("RPC: looking up %s cred\n", auth->au_ops->au_name); - ret = rpcauth_lookup_credcache(auth, &acred, taskflags); + ret = auth->au_ops->lookup_cred(auth, &acred, taskflags); put_group_info(current->group_info); return ret; } @@ -259,7 +259,7 @@ rpcauth_bindcred(struct rpc_task *task) dprintk("RPC: %4d looking up %s cred\n", task->tk_pid, task->tk_auth->au_ops->au_name); - task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags); + task->tk_msg.rpc_cred = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags); if (task->tk_msg.rpc_cred == 0) task->tk_status = -ENOMEM; ret = task->tk_msg.rpc_cred; Index: linux-2.6.11-rc3/net/sunrpc/auth_null.c =================================================================== --- linux-2.6.11-rc3.orig/net/sunrpc/auth_null.c +++ linux-2.6.11-rc3/net/sunrpc/auth_null.c @@ -47,6 +47,15 @@ nul_destroy(struct rpc_auth *auth) } /* + * Lookup NULL creds for current process + */ +static struct rpc_cred * +nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) +{ + return rpcauth_lookup_credcache(auth, acred, flags); +} + +/* * Create NULL creds for current process */ static struct rpc_cred * @@ -135,6 +144,7 @@ struct rpc_authops authnull_ops = { #endif .create = nul_create, .destroy = nul_destroy, + .lookup_cred = nul_lookup_cred, .crcreate = nul_create_cred, }; Index: linux-2.6.11-rc3/include/linux/sunrpc/auth.h =================================================================== --- linux-2.6.11-rc3.orig/include/linux/sunrpc/auth.h +++ linux-2.6.11-rc3/include/linux/sunrpc/auth.h @@ -91,6 +91,7 @@ struct rpc_authops { struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t); void (*destroy)(struct rpc_auth *); + struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int); struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); }; Index: linux-2.6.11-rc3/net/sunrpc/auth_unix.c =================================================================== --- linux-2.6.11-rc3.orig/net/sunrpc/auth_unix.c +++ linux-2.6.11-rc3/net/sunrpc/auth_unix.c @@ -65,6 +65,15 @@ unx_destroy(struct rpc_auth *auth) kfree(auth); } +/* + * Lookup AUTH_UNIX creds for current process + */ +static struct rpc_cred * +unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) +{ + return rpcauth_lookup_credcache(auth, acred, flags); +} + static struct rpc_cred * unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) { @@ -225,6 +234,7 @@ struct rpc_authops authunix_ops = { #endif .create = unx_create, .destroy = unx_destroy, + .lookup_cred = unx_lookup_cred, .crcreate = unx_create_cred, }; Index: linux-2.6.11-rc3/net/sunrpc/auth_gss/auth_gss.c =================================================================== --- linux-2.6.11-rc3.orig/net/sunrpc/auth_gss/auth_gss.c +++ linux-2.6.11-rc3/net/sunrpc/auth_gss/auth_gss.c @@ -654,6 +654,15 @@ gss_destroy_cred(struct rpc_cred *rc) kfree(cred); } +/* + * Lookup RPCSEC_GSS cred for the current process + */ +static struct rpc_cred * +gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) +{ + return rpcauth_lookup_credcache(auth, acred, taskflags); +} + static struct rpc_cred * gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) { @@ -1004,6 +1013,7 @@ static struct rpc_authops authgss_ops = #endif .create = gss_create, .destroy = gss_destroy, + .lookup_cred = gss_lookup_cred, .crcreate = gss_create_cred };