Commit dff58530 authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by Trond Myklebust

NFSv4.1: fix handling of backchannel binding in BIND_CONN_TO_SESSION

Currently, if the client sends BIND_CONN_TO_SESSION with
NFS4_CDFC4_FORE_OR_BOTH but only gets NFS4_CDFS4_FORE back it ignores
that it wasn't able to enable a backchannel.

To make sure, the client sends BIND_CONN_TO_SESSION as the first
operation on the connections (ie., no other session compounds haven't
been sent before), and if the client's request to bind the backchannel
is not satisfied, then reset the connection and retry.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent 7c4310ff
...@@ -7891,6 +7891,7 @@ static void ...@@ -7891,6 +7891,7 @@ static void
nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata) nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
{ {
struct nfs41_bind_conn_to_session_args *args = task->tk_msg.rpc_argp; struct nfs41_bind_conn_to_session_args *args = task->tk_msg.rpc_argp;
struct nfs41_bind_conn_to_session_res *res = task->tk_msg.rpc_resp;
struct nfs_client *clp = args->client; struct nfs_client *clp = args->client;
switch (task->tk_status) { switch (task->tk_status) {
...@@ -7899,6 +7900,12 @@ nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata) ...@@ -7899,6 +7900,12 @@ nfs4_bind_one_conn_to_session_done(struct rpc_task *task, void *calldata)
nfs4_schedule_session_recovery(clp->cl_session, nfs4_schedule_session_recovery(clp->cl_session,
task->tk_status); task->tk_status);
} }
if (args->dir == NFS4_CDFC4_FORE_OR_BOTH &&
res->dir != NFS4_CDFS4_BOTH) {
rpc_task_close_connection(task);
if (args->retries++ < MAX_BIND_CONN_TO_SESSION_RETRIES)
rpc_restart_call(task);
}
} }
static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = { static const struct rpc_call_ops nfs4_bind_one_conn_to_session_ops = {
...@@ -7921,6 +7928,7 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt, ...@@ -7921,6 +7928,7 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
struct nfs41_bind_conn_to_session_args args = { struct nfs41_bind_conn_to_session_args args = {
.client = clp, .client = clp,
.dir = NFS4_CDFC4_FORE_OR_BOTH, .dir = NFS4_CDFC4_FORE_OR_BOTH,
.retries = 0,
}; };
struct nfs41_bind_conn_to_session_res res; struct nfs41_bind_conn_to_session_res res;
struct rpc_message msg = { struct rpc_message msg = {
......
...@@ -1317,11 +1317,13 @@ struct nfs41_impl_id { ...@@ -1317,11 +1317,13 @@ struct nfs41_impl_id {
struct nfstime4 date; struct nfstime4 date;
}; };
#define MAX_BIND_CONN_TO_SESSION_RETRIES 3
struct nfs41_bind_conn_to_session_args { struct nfs41_bind_conn_to_session_args {
struct nfs_client *client; struct nfs_client *client;
struct nfs4_sessionid sessionid; struct nfs4_sessionid sessionid;
u32 dir; u32 dir;
bool use_conn_in_rdma_mode; bool use_conn_in_rdma_mode;
int retries;
}; };
struct nfs41_bind_conn_to_session_res { struct nfs41_bind_conn_to_session_res {
......
...@@ -242,4 +242,9 @@ static inline int rpc_reply_expected(struct rpc_task *task) ...@@ -242,4 +242,9 @@ static inline int rpc_reply_expected(struct rpc_task *task)
(task->tk_msg.rpc_proc->p_decode != NULL); (task->tk_msg.rpc_proc->p_decode != NULL);
} }
static inline void rpc_task_close_connection(struct rpc_task *task)
{
if (task->tk_xprt)
xprt_force_disconnect(task->tk_xprt);
}
#endif /* _LINUX_SUNRPC_CLNT_H */ #endif /* _LINUX_SUNRPC_CLNT_H */
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