Commit 32b01310 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4.1: Don't clobber the seqid if exchange_id returns a confirmed clientid

If the EXCHGID4_FLAG_CONFIRMED_R flag is set, the client is in theory
supposed to already know the correct value of the seqid, in which case
RFC5661 states that it should ignore the value returned.

Also ensure that if the sanity check in nfs4_check_cl_exchange_flags
fails, then we must not change the nfs_client fields.

Finally, clean up the code: we don't need to retest the value of
'status' unless it can change.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 66245539
...@@ -5171,7 +5171,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) ...@@ -5171,7 +5171,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
.flags = EXCHGID4_FLAG_SUPP_MOVED_REFER, .flags = EXCHGID4_FLAG_SUPP_MOVED_REFER,
}; };
struct nfs41_exchange_id_res res = { struct nfs41_exchange_id_res res = {
.client = clp, 0
}; };
int status; int status;
struct rpc_message msg = { struct rpc_message msg = {
...@@ -5214,22 +5214,22 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) ...@@ -5214,22 +5214,22 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
if (status == 0) if (status == 0)
status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags); status = nfs4_check_cl_exchange_flags(res.flags);
if (status == 0) { if (status == 0) {
clp->cl_clientid = res.clientid;
clp->cl_exchange_flags = (res.flags & ~EXCHGID4_FLAG_CONFIRMED_R);
if (!(res.flags & EXCHGID4_FLAG_CONFIRMED_R))
clp->cl_seqid = res.seqid;
kfree(clp->cl_serverowner); kfree(clp->cl_serverowner);
clp->cl_serverowner = res.server_owner; clp->cl_serverowner = res.server_owner;
res.server_owner = NULL; res.server_owner = NULL;
}
if (status == 0) {
/* use the most recent implementation id */ /* use the most recent implementation id */
kfree(clp->cl_implid); kfree(clp->cl_implid);
clp->cl_implid = res.impl_id; clp->cl_implid = res.impl_id;
} else
kfree(res.impl_id);
if (status == 0) {
if (clp->cl_serverscope != NULL && if (clp->cl_serverscope != NULL &&
!nfs41_same_server_scope(clp->cl_serverscope, !nfs41_same_server_scope(clp->cl_serverscope,
res.server_scope)) { res.server_scope)) {
...@@ -5244,7 +5244,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred) ...@@ -5244,7 +5244,8 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
clp->cl_serverscope = res.server_scope; clp->cl_serverscope = res.server_scope;
goto out; goto out;
} }
} } else
kfree(res.impl_id);
out_server_owner: out_server_owner:
kfree(res.server_owner); kfree(res.server_owner);
......
...@@ -5319,7 +5319,6 @@ static int decode_exchange_id(struct xdr_stream *xdr, ...@@ -5319,7 +5319,6 @@ static int decode_exchange_id(struct xdr_stream *xdr,
uint32_t dummy; uint32_t dummy;
char *dummy_str; char *dummy_str;
int status; int status;
struct nfs_client *clp = res->client;
uint32_t impl_id_count; uint32_t impl_id_count;
status = decode_op_hdr(xdr, OP_EXCHANGE_ID); status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
...@@ -5329,12 +5328,12 @@ static int decode_exchange_id(struct xdr_stream *xdr, ...@@ -5329,12 +5328,12 @@ static int decode_exchange_id(struct xdr_stream *xdr,
p = xdr_inline_decode(xdr, 8); p = xdr_inline_decode(xdr, 8);
if (unlikely(!p)) if (unlikely(!p))
goto out_overflow; goto out_overflow;
xdr_decode_hyper(p, &clp->cl_clientid); xdr_decode_hyper(p, &res->clientid);
p = xdr_inline_decode(xdr, 12); p = xdr_inline_decode(xdr, 12);
if (unlikely(!p)) if (unlikely(!p))
goto out_overflow; goto out_overflow;
clp->cl_seqid = be32_to_cpup(p++); res->seqid = be32_to_cpup(p++);
clp->cl_exchange_flags = be32_to_cpup(p++); res->flags = be32_to_cpup(p++);
/* We ask for SP4_NONE */ /* We ask for SP4_NONE */
dummy = be32_to_cpup(p); dummy = be32_to_cpup(p);
......
...@@ -1132,7 +1132,8 @@ struct nfs41_bind_conn_to_session_res { ...@@ -1132,7 +1132,8 @@ struct nfs41_bind_conn_to_session_res {
}; };
struct nfs41_exchange_id_res { struct nfs41_exchange_id_res {
struct nfs_client *client; u64 clientid;
u32 seqid;
u32 flags; u32 flags;
struct nfs41_server_owner *server_owner; struct nfs41_server_owner *server_owner;
struct nfs41_server_scope *server_scope; struct nfs41_server_scope *server_scope;
......
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