RPC: [PATCH] improve rpcauthauth_create error returns Currently we return -ENOMEM for every single failure to create a new auth. This is actually accurate for auth_null and auth_unix, but for auth_gss it's a bit confusing. Allow rpcauth_create (and the ->create methods) to return errors. With this patch, the user may sometimes see an EINVAL instead. Whee. Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 25 ++++++++++++++++--------- net/sunrpc/auth.c | 6 +++--- net/sunrpc/auth_gss/auth_gss.c | 13 +++++++++---- net/sunrpc/clnt.c | 6 ++++-- 4 files changed, 32 insertions(+), 18 deletions(-) Index: linux-2.6.12-rc6/net/sunrpc/auth_gss/auth_gss.c =================================================================== --- linux-2.6.12-rc6.orig/net/sunrpc/auth_gss/auth_gss.c +++ linux-2.6.12-rc6/net/sunrpc/auth_gss/auth_gss.c @@ -660,14 +660,16 @@ gss_create(struct rpc_clnt *clnt, rpc_au { struct gss_auth *gss_auth; struct rpc_auth * auth; + int err = -ENOMEM; /* XXX? */ dprintk("RPC: creating GSS authenticator for client %p\n",clnt); if (!try_module_get(THIS_MODULE)) - return NULL; + return ERR_PTR(err); if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) goto out_dec; gss_auth->client = clnt; + err = -EINVAL; gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor); if (!gss_auth->mech) { printk(KERN_WARNING "%s: Pseudoflavor %d not found!", @@ -686,15 +688,18 @@ gss_create(struct rpc_clnt *clnt, rpc_au auth->au_flavor = flavor; atomic_set(&auth->au_count, 1); - if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0) + err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE); + if (err) goto err_put_mech; snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s", clnt->cl_pathname, gss_auth->mech->gm_name); gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); - if (IS_ERR(gss_auth->dentry)) + if (IS_ERR(gss_auth->dentry)) { + err = PTR_ERR(gss_auth->dentry); goto err_put_mech; + } return auth; err_put_mech: @@ -703,7 +708,7 @@ err_free: kfree(gss_auth); out_dec: module_put(THIS_MODULE); - return NULL; + return ERR_PTR(err); } static void Index: linux-2.6.12-rc6/net/sunrpc/auth.c =================================================================== --- linux-2.6.12-rc6.orig/net/sunrpc/auth.c +++ linux-2.6.12-rc6/net/sunrpc/auth.c @@ -66,10 +66,10 @@ rpcauth_create(rpc_authflavor_t pseudofl u32 flavor = pseudoflavor_to_flavor(pseudoflavor); if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor])) - return NULL; + return ERR_PTR(-EINVAL); auth = ops->create(clnt, pseudoflavor); - if (!auth) - return NULL; + if (IS_ERR(auth)) + return auth; if (clnt->cl_auth) rpcauth_destroy(clnt->cl_auth); clnt->cl_auth = auth; Index: linux-2.6.12-rc6/net/sunrpc/clnt.c =================================================================== --- linux-2.6.12-rc6.orig/net/sunrpc/clnt.c +++ linux-2.6.12-rc6/net/sunrpc/clnt.c @@ -103,6 +103,7 @@ rpc_new_client(struct rpc_xprt *xprt, ch { struct rpc_version *version; struct rpc_clnt *clnt = NULL; + struct rpc_auth *auth; int err; int len; @@ -157,10 +158,11 @@ rpc_new_client(struct rpc_xprt *xprt, ch if (err < 0) goto out_no_path; - err = -ENOMEM; - if (!rpcauth_create(flavor, clnt)) { + auth = rpcauth_create(flavor, clnt); + if (IS_ERR(auth)) { printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", flavor); + err = PTR_ERR(auth); goto out_no_auth; } Index: linux-2.6.12-rc6/fs/nfs/inode.c =================================================================== --- linux-2.6.12-rc6.orig/fs/nfs/inode.c +++ linux-2.6.12-rc6/fs/nfs/inode.c @@ -160,11 +160,10 @@ nfs_clear_inode(struct inode *inode) void nfs_umount_begin(struct super_block *sb) { - struct nfs_server *server = NFS_SB(sb); - struct rpc_clnt *rpc; + struct rpc_clnt *rpc = NFS_SB(sb)->client; /* -EIO all pending I/O */ - if ((rpc = server->client) != NULL) + if (!IS_ERR(rpc)) rpc_killall_tasks(rpc); } @@ -450,11 +449,14 @@ nfs_fill_super(struct super_block *sb, s return PTR_ERR(server->client); /* RFC 2623, sec 2.3.2 */ if (authflavor != RPC_AUTH_UNIX) { + struct rpc_auth *auth; + server->client_sys = rpc_clone_client(server->client); if (IS_ERR(server->client_sys)) return PTR_ERR(server->client_sys); - if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys)) - return -ENOMEM; + auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys); + if (IS_ERR(auth)) + return PTR_ERR(auth); } else { atomic_inc(&server->client->cl_count); server->client_sys = server->client; @@ -1450,6 +1452,7 @@ static struct super_block *nfs_get_sb(st memset(server, 0, sizeof(struct nfs_server)); /* Zero out the NFS state stuff */ init_nfsv4_state(server); + server->client = server->client_sys = ERR_PTR(-EINVAL); root = &server->fh; if (data->flags & NFS_MOUNT_VER3) @@ -1506,9 +1509,9 @@ static void nfs_kill_super(struct super_ kill_anon_super(s); - if (server->client != NULL && !IS_ERR(server->client)) + if (!IS_ERR(server->client)) rpc_shutdown_client(server->client); - if (server->client_sys != NULL && !IS_ERR(server->client_sys)) + if (!IS_ERR(server->client_sys)) rpc_shutdown_client(server->client_sys); if (!(server->flags & NFS_MOUNT_NONLM)) @@ -1711,9 +1714,12 @@ static int nfs4_fill_super(struct super_ } if (clnt->cl_auth->au_flavor != authflavour) { - if (rpcauth_create(authflavour, clnt) == NULL) { + struct rpc_auth *auth; + + auth = rpcauth_create(authflavour, clnt); + if (IS_ERR(auth)) { dprintk("%s: couldn't create credcache!\n", __FUNCTION__); - return -ENOMEM; + return PTR_ERR(auth); } } @@ -1788,6 +1794,7 @@ static struct super_block *nfs4_get_sb(s memset(server, 0, sizeof(struct nfs_server)); /* Zero out the NFS state stuff */ init_nfsv4_state(server); + server->client = server->client_sys = ERR_PTR(-EINVAL); p = nfs_copy_user_string(NULL, &data->hostname, 256); if (IS_ERR(p))