NFS: advertise only supported callback netids
authorChuck Lever <chuck.lever@oracle.com>
Wed, 12 Mar 2014 16:51:47 +0000 (12:51 -0400)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Mon, 17 Mar 2014 20:04:54 +0000 (16:04 -0400)
NFSv4.0 clients use the SETCLIENTID operation to inform NFS servers
how to contact a client's callback service.  If a server cannot
contact a client's callback service, that server will not delegate
to that client, which results in a performance loss.

Our client advertises "rdma" as the callback netid when the forward
channel is "rdma".  But our client always starts only "tcp" and
"tcp6" callback services.

Instead of advertising the forward channel netid, advertise "tcp"
or "tcp6" as the callback netid, based on the value of the
clientaddr mount option, since those are what our client currently
supports.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=69171
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
fs/nfs/nfs4proc.c

index 025116c66feff85f2550184069a1b67b008feaf9..c866e325577fb3a3cc4c379cfc81d2a170f133ab 100644 (file)
@@ -4881,6 +4881,20 @@ nfs4_init_uniform_client_string(const struct nfs_client *clp,
                                nodename);
 }
 
+/*
+ * nfs4_callback_up_net() starts only "tcp" and "tcp6" callback
+ * services.  Advertise one based on the address family of the
+ * clientaddr.
+ */
+static unsigned int
+nfs4_init_callback_netid(const struct nfs_client *clp, char *buf, size_t len)
+{
+       if (strchr(clp->cl_ipaddr, ':') != NULL)
+               return scnprintf(buf, len, "tcp6");
+       else
+               return scnprintf(buf, len, "tcp");
+}
+
 /**
  * nfs4_proc_setclientid - Negotiate client ID
  * @clp: state data structure
@@ -4922,12 +4936,10 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                                                setclientid.sc_name,
                                                sizeof(setclientid.sc_name));
        /* cb_client4 */
-       rcu_read_lock();
-       setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
-                               sizeof(setclientid.sc_netid), "%s",
-                               rpc_peeraddr2str(clp->cl_rpcclient,
-                                                       RPC_DISPLAY_NETID));
-       rcu_read_unlock();
+       setclientid.sc_netid_len =
+                               nfs4_init_callback_netid(clp,
+                                               setclientid.sc_netid,
+                                               sizeof(setclientid.sc_netid));
        setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
                                sizeof(setclientid.sc_uaddr), "%s.%u.%u",
                                clp->cl_ipaddr, port >> 8, port & 255);