Commit ad0849a7 authored by Andy Adamson's avatar Andy Adamson Committed by Anna Schumaker

NFS test session trunking with exchange id

Use an async exchange id call to test for session trunking

To conform with RFC 5661 section 18.35.4, the Non-Update on
Existing Clientid case, save the exchange id verifier in
cl_confirm and use it for the session trunking exhange id test.
Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 04ea1b3e
......@@ -637,9 +637,10 @@ nfs4_check_server_scope(struct nfs41_server_scope *s1,
}
/**
* nfs4_detect_session_trunking - Checks for session trunking called
* after a successful EXCHANGE_ID testing a multi-addr connection to be
* potentially added as a session trunk
* nfs4_detect_session_trunking - Checks for session trunking.
*
* Called after a successful EXCHANGE_ID on a multi-addr connection.
* Upon success, add the transport.
*
* @clp: original mount nfs_client
* @res: result structure from an exchange_id using the original mount
......@@ -673,6 +674,9 @@ int nfs4_detect_session_trunking(struct nfs_client *clp,
if (!nfs4_check_server_scope(clp->cl_serverscope, res->server_scope))
goto out_err;
/* Session trunking passed, add the xprt */
rpc_clnt_xprt_switch_add_xprt(clp->cl_rpcclient, xprt);
pr_info("NFS: %s: Session trunking succeeded for %s\n",
clp->cl_hostname,
xprt->address_strings[RPC_DISPLAY_ADDR]);
......
......@@ -7107,6 +7107,7 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
struct nfs41_exchange_id_data {
struct nfs41_exchange_id_res res;
struct nfs41_exchange_id_args args;
struct rpc_xprt *xprt;
int rpc_status;
};
......@@ -7121,6 +7122,13 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
if (status == 0)
status = nfs4_check_cl_exchange_flags(cdata->res.flags);
if (cdata->xprt && status == 0) {
status = nfs4_detect_session_trunking(clp, &cdata->res,
cdata->xprt);
goto out;
}
if (status == 0)
status = nfs4_sp4_select_mode(clp, &cdata->res.state_protect);
......@@ -7157,8 +7165,13 @@ static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
clp->cl_serverscope = cdata->res.server_scope;
cdata->res.server_scope = NULL;
}
/* Save the EXCHANGE_ID verifier session trunk tests */
memcpy(clp->cl_confirm.data, cdata->args.verifier->data,
sizeof(clp->cl_confirm.data));
}
out:
cdata->rpc_status = status;
return;
}
static void nfs4_exchange_id_release(void *data)
......@@ -7167,6 +7180,10 @@ static void nfs4_exchange_id_release(void *data)
(struct nfs41_exchange_id_data *)data;
nfs_put_client(cdata->args.client);
if (cdata->xprt) {
xprt_put(cdata->xprt);
rpc_clnt_xprt_switch_put(cdata->args.client->cl_rpcclient);
}
kfree(cdata->res.impl_id);
kfree(cdata->res.server_scope);
kfree(cdata->res.server_owner);
......@@ -7184,7 +7201,7 @@ static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
* Wrapper for EXCHANGE_ID operation.
*/
static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
u32 sp4_how)
u32 sp4_how, struct rpc_xprt *xprt)
{
nfs4_verifier verifier;
struct rpc_message msg = {
......@@ -7209,7 +7226,8 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
if (!calldata)
goto out;
nfs4_init_boot_verifier(clp, &verifier);
if (!xprt)
nfs4_init_boot_verifier(clp, &verifier);
status = nfs4_init_uniform_client_string(clp);
if (status)
......@@ -7249,8 +7267,15 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
status = -EINVAL;
goto out_impl_id;
}
calldata->args.verifier = &verifier;
if (xprt) {
calldata->xprt = xprt;
task_setup_data.rpc_xprt = xprt;
task_setup_data.flags =
RPC_TASK_SOFT|RPC_TASK_SOFTCONN|RPC_TASK_ASYNC;
calldata->args.verifier = &clp->cl_confirm;
} else {
calldata->args.verifier = &verifier;
}
calldata->args.client = clp;
#ifdef CONFIG_NFS_V4_1_MIGRATION
calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
......@@ -7270,9 +7295,13 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
goto out_impl_id;
}
status = rpc_wait_for_completion_task(task);
if (!status)
if (!xprt) {
status = rpc_wait_for_completion_task(task);
if (!status)
status = calldata->rpc_status;
} else /* session trunking test */
status = calldata->rpc_status;
rpc_put_task(task);
out:
if (clp->cl_implid != NULL)
......@@ -7315,13 +7344,13 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
/* try SP4_MACH_CRED if krb5i/p */
if (authflavor == RPC_AUTH_GSS_KRB5I ||
authflavor == RPC_AUTH_GSS_KRB5P) {
status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED);
status = _nfs4_proc_exchange_id(clp, cred, SP4_MACH_CRED, NULL);
if (!status)
return 0;
}
/* try SP4_NONE */
return _nfs4_proc_exchange_id(clp, cred, SP4_NONE);
return _nfs4_proc_exchange_id(clp, cred, SP4_NONE, NULL);
}
static int _nfs4_proc_destroy_clientid(struct nfs_client *clp,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment