]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/sunrpc/rpcb_clnt.c
SUNRPC: Fix rpcauth_prune_expired
[mv-sheeva.git] / net / sunrpc / rpcb_clnt.c
index 0fa1086cf9911d198f57b584cc62bca4a842e0d7..41013dd66ac3f3e61e4823ef853911e179efc46b 100644 (file)
@@ -197,12 +197,8 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen,
                return error;
        }
 
-       if (!result) {
-               dprintk("RPC:       registration failed\n");
+       if (!result)
                return -EACCES;
-       }
-
-       dprintk("RPC:       registration succeeded\n");
        return 0;
 }
 
@@ -464,6 +460,28 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
        return rpc_run_task(&task_setup_data);
 }
 
+/*
+ * In the case where rpc clients have been cloned, we want to make
+ * sure that we use the program number/version etc of the actual
+ * owner of the xprt. To do so, we walk back up the tree of parents
+ * to find whoever created the transport and/or whoever has the
+ * autobind flag set.
+ */
+static struct rpc_clnt *rpcb_find_transport_owner(struct rpc_clnt *clnt)
+{
+       struct rpc_clnt *parent = clnt->cl_parent;
+
+       while (parent != clnt) {
+               if (parent->cl_xprt != clnt->cl_xprt)
+                       break;
+               if (clnt->cl_autobind)
+                       break;
+               clnt = parent;
+               parent = parent->cl_parent;
+       }
+       return clnt;
+}
+
 /**
  * rpcb_getport_async - obtain the port for a given RPC service on a given host
  * @task: task that is waiting for portmapper request
@@ -473,10 +491,10 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi
  */
 void rpcb_getport_async(struct rpc_task *task)
 {
-       struct rpc_clnt *clnt = task->tk_client;
+       struct rpc_clnt *clnt;
        struct rpc_procinfo *proc;
        u32 bind_version;
-       struct rpc_xprt *xprt = task->tk_xprt;
+       struct rpc_xprt *xprt;
        struct rpc_clnt *rpcb_clnt;
        static struct rpcbind_args *map;
        struct rpc_task *child;
@@ -485,13 +503,13 @@ void rpcb_getport_async(struct rpc_task *task)
        size_t salen;
        int status;
 
+       clnt = rpcb_find_transport_owner(task->tk_client);
+       xprt = clnt->cl_xprt;
+
        dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
                task->tk_pid, __func__,
                clnt->cl_server, clnt->cl_prog, clnt->cl_vers, xprt->prot);
 
-       /* Autobind on cloned rpc clients is discouraged */
-       BUG_ON(clnt->cl_parent != clnt);
-
        /* Put self on the wait queue to ensure we get notified if
         * some other task is already attempting to bind the port */
        rpc_sleep_on(&xprt->binding, task, NULL);
@@ -553,7 +571,7 @@ void rpcb_getport_async(struct rpc_task *task)
                status = -ENOMEM;
                dprintk("RPC: %5u %s: no memory available\n",
                        task->tk_pid, __func__);
-               goto bailout_nofree;
+               goto bailout_release_client;
        }
        map->r_prog = clnt->cl_prog;
        map->r_vers = clnt->cl_vers;
@@ -573,11 +591,13 @@ void rpcb_getport_async(struct rpc_task *task)
                        task->tk_pid, __func__);
                return;
        }
-       rpc_put_task(child);
 
-       task->tk_xprt->stat.bind_count++;
+       xprt->stat.bind_count++;
+       rpc_put_task(child);
        return;
 
+bailout_release_client:
+       rpc_release_client(rpcb_clnt);
 bailout_nofree:
        rpcb_wake_rpcbind_waiters(xprt, status);
        task->tk_status = status;
@@ -628,7 +648,7 @@ static void rpcb_getport_done(struct rpc_task *child, void *data)
 static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p,
                               struct rpcbind_args *rpcb)
 {
-       dprintk("RPC:       rpcb_encode_mapping(%u, %u, %d, %u)\n",
+       dprintk("RPC:       encoding rpcb request (%u, %u, %d, %u)\n",
                        rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port);
        *p++ = htonl(rpcb->r_prog);
        *p++ = htonl(rpcb->r_vers);
@@ -643,7 +663,7 @@ static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p,
                               unsigned short *portp)
 {
        *portp = (unsigned short) ntohl(*p++);
-       dprintk("RPC:       rpcb_decode_getport result %u\n",
+       dprintk("RPC:       rpcb getport result: %u\n",
                        *portp);
        return 0;
 }
@@ -652,7 +672,7 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
                           unsigned int *boolp)
 {
        *boolp = (unsigned int) ntohl(*p++);
-       dprintk("RPC:       rpcb_decode_set: call %s\n",
+       dprintk("RPC:       rpcb set/unset call %s\n",
                        (*boolp ? "succeeded" : "failed"));
        return 0;
 }
@@ -660,7 +680,7 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p,
 static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p,
                               struct rpcbind_args *rpcb)
 {
-       dprintk("RPC:       rpcb_encode_getaddr(%u, %u, %s)\n",
+       dprintk("RPC:       encoding rpcb request (%u, %u, %s)\n",
                        rpcb->r_prog, rpcb->r_vers, rpcb->r_addr);
        *p++ = htonl(rpcb->r_prog);
        *p++ = htonl(rpcb->r_vers);