Skip to content

Commit

Permalink
NFS test session trunking with exchange id
Browse files Browse the repository at this point in the history
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: Andy Adamson <andros@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
  • Loading branch information
Andy Adamson authored and Anna Schumaker committed Sep 19, 2016
1 parent 04ea1b3 commit ad0849a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 11 deletions.
10 changes: 7 additions & 3 deletions fs/nfs/nfs4client.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]);
Expand Down
45 changes: 37 additions & 8 deletions fs/nfs/nfs4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -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);

Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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 = {
Expand All @@ -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)
Expand Down Expand Up @@ -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 |
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit ad0849a

Please sign in to comment.