From: Trond Myklebust RPC,NFSv2/v3/v4: Ensure that xprt_create_proto() and rpc_create_client() return full error codes. Should allow "mount" to print more useful error diagnostics. NFSroot: Also includes a bugfix to NFSroot "mount" program to cause it to use AUTH_UNIX instead of AUTH_NULL for authentication. --- fs/lockd/host.c | 4 ++-- fs/lockd/mon.c | 16 ++++++++-------- fs/nfs/inode.c | 24 ++++++++++++++---------- fs/nfs/mount_clnt.c | 14 ++++++++------ net/sunrpc/clnt.c | 24 ++++++++++++------------ net/sunrpc/pmap_clnt.c | 28 +++++++++++++++++----------- net/sunrpc/xprt.c | 15 +++++---------- 7 files changed, 66 insertions(+), 59 deletions(-) diff -puN fs/lockd/host.c~nfs-mount-return-useful-errors fs/lockd/host.c --- 25/fs/lockd/host.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/fs/lockd/host.c 2004-02-29 14:49:09.000000000 -0800 @@ -188,14 +188,14 @@ nlm_bind_host(struct nlm_host *host) } } else { xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); - if (xprt == NULL) + if (IS_ERR(xprt)) goto forgetit; xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); clnt = rpc_create_client(xprt, host->h_name, &nlm_program, host->h_version, host->h_authflavor); - if (clnt == NULL) { + if (IS_ERR(clnt)) { xprt_destroy(xprt); goto forgetit; } diff -puN fs/lockd/mon.c~nfs-mount-return-useful-errors fs/lockd/mon.c --- 25/fs/lockd/mon.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/fs/lockd/mon.c 2004-02-29 14:49:09.000000000 -0800 @@ -36,10 +36,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 int status; struct nsm_args args; - status = -EACCES; clnt = nsm_create(); - if (!clnt) + if (IS_ERR(clnt)) { + status = PTR_ERR(clnt); goto out; + } args.addr = host->h_addr.sin_addr.s_addr; args.proto= (host->h_proto<<1) | host->h_server; @@ -104,7 +105,7 @@ static struct rpc_clnt * nsm_create(void) { struct rpc_xprt *xprt; - struct rpc_clnt *clnt = NULL; + struct rpc_clnt *clnt; struct sockaddr_in sin; sin.sin_family = AF_INET; @@ -112,24 +113,23 @@ nsm_create(void) sin.sin_port = 0; xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); - if (!xprt) - goto out; + if (IS_ERR(xprt)) + return (struct rpc_clnt *)xprt; clnt = rpc_create_client(xprt, "localhost", &nsm_program, SM_VERSION, RPC_AUTH_NULL); - if (!clnt) + if (IS_ERR(clnt)) goto out_destroy; clnt->cl_softrtry = 1; clnt->cl_chatty = 1; clnt->cl_oneshot = 1; xprt->resvport = 1; /* NSM requires a reserved port */ -out: return clnt; out_destroy: xprt_destroy(xprt); - goto out; + return clnt; } /* diff -puN fs/nfs/inode.c~nfs-mount-return-useful-errors fs/nfs/inode.c --- 25/fs/nfs/inode.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/fs/nfs/inode.c 2004-02-29 14:49:09.000000000 -0800 @@ -371,13 +371,13 @@ nfs_create_client(struct nfs_server *ser /* create transport and client */ xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, &server->addr, &timeparms); - if (xprt == NULL) { + if (IS_ERR(xprt)) { printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); - goto out_fail; + return (struct rpc_clnt *)xprt; } clnt = rpc_create_client(xprt, server->hostname, &nfs_program, server->rpc_ops->version, data->pseudoflavor); - if (clnt == NULL) { + if (IS_ERR(clnt)) { printk(KERN_WARNING "NFS: cannot create RPC client.\n"); goto out_fail; } @@ -390,9 +390,8 @@ nfs_create_client(struct nfs_server *ser return clnt; out_fail: - if (xprt) - xprt_destroy(xprt); - return NULL; + xprt_destroy(xprt); + return clnt; } /* @@ -1489,17 +1488,19 @@ static int nfs4_fill_super(struct super_ down_write(&clp->cl_sem); if (clp->cl_rpcclient == NULL) { xprt = xprt_create_proto(proto, &server->addr, &timeparms); - if (xprt == NULL) { + if (IS_ERR(xprt)) { up_write(&clp->cl_sem); printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); + err = PTR_ERR(xprt); goto out_fail; } clnt = rpc_create_client(xprt, server->hostname, &nfs_program, server->rpc_ops->version, authflavour); - if (clnt == NULL) { + if (IS_ERR(clnt)) { up_write(&clp->cl_sem); printk(KERN_WARNING "NFS: cannot create RPC client.\n"); xprt_destroy(xprt); + err = PTR_ERR(clnt); goto out_fail; } clnt->cl_chatty = 1; @@ -1512,14 +1513,17 @@ static int nfs4_fill_super(struct super_ clear_bit(NFS4CLNT_OK, &clp->cl_state); list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); clnt = rpc_clone_client(clp->cl_rpcclient); - server->nfs4_state = clp; + if (!IS_ERR(clnt)) + server->nfs4_state = clp; up_write(&clp->cl_sem); clp = NULL; - if (clnt == NULL) { + if (IS_ERR(clnt)) { printk(KERN_WARNING "NFS: cannot create RPC client.\n"); + err = PTR_ERR(clnt); goto out_remove_list; } + err = -ENOMEM; if (server->nfs4_state->cl_idmap == NULL) { printk(KERN_WARNING "NFS: failed to create idmapper.\n"); goto out_shutdown; diff -puN fs/nfs/mount_clnt.c~nfs-mount-return-useful-errors fs/nfs/mount_clnt.c --- 25/fs/nfs/mount_clnt.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/fs/nfs/mount_clnt.c 2004-02-29 14:49:09.000000000 -0800 @@ -57,8 +57,9 @@ nfsroot_mount(struct sockaddr_in *addr, (unsigned)ntohl(addr->sin_addr.s_addr), path); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr)); - if (!(mnt_clnt = mnt_create(hostname, addr, version, protocol))) - return -EACCES; + mnt_clnt = mnt_create(hostname, addr, version, protocol); + if (IS_ERR(mnt_clnt)) + return PTR_ERR(mnt_clnt); call = (version == NFS_MNT3_VERSION) ? MOUNTPROC3_MNT : MNTPROC_MNT; status = rpc_call(mnt_clnt, call, path, &result, 0); @@ -72,13 +73,14 @@ mnt_create(char *hostname, struct sockad struct rpc_xprt *xprt; struct rpc_clnt *clnt; - if (!(xprt = xprt_create_proto(protocol, srvaddr, NULL))) - return NULL; + xprt = xprt_create_proto(protocol, srvaddr, NULL); + if (IS_ERR(xprt)) + return (struct rpc_clnt *)xprt; clnt = rpc_create_client(xprt, hostname, &mnt_program, version, - RPC_AUTH_NULL); - if (!clnt) { + RPC_AUTH_UNIX); + if (IS_ERR(clnt)) { xprt_destroy(xprt); } else { clnt->cl_softrtry = 1; diff -puN net/sunrpc/clnt.c~nfs-mount-return-useful-errors net/sunrpc/clnt.c --- 25/net/sunrpc/clnt.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/net/sunrpc/clnt.c 2004-02-29 14:49:09.000000000 -0800 @@ -102,19 +102,22 @@ rpc_create_client(struct rpc_xprt *xprt, { struct rpc_version *version; struct rpc_clnt *clnt = NULL; + int err; int len; dprintk("RPC: creating %s client for %s (xprt %p)\n", program->name, servname, xprt); + err = -EINVAL; if (!xprt) - goto out; + goto out_err; if (vers >= program->nrvers || !(version = program->version[vers])) - goto out; + goto out_err; + err = -ENOMEM; clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL); if (!clnt) - goto out_no_clnt; + goto out_err; memset(clnt, 0, sizeof(*clnt)); atomic_set(&clnt->cl_users, 0); atomic_set(&clnt->cl_count, 1); @@ -149,9 +152,11 @@ rpc_create_client(struct rpc_xprt *xprt, clnt->cl_rtt = &clnt->cl_rtt_default; rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); - if (rpc_setup_pipedir(clnt, program->pipe_dir_name) < 0) + err = rpc_setup_pipedir(clnt, program->pipe_dir_name); + if (err < 0) goto out_no_path; + err = -ENOMEM; if (!rpcauth_create(flavor, clnt)) { printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", flavor); @@ -163,20 +168,16 @@ rpc_create_client(struct rpc_xprt *xprt, if (clnt->cl_nodelen > UNX_MAXNODENAME) clnt->cl_nodelen = UNX_MAXNODENAME; memcpy(clnt->cl_nodename, system_utsname.nodename, clnt->cl_nodelen); -out: return clnt; -out_no_clnt: - printk(KERN_INFO "RPC: out of memory in rpc_create_client\n"); - goto out; out_no_auth: rpc_rmdir(clnt->cl_pathname); out_no_path: if (clnt->cl_server != clnt->cl_inline_name) kfree(clnt->cl_server); kfree(clnt); - clnt = NULL; - goto out; +out_err: + return ERR_PTR(err); } /* @@ -198,11 +199,10 @@ rpc_clone_client(struct rpc_clnt *clnt) atomic_inc(&new->cl_parent->cl_count); if (new->cl_auth) atomic_inc(&new->cl_auth->au_count); -out: return new; out_no_clnt: printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); - goto out; + return ERR_PTR(-ENOMEM); } /* diff -puN net/sunrpc/pmap_clnt.c~nfs-mount-return-useful-errors net/sunrpc/pmap_clnt.c --- 25/net/sunrpc/pmap_clnt.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/net/sunrpc/pmap_clnt.c 2004-02-29 14:49:09.000000000 -0800 @@ -65,9 +65,11 @@ rpc_getport(struct rpc_task *task, struc map->pm_binding = 1; spin_unlock(&pmap_lock); - task->tk_status = -EACCES; /* why set this? returns -EIO below */ - if (!(pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot))) + pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot); + if (IS_ERR(pmap_clnt)) { + task->tk_status = PTR_ERR(pmap_clnt); goto bailout; + } task->tk_status = 0; /* @@ -110,8 +112,9 @@ rpc_getport_external(struct sockaddr_in NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); - if (!(pmap_clnt = pmap_create(hostname, sin, prot))) - return -EACCES; + pmap_clnt = pmap_create(hostname, sin, prot); + if (IS_ERR(pmap_clnt)) + return PTR_ERR(pmap_clnt); /* Setup the call info struct */ status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0); @@ -161,16 +164,18 @@ rpc_register(u32 prog, u32 vers, int pro struct sockaddr_in sin; struct rpc_portmap map; struct rpc_clnt *pmap_clnt; - unsigned int error = 0; + int error = 0; dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n", prog, vers, prot, port); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if (!(pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP))) { - dprintk("RPC: couldn't create pmap client\n"); - return -EACCES; + pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP); + if (IS_ERR(pmap_clnt)) { + error = PTR_ERR(pmap_clnt); + dprintk("RPC: couldn't create pmap client. Error = %d\n", error); + return error; } map.pm_prog = prog; @@ -199,15 +204,16 @@ pmap_create(char *hostname, struct socka struct rpc_clnt *clnt; /* printk("pmap: create xprt\n"); */ - if (!(xprt = xprt_create_proto(proto, srvaddr, NULL))) - return NULL; + xprt = xprt_create_proto(proto, srvaddr, NULL); + if (IS_ERR(xprt)) + return (struct rpc_clnt *)xprt; xprt->addr.sin_port = htons(RPC_PMAP_PORT); /* printk("pmap: create clnt\n"); */ clnt = rpc_create_client(xprt, hostname, &pmap_program, RPC_PMAP_VERSION, RPC_AUTH_NULL); - if (!clnt) { + if (IS_ERR(clnt)) { xprt_destroy(xprt); } else { clnt->cl_softrtry = 1; diff -puN net/sunrpc/xprt.c~nfs-mount-return-useful-errors net/sunrpc/xprt.c --- 25/net/sunrpc/xprt.c~nfs-mount-return-useful-errors 2004-02-29 14:49:09.000000000 -0800 +++ 25-akpm/net/sunrpc/xprt.c 2004-02-29 14:49:09.000000000 -0800 @@ -1423,7 +1423,7 @@ xprt_setup(int proto, struct sockaddr_in proto == IPPROTO_UDP? "UDP" : "TCP"); if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) - return NULL; + return ERR_PTR(-ENOMEM); memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */ xprt->addr = *ap; @@ -1601,16 +1601,11 @@ xprt_create_proto(int proto, struct sock struct rpc_xprt *xprt; xprt = xprt_setup(proto, sap, to); - if (!xprt) - goto out_bad; - - dprintk("RPC: xprt_create_proto created xprt %p\n", xprt); + if (IS_ERR(xprt)) + dprintk("RPC: xprt_create_proto failed\n"); + else + dprintk("RPC: xprt_create_proto created xprt %p\n", xprt); return xprt; - out_bad: - dprintk("RPC: xprt_create_proto failed\n"); - if (xprt) - kfree(xprt); - return NULL; } /* _