Commit 72cffe4f authored by Trond Myklebust's avatar Trond Myklebust

RPC,NFSv2/v3/v4: Ensure that xprt_create_proto() and rpc_create_client() return

     full error codes. Should allow the "mount" program to print more useful error
     diagnostics.
parent 0e459649
...@@ -188,14 +188,14 @@ nlm_bind_host(struct nlm_host *host) ...@@ -188,14 +188,14 @@ nlm_bind_host(struct nlm_host *host)
} }
} else { } else {
xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL);
if (xprt == NULL) if (IS_ERR(xprt))
goto forgetit; goto forgetit;
xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
clnt = rpc_create_client(xprt, host->h_name, &nlm_program, clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
host->h_version, host->h_authflavor); host->h_version, host->h_authflavor);
if (clnt == NULL) { if (IS_ERR(clnt)) {
xprt_destroy(xprt); xprt_destroy(xprt);
goto forgetit; goto forgetit;
} }
......
...@@ -36,10 +36,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) ...@@ -36,10 +36,11 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res)
int status; int status;
struct nsm_args args; struct nsm_args args;
status = -EACCES;
clnt = nsm_create(); clnt = nsm_create();
if (!clnt) if (IS_ERR(clnt)) {
status = PTR_ERR(clnt);
goto out; goto out;
}
args.addr = host->h_addr.sin_addr.s_addr; args.addr = host->h_addr.sin_addr.s_addr;
args.proto= (host->h_proto<<1) | host->h_server; args.proto= (host->h_proto<<1) | host->h_server;
...@@ -104,7 +105,7 @@ static struct rpc_clnt * ...@@ -104,7 +105,7 @@ static struct rpc_clnt *
nsm_create(void) nsm_create(void)
{ {
struct rpc_xprt *xprt; struct rpc_xprt *xprt;
struct rpc_clnt *clnt = NULL; struct rpc_clnt *clnt;
struct sockaddr_in sin; struct sockaddr_in sin;
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
...@@ -112,24 +113,23 @@ nsm_create(void) ...@@ -112,24 +113,23 @@ nsm_create(void)
sin.sin_port = 0; sin.sin_port = 0;
xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
if (!xprt) if (IS_ERR(xprt))
goto out; return (struct rpc_clnt *)xprt;
clnt = rpc_create_client(xprt, "localhost", clnt = rpc_create_client(xprt, "localhost",
&nsm_program, SM_VERSION, &nsm_program, SM_VERSION,
RPC_AUTH_NULL); RPC_AUTH_NULL);
if (!clnt) if (IS_ERR(clnt))
goto out_destroy; goto out_destroy;
clnt->cl_softrtry = 1; clnt->cl_softrtry = 1;
clnt->cl_chatty = 1; clnt->cl_chatty = 1;
clnt->cl_oneshot = 1; clnt->cl_oneshot = 1;
xprt->resvport = 1; /* NSM requires a reserved port */ xprt->resvport = 1; /* NSM requires a reserved port */
out:
return clnt; return clnt;
out_destroy: out_destroy:
xprt_destroy(xprt); xprt_destroy(xprt);
goto out; return clnt;
} }
/* /*
......
...@@ -371,13 +371,13 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) ...@@ -371,13 +371,13 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
/* create transport and client */ /* create transport and client */
xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP, xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
&server->addr, &timeparms); &server->addr, &timeparms);
if (xprt == NULL) { if (IS_ERR(xprt)) {
printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); 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, clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
server->rpc_ops->version, data->pseudoflavor); server->rpc_ops->version, data->pseudoflavor);
if (clnt == NULL) { if (IS_ERR(clnt)) {
printk(KERN_WARNING "NFS: cannot create RPC client.\n"); printk(KERN_WARNING "NFS: cannot create RPC client.\n");
goto out_fail; goto out_fail;
} }
...@@ -390,9 +390,8 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) ...@@ -390,9 +390,8 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
return clnt; return clnt;
out_fail: out_fail:
if (xprt)
xprt_destroy(xprt); xprt_destroy(xprt);
return NULL; return clnt;
} }
/* /*
...@@ -1492,17 +1491,19 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1492,17 +1491,19 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
down_write(&clp->cl_sem); down_write(&clp->cl_sem);
if (clp->cl_rpcclient == NULL) { if (clp->cl_rpcclient == NULL) {
xprt = xprt_create_proto(proto, &server->addr, &timeparms); xprt = xprt_create_proto(proto, &server->addr, &timeparms);
if (xprt == NULL) { if (IS_ERR(xprt)) {
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
printk(KERN_WARNING "NFS: cannot create RPC transport.\n"); printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
err = PTR_ERR(xprt);
goto out_fail; goto out_fail;
} }
clnt = rpc_create_client(xprt, server->hostname, &nfs_program, clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
server->rpc_ops->version, authflavour); server->rpc_ops->version, authflavour);
if (clnt == NULL) { if (IS_ERR(clnt)) {
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
printk(KERN_WARNING "NFS: cannot create RPC client.\n"); printk(KERN_WARNING "NFS: cannot create RPC client.\n");
xprt_destroy(xprt); xprt_destroy(xprt);
err = PTR_ERR(clnt);
goto out_fail; goto out_fail;
} }
clnt->cl_chatty = 1; clnt->cl_chatty = 1;
...@@ -1515,14 +1516,17 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, ...@@ -1515,14 +1516,17 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
clear_bit(NFS4CLNT_OK, &clp->cl_state); clear_bit(NFS4CLNT_OK, &clp->cl_state);
list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
clnt = rpc_clone_client(clp->cl_rpcclient); clnt = rpc_clone_client(clp->cl_rpcclient);
if (!IS_ERR(clnt))
server->nfs4_state = clp; server->nfs4_state = clp;
up_write(&clp->cl_sem); up_write(&clp->cl_sem);
clp = NULL; clp = NULL;
if (clnt == NULL) { if (IS_ERR(clnt)) {
printk(KERN_WARNING "NFS: cannot create RPC client.\n"); printk(KERN_WARNING "NFS: cannot create RPC client.\n");
err = PTR_ERR(clnt);
goto out_remove_list; goto out_remove_list;
} }
err = -ENOMEM;
if (server->nfs4_state->cl_idmap == NULL) { if (server->nfs4_state->cl_idmap == NULL) {
printk(KERN_WARNING "NFS: failed to create idmapper.\n"); printk(KERN_WARNING "NFS: failed to create idmapper.\n");
goto out_shutdown; goto out_shutdown;
......
...@@ -57,8 +57,9 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh, ...@@ -57,8 +57,9 @@ nfsroot_mount(struct sockaddr_in *addr, char *path, struct nfs_fh *fh,
(unsigned)ntohl(addr->sin_addr.s_addr), path); (unsigned)ntohl(addr->sin_addr.s_addr), path);
sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr)); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr->sin_addr.s_addr));
if (!(mnt_clnt = mnt_create(hostname, addr, version, protocol))) mnt_clnt = mnt_create(hostname, addr, version, protocol);
return -EACCES; if (IS_ERR(mnt_clnt))
return PTR_ERR(mnt_clnt);
call = (version == NFS_MNT3_VERSION) ? MOUNTPROC3_MNT : MNTPROC_MNT; call = (version == NFS_MNT3_VERSION) ? MOUNTPROC3_MNT : MNTPROC_MNT;
status = rpc_call(mnt_clnt, call, path, &result, 0); status = rpc_call(mnt_clnt, call, path, &result, 0);
...@@ -72,13 +73,14 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, ...@@ -72,13 +73,14 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
struct rpc_xprt *xprt; struct rpc_xprt *xprt;
struct rpc_clnt *clnt; struct rpc_clnt *clnt;
if (!(xprt = xprt_create_proto(protocol, srvaddr, NULL))) xprt = xprt_create_proto(protocol, srvaddr, NULL);
return NULL; if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
clnt = rpc_create_client(xprt, hostname, clnt = rpc_create_client(xprt, hostname,
&mnt_program, version, &mnt_program, version,
RPC_AUTH_NULL); RPC_AUTH_UNIX);
if (!clnt) { if (IS_ERR(clnt)) {
xprt_destroy(xprt); xprt_destroy(xprt);
} else { } else {
clnt->cl_softrtry = 1; clnt->cl_softrtry = 1;
......
...@@ -102,19 +102,22 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, ...@@ -102,19 +102,22 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
{ {
struct rpc_version *version; struct rpc_version *version;
struct rpc_clnt *clnt = NULL; struct rpc_clnt *clnt = NULL;
int err;
int len; int len;
dprintk("RPC: creating %s client for %s (xprt %p)\n", dprintk("RPC: creating %s client for %s (xprt %p)\n",
program->name, servname, xprt); program->name, servname, xprt);
err = -EINVAL;
if (!xprt) if (!xprt)
goto out; goto out_err;
if (vers >= program->nrvers || !(version = program->version[vers])) if (vers >= program->nrvers || !(version = program->version[vers]))
goto out; goto out_err;
err = -ENOMEM;
clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL); clnt = (struct rpc_clnt *) kmalloc(sizeof(*clnt), GFP_KERNEL);
if (!clnt) if (!clnt)
goto out_no_clnt; goto out_err;
memset(clnt, 0, sizeof(*clnt)); memset(clnt, 0, sizeof(*clnt));
atomic_set(&clnt->cl_users, 0); atomic_set(&clnt->cl_users, 0);
atomic_set(&clnt->cl_count, 1); atomic_set(&clnt->cl_count, 1);
...@@ -149,9 +152,11 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, ...@@ -149,9 +152,11 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
clnt->cl_rtt = &clnt->cl_rtt_default; clnt->cl_rtt = &clnt->cl_rtt_default;
rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); 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; goto out_no_path;
err = -ENOMEM;
if (!rpcauth_create(flavor, clnt)) { if (!rpcauth_create(flavor, clnt)) {
printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n", printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n",
flavor); flavor);
...@@ -163,20 +168,16 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname, ...@@ -163,20 +168,16 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
if (clnt->cl_nodelen > UNX_MAXNODENAME) if (clnt->cl_nodelen > UNX_MAXNODENAME)
clnt->cl_nodelen = UNX_MAXNODENAME; clnt->cl_nodelen = UNX_MAXNODENAME;
memcpy(clnt->cl_nodename, system_utsname.nodename, clnt->cl_nodelen); memcpy(clnt->cl_nodename, system_utsname.nodename, clnt->cl_nodelen);
out:
return clnt; return clnt;
out_no_clnt:
printk(KERN_INFO "RPC: out of memory in rpc_create_client\n");
goto out;
out_no_auth: out_no_auth:
rpc_rmdir(clnt->cl_pathname); rpc_rmdir(clnt->cl_pathname);
out_no_path: out_no_path:
if (clnt->cl_server != clnt->cl_inline_name) if (clnt->cl_server != clnt->cl_inline_name)
kfree(clnt->cl_server); kfree(clnt->cl_server);
kfree(clnt); kfree(clnt);
clnt = NULL; out_err:
goto out; return ERR_PTR(err);
} }
/* /*
...@@ -198,11 +199,10 @@ rpc_clone_client(struct rpc_clnt *clnt) ...@@ -198,11 +199,10 @@ rpc_clone_client(struct rpc_clnt *clnt)
atomic_inc(&new->cl_parent->cl_count); atomic_inc(&new->cl_parent->cl_count);
if (new->cl_auth) if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count); atomic_inc(&new->cl_auth->au_count);
out:
return new; return new;
out_no_clnt: out_no_clnt:
printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
goto out; return ERR_PTR(-ENOMEM);
} }
/* /*
......
...@@ -65,9 +65,11 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) ...@@ -65,9 +65,11 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
map->pm_binding = 1; map->pm_binding = 1;
spin_unlock(&pmap_lock); spin_unlock(&pmap_lock);
task->tk_status = -EACCES; /* why set this? returns -EIO below */ pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot);
if (!(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; goto bailout;
}
task->tk_status = 0; task->tk_status = 0;
/* /*
...@@ -110,8 +112,9 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot) ...@@ -110,8 +112,9 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr));
if (!(pmap_clnt = pmap_create(hostname, sin, prot))) pmap_clnt = pmap_create(hostname, sin, prot);
return -EACCES; if (IS_ERR(pmap_clnt))
return PTR_ERR(pmap_clnt);
/* Setup the call info struct */ /* Setup the call info struct */
status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0); status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0);
...@@ -161,16 +164,18 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) ...@@ -161,16 +164,18 @@ rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
struct sockaddr_in sin; struct sockaddr_in sin;
struct rpc_portmap map; struct rpc_portmap map;
struct rpc_clnt *pmap_clnt; struct rpc_clnt *pmap_clnt;
unsigned int error = 0; int error = 0;
dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n", dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n",
prog, vers, prot, port); prog, vers, prot, port);
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (!(pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP))) { pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP);
dprintk("RPC: couldn't create pmap client\n"); if (IS_ERR(pmap_clnt)) {
return -EACCES; error = PTR_ERR(pmap_clnt);
dprintk("RPC: couldn't create pmap client. Error = %d\n", error);
return error;
} }
map.pm_prog = prog; map.pm_prog = prog;
...@@ -199,15 +204,16 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto) ...@@ -199,15 +204,16 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
struct rpc_clnt *clnt; struct rpc_clnt *clnt;
/* printk("pmap: create xprt\n"); */ /* printk("pmap: create xprt\n"); */
if (!(xprt = xprt_create_proto(proto, srvaddr, NULL))) xprt = xprt_create_proto(proto, srvaddr, NULL);
return NULL; if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
xprt->addr.sin_port = htons(RPC_PMAP_PORT); xprt->addr.sin_port = htons(RPC_PMAP_PORT);
/* printk("pmap: create clnt\n"); */ /* printk("pmap: create clnt\n"); */
clnt = rpc_create_client(xprt, hostname, clnt = rpc_create_client(xprt, hostname,
&pmap_program, RPC_PMAP_VERSION, &pmap_program, RPC_PMAP_VERSION,
RPC_AUTH_NULL); RPC_AUTH_NULL);
if (!clnt) { if (IS_ERR(clnt)) {
xprt_destroy(xprt); xprt_destroy(xprt);
} else { } else {
clnt->cl_softrtry = 1; clnt->cl_softrtry = 1;
......
...@@ -1421,7 +1421,7 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to) ...@@ -1421,7 +1421,7 @@ xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to)
proto == IPPROTO_UDP? "UDP" : "TCP"); proto == IPPROTO_UDP? "UDP" : "TCP");
if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) if ((xprt = kmalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL)
return NULL; return ERR_PTR(-ENOMEM);
memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */ memset(xprt, 0, sizeof(*xprt)); /* Nnnngh! */
xprt->addr = *ap; xprt->addr = *ap;
...@@ -1597,16 +1597,11 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to) ...@@ -1597,16 +1597,11 @@ xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to)
struct rpc_xprt *xprt; struct rpc_xprt *xprt;
xprt = xprt_setup(proto, sap, to); xprt = xprt_setup(proto, sap, to);
if (!xprt) if (IS_ERR(xprt))
goto out_bad; dprintk("RPC: xprt_create_proto failed\n");
else
dprintk("RPC: xprt_create_proto created xprt %p\n", xprt); dprintk("RPC: xprt_create_proto created xprt %p\n", xprt);
return xprt; return xprt;
out_bad:
dprintk("RPC: xprt_create_proto failed\n");
if (xprt)
kfree(xprt);
return NULL;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment