RPC: make rpcauth_lookupcred() return error codes. So we can distinguish between ENOMEM and EACCES errors. Signed-off-by: Trond Myklebust --- fs/nfs/dir.c | 7 +++++-- fs/nfs/inode.c | 10 ++++++++-- fs/nfs/nfs4proc.c | 12 ++++++++++-- fs/nfs/unlink.c | 9 ++++++++- fs/nfsd/nfs4callback.c | 9 ++++++++- net/sunrpc/auth.c | 14 ++++++++------ net/sunrpc/auth_gss/auth_gss.c | 7 ++++--- net/sunrpc/auth_unix.c | 2 +- net/sunrpc/clnt.c | 4 ++-- 9 files changed, 54 insertions(+), 20 deletions(-) Index: linux-2.6.11/fs/nfs/unlink.c =================================================================== --- linux-2.6.11.orig/fs/nfs/unlink.c +++ linux-2.6.11/fs/nfs/unlink.c @@ -167,6 +167,11 @@ nfs_async_unlink(struct dentry *dentry) goto out; memset(data, 0, sizeof(*data)); + data->cred = rpcauth_lookupcred(clnt->cl_auth, 0); + if (IS_ERR(data->cred)) { + status = PTR_ERR(data->cred); + goto out_free; + } data->dir = dget(dir); data->dentry = dentry; @@ -183,12 +188,14 @@ nfs_async_unlink(struct dentry *dentry) spin_lock(&dentry->d_lock); dentry->d_flags |= DCACHE_NFSFS_RENAMED; spin_unlock(&dentry->d_lock); - data->cred = rpcauth_lookupcred(clnt->cl_auth, 0); rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL); status = 0; out: return status; +out_free: + kfree(data); + return status; } /** Index: linux-2.6.11/fs/nfs/inode.c =================================================================== --- linux-2.6.11.orig/fs/nfs/inode.c +++ linux-2.6.11/fs/nfs/inode.c @@ -918,8 +918,9 @@ int nfs_open(struct inode *inode, struct struct nfs_open_context *ctx; struct rpc_cred *cred; - if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL) - return -ENOMEM; + cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); + if (IS_ERR(cred)) + return PTR_ERR(cred); ctx = alloc_nfs_open_context(filp->f_dentry, cred); put_rpccred(cred); if (ctx == NULL) @@ -1613,6 +1614,12 @@ static int nfs4_fill_super(struct super_ clnt->cl_chatty = 1; clp->cl_rpcclient = clnt; clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0); + if (IS_ERR(clp->cl_cred)) { + up_write(&clp->cl_sem); + err = PTR_ERR(clp->cl_cred); + clp->cl_cred = NULL; + goto out_fail; + } memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); nfs_idmap_new(clp); } Index: linux-2.6.11/fs/nfs/nfs4proc.c =================================================================== --- linux-2.6.11.orig/fs/nfs/nfs4proc.c +++ linux-2.6.11/fs/nfs/nfs4proc.c @@ -774,6 +774,8 @@ nfs4_atomic_open(struct inode *dir, stru } cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); + if (IS_ERR(cred)) + return (struct inode *)cred; state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); put_rpccred(cred); if (IS_ERR(state)) @@ -789,6 +791,8 @@ nfs4_open_revalidate(struct inode *dir, struct inode *inode; cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); + if (IS_ERR(cred)) + return PTR_ERR(cred); state = nfs4_open_delegated(dentry->d_inode, openflags, cred); if (IS_ERR(state)) state = nfs4_do_open(dir, dentry, openflags, NULL, cred); @@ -1009,6 +1013,8 @@ nfs4_proc_setattr(struct dentry *dentry, if (size_change) { struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); + if (IS_ERR(cred)) + return PTR_ERR(cred); state = nfs4_find_state(inode, cred, FMODE_WRITE); if (state == NULL) { state = nfs4_open_delegated(dentry->d_inode, @@ -1324,6 +1330,8 @@ nfs4_proc_create(struct inode *dir, stru struct rpc_cred *cred; cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); + if (IS_ERR(cred)) + return (struct inode *)cred; state = nfs4_do_open(dir, dentry, flags, sattr, cred); put_rpccred(cred); if (IS_ERR(state)) { @@ -2004,8 +2012,8 @@ nfs4_proc_file_open(struct inode *inode, /* Find our open stateid */ cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); - if (unlikely(cred == NULL)) - return -ENOMEM; + if (IS_ERR(cred)) + return PTR_ERR(cred); ctx = alloc_nfs_open_context(dentry, cred); put_rpccred(cred); if (unlikely(ctx == NULL)) Index: linux-2.6.11/net/sunrpc/auth.c =================================================================== --- linux-2.6.11.orig/net/sunrpc/auth.c +++ linux-2.6.11/net/sunrpc/auth.c @@ -226,12 +226,13 @@ retry: if (!cred) { new = auth->au_ops->crcreate(auth, acred, taskflags); - if (new) { + if (!IS_ERR(new)) { #ifdef RPC_DEBUG new->cr_magic = RPCAUTH_CRED_MAGIC; #endif goto retry; - } + } else + cred = new; } return (struct rpc_cred *) cred; @@ -269,10 +270,11 @@ 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 = 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; + ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags); + if (!IS_ERR(ret)) + task->tk_msg.rpc_cred = ret; + else + task->tk_status = PTR_ERR(ret); put_group_info(current->group_info); return ret; } Index: linux-2.6.11/fs/nfs/dir.c =================================================================== --- linux-2.6.11.orig/fs/nfs/dir.c +++ linux-2.6.11/fs/nfs/dir.c @@ -1532,8 +1532,11 @@ force_lookup: goto out_notsup; cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); - res = nfs_do_access(inode, cred, mask); - put_rpccred(cred); + if (!IS_ERR(cred)) { + res = nfs_do_access(inode, cred, mask); + put_rpccred(cred); + } else + res = PTR_ERR(cred); unlock_kernel(); out: return res; Index: linux-2.6.11/net/sunrpc/auth_unix.c =================================================================== --- linux-2.6.11.orig/net/sunrpc/auth_unix.c +++ linux-2.6.11/net/sunrpc/auth_unix.c @@ -75,7 +75,7 @@ unx_create_cred(struct rpc_auth *auth, s acred->uid, acred->gid); if (!(cred = (struct unx_cred *) kmalloc(sizeof(*cred), GFP_KERNEL))) - return NULL; + return ERR_PTR(-ENOMEM); atomic_set(&cred->uc_count, 1); cred->uc_flags = RPCAUTH_CRED_UPTODATE; Index: linux-2.6.11/net/sunrpc/auth_gss/auth_gss.c =================================================================== --- linux-2.6.11.orig/net/sunrpc/auth_gss/auth_gss.c +++ linux-2.6.11/net/sunrpc/auth_gss/auth_gss.c @@ -585,10 +585,11 @@ gss_pipe_downcall(struct file *filp, con } else { struct auth_cred acred = { .uid = uid }; spin_unlock(&gss_auth->lock); - err = -ENOENT; cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0); - if (!cred) + if (IS_ERR(cred)) { + err = PTR_ERR(cred); goto err_put_ctx; + } gss_cred_set_ctx(cred, gss_get_ctx(ctx)); } gss_put_ctx(ctx); @@ -795,7 +796,7 @@ gss_create_cred(struct rpc_auth *auth, s out_err: dprintk("RPC: gss_create_cred failed with error %d\n", err); if (cred) gss_destroy_cred(&cred->gc_base); - return NULL; + return ERR_PTR(err); } static int Index: linux-2.6.11/fs/nfsd/nfs4callback.c =================================================================== --- linux-2.6.11.orig/fs/nfsd/nfs4callback.c +++ linux-2.6.11/fs/nfsd/nfs4callback.c @@ -447,7 +447,10 @@ nfsd4_probe_callback(struct nfs4_client atomic_inc(&clp->cl_count); msg.rpc_cred = nfsd4_lookupcred(clp,0); - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL); + if (IS_ERR(msg.rpc_cred)) + status = PTR_ERR(msg.rpc_cred); + else + status = rpc_call_async(clnt, &msg, 0, nfs4_cb_null, NULL); if (status != 0) { dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n"); @@ -563,6 +566,10 @@ nfsd4_cb_recall(struct nfs4_delegation * msg.rpc_argp = cbr; msg.rpc_resp = cbr; msg.rpc_cred = nfsd4_lookupcred(clp,0); + if (IS_ERR(msg.rpc_cred)) { + status = PTR_ERR(msg.rpc_cred); + goto out_fail; + } cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ cbr->cbr_dp = dp; Index: linux-2.6.11/net/sunrpc/clnt.c =================================================================== --- linux-2.6.11.orig/net/sunrpc/clnt.c +++ linux-2.6.11/net/sunrpc/clnt.c @@ -425,9 +425,9 @@ rpc_call_setup(struct rpc_task *task, st task->tk_msg = *msg; task->tk_flags |= flags; /* Bind the user cred */ - if (task->tk_msg.rpc_cred != NULL) { + if (task->tk_msg.rpc_cred != NULL) rpcauth_holdcred(task); - } else + else rpcauth_bindcred(task); if (task->tk_status == 0)