]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sunrpc/clnt.c
Merge branch 'for-2.6.25' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerp...
[linux-2.6-omap-h63xx.git] / net / sunrpc / clnt.c
index e1553cf2a68f7cbde1b56d6426ef06aa9a127b34..76be83ee4b04a59f90f99a3afc69ce8889a7ff39 100644 (file)
@@ -127,7 +127,14 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        struct rpc_clnt         *clnt = NULL;
        struct rpc_auth         *auth;
        int err;
-       int len;
+       size_t len;
+
+       /* sanity check the name before trying to print it */
+       err = -EINVAL;
+       len = strlen(servname);
+       if (len > RPC_MAXNETNAMELEN)
+               goto out_no_rpciod;
+       len++;
 
        dprintk("RPC:       creating %s client for %s (xprt %p)\n",
                        program->name, servname, xprt);
@@ -148,7 +155,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
        clnt->cl_parent = clnt;
 
        clnt->cl_server = clnt->cl_inline_name;
-       len = strlen(servname) + 1;
        if (len > sizeof(clnt->cl_inline_name)) {
                char *buf = kmalloc(len, GFP_KERNEL);
                if (buf != 0)
@@ -234,12 +240,31 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 {
        struct rpc_xprt *xprt;
        struct rpc_clnt *clnt;
+       struct xprt_create xprtargs = {
+               .ident = args->protocol,
+               .srcaddr = args->saddress,
+               .dstaddr = args->address,
+               .addrlen = args->addrsize,
+               .timeout = args->timeout
+       };
+       char servername[20];
 
-       xprt = xprt_create_transport(args->protocol, args->address,
-                                       args->addrsize, args->timeout);
+       xprt = xprt_create_transport(&xprtargs);
        if (IS_ERR(xprt))
                return (struct rpc_clnt *)xprt;
 
+       /*
+        * If the caller chooses not to specify a hostname, whip
+        * up a string representation of the passed-in address.
+        */
+       if (args->servername == NULL) {
+               struct sockaddr_in *addr =
+                                       (struct sockaddr_in *) args->address;
+               snprintf(servername, sizeof(servername), NIPQUAD_FMT,
+                       NIPQUAD(addr->sin_addr.s_addr));
+               args->servername = servername;
+       }
+
        /*
         * By default, kernel RPC client connects from a reserved port.
         * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters,
@@ -250,9 +275,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT)
                xprt->resvport = 0;
 
-       dprintk("RPC:       creating %s client for %s (xprt %p)\n",
-                       args->program->name, args->servername, xprt);
-
        clnt = rpc_new_client(xprt, args->servername, args->program,
                                args->version, args->authflavor);
        if (IS_ERR(clnt))
@@ -420,7 +442,7 @@ rpc_release_client(struct rpc_clnt *clnt)
  */
 struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
                                      struct rpc_program *program,
-                                     int vers)
+                                     u32 vers)
 {
        struct rpc_clnt *clnt;
        struct rpc_version *version;
@@ -824,8 +846,7 @@ call_allocate(struct rpc_task *task)
        dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
 
        if (RPC_IS_ASYNC(task) || !signalled()) {
-               xprt_release(task);
-               task->tk_action = call_reserve;
+               task->tk_action = call_allocate;
                rpc_delay(task, HZ>>4);
                return;
        }
@@ -852,6 +873,7 @@ rpc_xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
        buf->head[0].iov_len = len;
        buf->tail[0].iov_len = 0;
        buf->page_len = 0;
+       buf->flags = 0;
        buf->len = 0;
        buf->buflen = len;
 }
@@ -885,10 +907,8 @@ call_encode(struct rpc_task *task)
        if (encode == NULL)
                return;
 
-       lock_kernel();
        task->tk_status = rpcauth_wrap_req(task, encode, req, p,
                        task->tk_msg.rpc_argp);
-       unlock_kernel();
        if (task->tk_status == -ENOMEM) {
                /* XXX: Is this sane? */
                rpc_delay(task, 3*HZ);
@@ -920,7 +940,7 @@ call_bind(struct rpc_task *task)
 static void
 call_bind_status(struct rpc_task *task)
 {
-       int status = -EACCES;
+       int status = -EIO;
 
        if (task->tk_status >= 0) {
                dprint_status(task);
@@ -930,9 +950,20 @@ call_bind_status(struct rpc_task *task)
        }
 
        switch (task->tk_status) {
+       case -EAGAIN:
+               dprintk("RPC: %5u rpcbind waiting for another request "
+                               "to finish\n", task->tk_pid);
+               /* avoid busy-waiting here -- could be a network outage. */
+               rpc_delay(task, 5*HZ);
+               goto retry_timeout;
        case -EACCES:
                dprintk("RPC: %5u remote rpcbind: RPC program/version "
                                "unavailable\n", task->tk_pid);
+               /* fail immediately if this is an RPC ping */
+               if (task->tk_msg.rpc_proc->p_proc == 0) {
+                       status = -EOPNOTSUPP;
+                       break;
+               }
                rpc_delay(task, 3*HZ);
                goto retry_timeout;
        case -ETIMEDOUT:
@@ -940,6 +971,7 @@ call_bind_status(struct rpc_task *task)
                                task->tk_pid);
                goto retry_timeout;
        case -EPFNOSUPPORT:
+               /* server doesn't support any rpcbind version we know of */
                dprintk("RPC: %5u remote rpcbind service unavailable\n",
                                task->tk_pid);
                break;
@@ -952,7 +984,6 @@ call_bind_status(struct rpc_task *task)
        default:
                dprintk("RPC: %5u unrecognized rpcbind error (%d)\n",
                                task->tk_pid, -task->tk_status);
-               status = -EIO;
        }
 
        rpc_exit(task, status);
@@ -1219,10 +1250,8 @@ call_decode(struct rpc_task *task)
        task->tk_action = rpc_exit_task;
 
        if (decode) {
-               lock_kernel();
                task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
                                                      task->tk_msg.rpc_resp);
-               unlock_kernel();
        }
        dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
                        task->tk_status);
@@ -1242,7 +1271,6 @@ call_refresh(struct rpc_task *task)
 {
        dprint_status(task);
 
-       xprt_release(task);     /* Must do to obtain new XID */
        task->tk_action = call_refreshresult;
        task->tk_status = 0;
        task->tk_client->cl_stats->rpcauthrefresh++;
@@ -1360,6 +1388,8 @@ call_verify(struct rpc_task *task)
                        dprintk("RPC: %5u %s: retry stale creds\n",
                                        task->tk_pid, __FUNCTION__);
                        rpcauth_invalcred(task);
+                       /* Ensure we obtain a new XID! */
+                       xprt_release(task);
                        task->tk_action = call_refresh;
                        goto out_retry;
                case RPC_AUTH_BADCRED:
@@ -1508,13 +1538,18 @@ void rpc_show_tasks(void)
                spin_lock(&clnt->cl_lock);
                list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
                        const char *rpc_waitq = "none";
+                       int proc;
+
+                       if (t->tk_msg.rpc_proc)
+                               proc = t->tk_msg.rpc_proc->p_proc;
+                       else
+                               proc = -1;
 
                        if (RPC_IS_QUEUED(t))
                                rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
 
                        printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
-                               t->tk_pid,
-                               (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
+                               t->tk_pid, proc,
                                t->tk_flags, t->tk_status,
                                t->tk_client,
                                (t->tk_client ? t->tk_client->cl_prog : 0),