@@ -218,6 +218,11 @@ struct nfs4_add_xprt_data {
struct nfs_client *clp;
struct rpc_cred *cred;
};
+extern int nfs4_test_session_trunk_and_add_xprt(struct rpc_clnt *clnt,
+ struct rpc_xprt_switch *xps,
+ struct rpc_xprt *xprt,
+ void *data);
+
extern const struct dentry_operations nfs4_dentry_operations;
/* dir.c */
@@ -1041,6 +1041,43 @@ out:
return error;
}
+/**
+ * Add rpc_xprts to an existing RPC client
+ */
+void nfs4_try_multiaddr(struct nfs_parsed_mount_data *mnt,
+ struct nfs_client *clp)
+{
+ struct multi_addr *multip = mnt->multiaddrs;
+ struct nfs4_add_xprt_data xprtdata = {
+ .clp = clp,
+ };
+ int i;
+
+ dprintk("NFS: Try adding %u multi addrs\n", mnt->num_multi);
+
+ if (mnt->num_multi == 0)
+ return;
+
+ xprtdata.cred = nfs4_get_clid_cred(clp);
+
+ for (i = 0; i < mnt->num_multi; i++) {
+ struct xprt_create xprt_args = {
+ .ident = XPRT_TRANSPORT_TCP,
+ .net = mnt->net,
+ .dstaddr = (struct sockaddr *)&multip->addr,
+ .addrlen = multip->addrlen,
+ .servername = multip->hostname,
+ };
+ /* Add this address as an alias */
+ rpc_clnt_add_xprt(clp->cl_rpcclient, &xprt_args,
+ nfs4_test_session_trunk_and_add_xprt,
+ &xprtdata);
+ multip++;
+ }
+ if (xprtdata.cred)
+ put_rpccred(xprtdata.cred);
+}
+
/*
* Create a version 4 volume record
*/
@@ -1097,6 +1134,8 @@ static int nfs4_init_server(struct nfs_server *server,
error = nfs_init_server_rpcclient(server, &timeparms,
data->selected_flavor);
+ if (!error)
+ nfs4_try_multiaddr(data, server->nfs_client);
error:
/* Done */
dprintk("<-- nfs4_init_server() = %d\n", error);
@@ -7207,6 +7207,43 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL);
}
+/**
+ * nfs4_test_session_trunk_and_add_xprt - Test for session trunking with a
+ * synchronous exchange_id call, and add a new transport to the rpc_clnt
+ *
+ * @clnt: struct rpc_clnt to get new transport
+ * @xps: the rpc_xprt_switch to hold the new transport
+ * @xprt: the rpc_xprt to test
+ * @data: call data for _nfs4_proc_exchange_id.
+ *
+ */
+int nfs4_test_session_trunk_and_add_xprt(struct rpc_clnt *clnt,
+ struct rpc_xprt_switch *xps,
+ struct rpc_xprt *xprt,
+ void *data)
+{
+ struct nfs4_add_xprt_data *xdata = (struct nfs4_add_xprt_data *)data;
+ u32 sp4_how;
+ int status;
+
+ sp4_how = (xdata->clp->cl_sp4_flags == 0 ? SP4_NONE : SP4_MACH_CRED);
+
+ /* Ensure these stick around for the rpc call */
+ xps = xprt_switch_get(xps);
+ xprt = xprt_get(xprt);
+
+ /* Sync call */
+ status = _nfs4_proc_exchange_id(xdata->clp, xdata->cred, sp4_how, xprt);
+
+ xprt_put(xprt);
+ xprt_switch_put(xps);
+
+ if (status)
+ pr_info("NFS: mulitaddr %s establishment failed. status %d\n",
+ xprt->address_strings[RPC_DISPLAY_ADDR], status);
+ return status;
+}
+
static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
struct rpc_cred *cred)
{
@@ -53,6 +53,7 @@ void rpc_xprt_switch_add_xprt(struct rpc_xprt_switch *xps,
xprt_switch_add_xprt_locked(xps, xprt);
spin_unlock(&xps->xps_lock);
}
+EXPORT_SYMBOL_GPL(rpc_xprt_switch_add_xprt);
static void xprt_switch_remove_xprt_locked(struct rpc_xprt_switch *xps,
struct rpc_xprt *xprt)
@@ -145,6 +146,7 @@ struct rpc_xprt_switch *xprt_switch_get(struct rpc_xprt_switch *xps)
return xps;
return NULL;
}
+EXPORT_SYMBOL_GPL(xprt_switch_get);
/**
* xprt_switch_put - Release a reference to a rpc_xprt_switch
@@ -157,6 +159,7 @@ void xprt_switch_put(struct rpc_xprt_switch *xps)
if (xps != NULL)
kref_put(&xps->xps_kref, xprt_switch_free);
}
+EXPORT_SYMBOL_GPL(xprt_switch_put);
/**
* rpc_xprt_switch_set_roundrobin - Set a round-robin policy on rpc_xprt_switch