SUNRPC: Fix an rpcbind breakage for the case of IPv6 lookups
Trond Myklebust [Tue, 1 Jul 2008 19:20:55 +0000 (15:20 -0400)]
Now that rpcb_next_version has been split into an IPv4 version and an IPv6
version, we Oops when rpcb_call_async attempts to look up the IPv6-specific
RPC procedure in rpcb_next_version.

Fix the Oops simply by having rpcb_getport_async pass the correct RPC
procedure as an argument.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

net/sunrpc/rpcb_clnt.c

index 21c698d..e6fb21b 100644 (file)
@@ -243,10 +243,10 @@ int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
 }
 EXPORT_SYMBOL_GPL(rpcb_getport_sync);
 
-static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, int version)
+static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
 {
        struct rpc_message msg = {
-               .rpc_proc = rpcb_next_version[version].rpc_proc,
+               .rpc_proc = proc,
                .rpc_argp = map,
                .rpc_resp = &map->r_port,
        };
@@ -271,6 +271,7 @@ 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_procinfo *proc;
        u32 bind_version;
        struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_clnt *rpcb_clnt;
@@ -280,7 +281,6 @@ void rpcb_getport_async(struct rpc_task *task)
        struct sockaddr *sap = (struct sockaddr *)&addr;
        size_t salen;
        int status;
-       struct rpcb_info *info;
 
        dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
                task->tk_pid, __func__,
@@ -313,10 +313,12 @@ void rpcb_getport_async(struct rpc_task *task)
        /* Don't ever use rpcbind v2 for AF_INET6 requests */
        switch (sap->sa_family) {
        case AF_INET:
-               info = rpcb_next_version;
+               proc = rpcb_next_version[xprt->bind_index].rpc_proc;
+               bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
                break;
        case AF_INET6:
-               info = rpcb_next_version6;
+               proc = rpcb_next_version6[xprt->bind_index].rpc_proc;
+               bind_version = rpcb_next_version6[xprt->bind_index].rpc_vers;
                break;
        default:
                status = -EAFNOSUPPORT;
@@ -324,14 +326,13 @@ void rpcb_getport_async(struct rpc_task *task)
                                task->tk_pid, __func__);
                goto bailout_nofree;
        }
-       if (info[xprt->bind_index].rpc_proc == NULL) {
+       if (proc == NULL) {
                xprt->bind_index = 0;
                status = -EPFNOSUPPORT;
                dprintk("RPC: %5u %s: no more getport versions available\n",
                        task->tk_pid, __func__);
                goto bailout_nofree;
        }
-       bind_version = info[xprt->bind_index].rpc_vers;
 
        dprintk("RPC: %5u %s: trying rpcbind version %u\n",
                task->tk_pid, __func__, bind_version);
@@ -361,7 +362,7 @@ void rpcb_getport_async(struct rpc_task *task)
        map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR);
        map->r_owner = RPCB_OWNER_STRING;       /* ignored for GETADDR */
 
-       child = rpcb_call_async(rpcb_clnt, map, xprt->bind_index);
+       child = rpcb_call_async(rpcb_clnt, map, proc);
        rpc_release_client(rpcb_clnt);
        if (IS_ERR(child)) {
                status = -EIO;