Commit 8d89bd70 authored by Andy Adamson's avatar Andy Adamson Committed by Anna Schumaker

NFS setup async exchange_id

Testing an rpc_xprt for session trunking should not delay application
progress over already established transports.
Setup exchange_id to be able to be an async call to test an rpc_xprt
for session trunking use.
Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 5405fc44
...@@ -7104,6 +7104,80 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp, ...@@ -7104,6 +7104,80 @@ static int nfs4_sp4_select_mode(struct nfs_client *clp,
return 0; return 0;
} }
struct nfs41_exchange_id_data {
struct nfs41_exchange_id_res res;
struct nfs41_exchange_id_args args;
int rpc_status;
};
static void nfs4_exchange_id_done(struct rpc_task *task, void *data)
{
struct nfs41_exchange_id_data *cdata =
(struct nfs41_exchange_id_data *)data;
struct nfs_client *clp = cdata->args.client;
int status = task->tk_status;
trace_nfs4_exchange_id(clp, status);
if (status == 0)
status = nfs4_check_cl_exchange_flags(cdata->res.flags);
if (status == 0)
status = nfs4_sp4_select_mode(clp, &cdata->res.state_protect);
if (status == 0) {
clp->cl_clientid = cdata->res.clientid;
clp->cl_exchange_flags = cdata->res.flags;
/* Client ID is not confirmed */
if (!(cdata->res.flags & EXCHGID4_FLAG_CONFIRMED_R)) {
clear_bit(NFS4_SESSION_ESTABLISHED,
&clp->cl_session->session_state);
clp->cl_seqid = cdata->res.seqid;
}
kfree(clp->cl_serverowner);
clp->cl_serverowner = cdata->res.server_owner;
cdata->res.server_owner = NULL;
/* use the most recent implementation id */
kfree(clp->cl_implid);
clp->cl_implid = cdata->res.impl_id;
cdata->res.impl_id = NULL;
if (clp->cl_serverscope != NULL &&
!nfs41_same_server_scope(clp->cl_serverscope,
cdata->res.server_scope)) {
dprintk("%s: server_scope mismatch detected\n",
__func__);
set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
kfree(clp->cl_serverscope);
clp->cl_serverscope = NULL;
}
if (clp->cl_serverscope == NULL) {
clp->cl_serverscope = cdata->res.server_scope;
cdata->res.server_scope = NULL;
}
}
cdata->rpc_status = status;
}
static void nfs4_exchange_id_release(void *data)
{
struct nfs41_exchange_id_data *cdata =
(struct nfs41_exchange_id_data *)data;
nfs_put_client(cdata->args.client);
kfree(cdata->res.impl_id);
kfree(cdata->res.server_scope);
kfree(cdata->res.server_owner);
kfree(cdata);
}
static const struct rpc_call_ops nfs4_exchange_id_call_ops = {
.rpc_call_done = nfs4_exchange_id_done,
.rpc_release = nfs4_exchange_id_release,
};
/* /*
* _nfs4_proc_exchange_id() * _nfs4_proc_exchange_id()
* *
...@@ -7113,66 +7187,60 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, ...@@ -7113,66 +7187,60 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
u32 sp4_how) u32 sp4_how)
{ {
nfs4_verifier verifier; nfs4_verifier verifier;
struct nfs41_exchange_id_args args = {
.verifier = &verifier,
.client = clp,
#ifdef CONFIG_NFS_V4_1_MIGRATION
.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
EXCHGID4_FLAG_BIND_PRINC_STATEID |
EXCHGID4_FLAG_SUPP_MOVED_MIGR,
#else
.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
EXCHGID4_FLAG_BIND_PRINC_STATEID,
#endif
};
struct nfs41_exchange_id_res res = {
0
};
int status;
struct rpc_message msg = { struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID], .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_EXCHANGE_ID],
.rpc_argp = &args,
.rpc_resp = &res,
.rpc_cred = cred, .rpc_cred = cred,
}; };
struct rpc_task_setup task_setup_data = {
.rpc_client = clp->cl_rpcclient,
.callback_ops = &nfs4_exchange_id_call_ops,
.rpc_message = &msg,
.flags = RPC_TASK_ASYNC | RPC_TASK_TIMEOUT,
};
struct nfs41_exchange_id_data *calldata;
struct rpc_task *task;
int status = -EIO;
if (!atomic_inc_not_zero(&clp->cl_count))
goto out;
status = -ENOMEM;
calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
if (!calldata)
goto out;
nfs4_init_boot_verifier(clp, &verifier); nfs4_init_boot_verifier(clp, &verifier);
status = nfs4_init_uniform_client_string(clp); status = nfs4_init_uniform_client_string(clp);
if (status) if (status)
goto out; goto out_calldata;
dprintk("NFS call exchange_id auth=%s, '%s'\n", dprintk("NFS call exchange_id auth=%s, '%s'\n",
clp->cl_rpcclient->cl_auth->au_ops->au_name, clp->cl_rpcclient->cl_auth->au_ops->au_name,
clp->cl_owner_id); clp->cl_owner_id);
res.server_owner = kzalloc(sizeof(struct nfs41_server_owner), calldata->res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
GFP_NOFS); GFP_NOFS);
if (unlikely(res.server_owner == NULL)) { status = -ENOMEM;
status = -ENOMEM; if (unlikely(calldata->res.server_owner == NULL))
goto out; goto out_calldata;
}
res.server_scope = kzalloc(sizeof(struct nfs41_server_scope), calldata->res.server_scope = kzalloc(sizeof(struct nfs41_server_scope),
GFP_NOFS); GFP_NOFS);
if (unlikely(res.server_scope == NULL)) { if (unlikely(calldata->res.server_scope == NULL))
status = -ENOMEM;
goto out_server_owner; goto out_server_owner;
}
res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_NOFS); calldata->res.impl_id = kzalloc(sizeof(struct nfs41_impl_id), GFP_NOFS);
if (unlikely(res.impl_id == NULL)) { if (unlikely(calldata->res.impl_id == NULL))
status = -ENOMEM;
goto out_server_scope; goto out_server_scope;
}
switch (sp4_how) { switch (sp4_how) {
case SP4_NONE: case SP4_NONE:
args.state_protect.how = SP4_NONE; calldata->args.state_protect.how = SP4_NONE;
break; break;
case SP4_MACH_CRED: case SP4_MACH_CRED:
args.state_protect = nfs4_sp4_mach_cred_request; calldata->args.state_protect = nfs4_sp4_mach_cred_request;
break; break;
default: default:
...@@ -7182,55 +7250,30 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, ...@@ -7182,55 +7250,30 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
goto out_impl_id; goto out_impl_id;
} }
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); calldata->args.verifier = &verifier;
trace_nfs4_exchange_id(clp, status); calldata->args.client = clp;
if (status == 0) #ifdef CONFIG_NFS_V4_1_MIGRATION
status = nfs4_check_cl_exchange_flags(res.flags); calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
EXCHGID4_FLAG_BIND_PRINC_STATEID |
if (status == 0) EXCHGID4_FLAG_SUPP_MOVED_MIGR,
status = nfs4_sp4_select_mode(clp, &res.state_protect); #else
calldata->args.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER |
if (status == 0) { EXCHGID4_FLAG_BIND_PRINC_STATEID,
clp->cl_clientid = res.clientid; #endif
clp->cl_exchange_flags = res.flags; msg.rpc_argp = &calldata->args;
/* Client ID is not confirmed */ msg.rpc_resp = &calldata->res;
if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R)) { task_setup_data.callback_data = calldata;
clear_bit(NFS4_SESSION_ESTABLISHED,
&clp->cl_session->session_state);
clp->cl_seqid = res.seqid;
}
kfree(clp->cl_serverowner);
clp->cl_serverowner = res.server_owner;
res.server_owner = NULL;
/* use the most recent implementation id */
kfree(clp->cl_implid);
clp->cl_implid = res.impl_id;
res.impl_id = NULL;
if (clp->cl_serverscope != NULL &&
!nfs41_same_server_scope(clp->cl_serverscope,
res.server_scope)) {
dprintk("%s: server_scope mismatch detected\n",
__func__);
set_bit(NFS4CLNT_SERVER_SCOPE_MISMATCH, &clp->cl_state);
kfree(clp->cl_serverscope);
clp->cl_serverscope = NULL;
}
if (clp->cl_serverscope == NULL) { task = rpc_run_task(&task_setup_data);
clp->cl_serverscope = res.server_scope; if (IS_ERR(task)) {
res.server_scope = NULL; status = PTR_ERR(task);
} goto out_impl_id;
} }
out_impl_id: status = rpc_wait_for_completion_task(task);
kfree(res.impl_id); if (!status)
out_server_scope: status = calldata->rpc_status;
kfree(res.server_scope); rpc_put_task(task);
out_server_owner:
kfree(res.server_owner);
out: out:
if (clp->cl_implid != NULL) if (clp->cl_implid != NULL)
dprintk("NFS reply exchange_id: Server Implementation ID: " dprintk("NFS reply exchange_id: Server Implementation ID: "
...@@ -7240,6 +7283,16 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred, ...@@ -7240,6 +7283,16 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
clp->cl_implid->date.nseconds); clp->cl_implid->date.nseconds);
dprintk("NFS reply exchange_id: %d\n", status); dprintk("NFS reply exchange_id: %d\n", status);
return status; return status;
out_impl_id:
kfree(calldata->res.impl_id);
out_server_scope:
kfree(calldata->res.server_scope);
out_server_owner:
kfree(calldata->res.server_owner);
out_calldata:
kfree(calldata);
goto out;
} }
/* /*
......
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