aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c42
-rw-r--r--fs/nfs/nfs4session.h6
-rw-r--r--fs/nfs/nfs4xdr.c16
-rw-r--r--include/linux/nfs_xdr.h8
4 files changed, 49 insertions, 23 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2e7c9f7a6f7c..006bfa3da55b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -7166,10 +7166,11 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
7166 args->bc_attrs.max_reqs); 7166 args->bc_attrs.max_reqs);
7167} 7167}
7168 7168
7169static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) 7169static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args,
7170 struct nfs41_create_session_res *res)
7170{ 7171{
7171 struct nfs4_channel_attrs *sent = &args->fc_attrs; 7172 struct nfs4_channel_attrs *sent = &args->fc_attrs;
7172 struct nfs4_channel_attrs *rcvd = &session->fc_attrs; 7173 struct nfs4_channel_attrs *rcvd = &res->fc_attrs;
7173 7174
7174 if (rcvd->max_resp_sz > sent->max_resp_sz) 7175 if (rcvd->max_resp_sz > sent->max_resp_sz)
7175 return -EINVAL; 7176 return -EINVAL;
@@ -7188,10 +7189,11 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
7188 return 0; 7189 return 0;
7189} 7190}
7190 7191
7191static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) 7192static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args,
7193 struct nfs41_create_session_res *res)
7192{ 7194{
7193 struct nfs4_channel_attrs *sent = &args->bc_attrs; 7195 struct nfs4_channel_attrs *sent = &args->bc_attrs;
7194 struct nfs4_channel_attrs *rcvd = &session->bc_attrs; 7196 struct nfs4_channel_attrs *rcvd = &res->bc_attrs;
7195 7197
7196 if (rcvd->max_rqst_sz > sent->max_rqst_sz) 7198 if (rcvd->max_rqst_sz > sent->max_rqst_sz)
7197 return -EINVAL; 7199 return -EINVAL;
@@ -7208,14 +7210,23 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args
7208} 7210}
7209 7211
7210static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args, 7212static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
7211 struct nfs4_session *session) 7213 struct nfs41_create_session_res *res)
7212{ 7214{
7213 int ret; 7215 int ret;
7214 7216
7215 ret = nfs4_verify_fore_channel_attrs(args, session); 7217 ret = nfs4_verify_fore_channel_attrs(args, res);
7216 if (ret) 7218 if (ret)
7217 return ret; 7219 return ret;
7218 return nfs4_verify_back_channel_attrs(args, session); 7220 return nfs4_verify_back_channel_attrs(args, res);
7221}
7222
7223static void nfs4_update_session(struct nfs4_session *session,
7224 struct nfs41_create_session_res *res)
7225{
7226 nfs4_copy_sessionid(&session->sess_id, &res->sessionid);
7227 session->flags = res->flags;
7228 memcpy(&session->fc_attrs, &res->fc_attrs, sizeof(session->fc_attrs));
7229 memcpy(&session->bc_attrs, &res->bc_attrs, sizeof(session->bc_attrs));
7219} 7230}
7220 7231
7221static int _nfs4_proc_create_session(struct nfs_client *clp, 7232static int _nfs4_proc_create_session(struct nfs_client *clp,
@@ -7224,11 +7235,12 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
7224 struct nfs4_session *session = clp->cl_session; 7235 struct nfs4_session *session = clp->cl_session;
7225 struct nfs41_create_session_args args = { 7236 struct nfs41_create_session_args args = {
7226 .client = clp, 7237 .client = clp,
7238 .clientid = clp->cl_clientid,
7239 .seqid = clp->cl_seqid,
7227 .cb_program = NFS4_CALLBACK, 7240 .cb_program = NFS4_CALLBACK,
7228 }; 7241 };
7229 struct nfs41_create_session_res res = { 7242 struct nfs41_create_session_res res;
7230 .client = clp, 7243
7231 };
7232 struct rpc_message msg = { 7244 struct rpc_message msg = {
7233 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION], 7245 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE_SESSION],
7234 .rpc_argp = &args, 7246 .rpc_argp = &args,
@@ -7245,11 +7257,15 @@ static int _nfs4_proc_create_session(struct nfs_client *clp,
7245 7257
7246 if (!status) { 7258 if (!status) {
7247 /* Verify the session's negotiated channel_attrs values */ 7259 /* Verify the session's negotiated channel_attrs values */
7248 status = nfs4_verify_channel_attrs(&args, session); 7260 status = nfs4_verify_channel_attrs(&args, &res);
7249 /* Increment the clientid slot sequence id */ 7261 /* Increment the clientid slot sequence id */
7250 clp->cl_seqid++; 7262 if (clp->cl_seqid == res.seqid)
7263 clp->cl_seqid++;
7264 if (status)
7265 goto out;
7266 nfs4_update_session(session, &res);
7251 } 7267 }
7252 7268out:
7253 return status; 7269 return status;
7254} 7270}
7255 7271
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index b34ada9bc6a2..fc46c7455898 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -118,6 +118,12 @@ static inline int nfs4_has_persistent_session(const struct nfs_client *clp)
118 return 0; 118 return 0;
119} 119}
120 120
121static inline void nfs4_copy_sessionid(struct nfs4_sessionid *dst,
122 const struct nfs4_sessionid *src)
123{
124 memcpy(dst->data, src->data, NFS4_MAX_SESSIONID_LEN);
125}
126
121#ifdef CONFIG_CRC32 127#ifdef CONFIG_CRC32
122/* 128/*
123 * nfs_session_id_hash - calculate the crc32 hash for the session id 129 * nfs_session_id_hash - calculate the crc32 hash for the session id
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e23a0a664e12..248903b138a8 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1806,8 +1806,8 @@ static void encode_create_session(struct xdr_stream *xdr,
1806 1806
1807 encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr); 1807 encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
1808 p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12); 1808 p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
1809 p = xdr_encode_hyper(p, clp->cl_clientid); 1809 p = xdr_encode_hyper(p, args->clientid);
1810 *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */ 1810 *p++ = cpu_to_be32(args->seqid); /*Sequence id */
1811 *p++ = cpu_to_be32(args->flags); /*flags */ 1811 *p++ = cpu_to_be32(args->flags); /*flags */
1812 1812
1813 /* Fore Channel */ 1813 /* Fore Channel */
@@ -5641,12 +5641,10 @@ static int decode_create_session(struct xdr_stream *xdr,
5641{ 5641{
5642 __be32 *p; 5642 __be32 *p;
5643 int status; 5643 int status;
5644 struct nfs_client *clp = res->client;
5645 struct nfs4_session *session = clp->cl_session;
5646 5644
5647 status = decode_op_hdr(xdr, OP_CREATE_SESSION); 5645 status = decode_op_hdr(xdr, OP_CREATE_SESSION);
5648 if (!status) 5646 if (!status)
5649 status = decode_sessionid(xdr, &session->sess_id); 5647 status = decode_sessionid(xdr, &res->sessionid);
5650 if (unlikely(status)) 5648 if (unlikely(status))
5651 return status; 5649 return status;
5652 5650
@@ -5654,13 +5652,13 @@ static int decode_create_session(struct xdr_stream *xdr,
5654 p = xdr_inline_decode(xdr, 8); 5652 p = xdr_inline_decode(xdr, 8);
5655 if (unlikely(!p)) 5653 if (unlikely(!p))
5656 goto out_overflow; 5654 goto out_overflow;
5657 clp->cl_seqid = be32_to_cpup(p++); 5655 res->seqid = be32_to_cpup(p++);
5658 session->flags = be32_to_cpup(p); 5656 res->flags = be32_to_cpup(p);
5659 5657
5660 /* Channel attributes */ 5658 /* Channel attributes */
5661 status = decode_chan_attrs(xdr, &session->fc_attrs); 5659 status = decode_chan_attrs(xdr, &res->fc_attrs);
5662 if (!status) 5660 if (!status)
5663 status = decode_chan_attrs(xdr, &session->bc_attrs); 5661 status = decode_chan_attrs(xdr, &res->bc_attrs);
5664 return status; 5662 return status;
5665out_overflow: 5663out_overflow:
5666 print_overflow_msg(__func__, xdr); 5664 print_overflow_msg(__func__, xdr);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9a39132fda49..1af12fc16e98 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1185,6 +1185,8 @@ struct nfs41_exchange_id_res {
1185 1185
1186struct nfs41_create_session_args { 1186struct nfs41_create_session_args {
1187 struct nfs_client *client; 1187 struct nfs_client *client;
1188 u64 clientid;
1189 uint32_t seqid;
1188 uint32_t flags; 1190 uint32_t flags;
1189 uint32_t cb_program; 1191 uint32_t cb_program;
1190 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */ 1192 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
@@ -1192,7 +1194,11 @@ struct nfs41_create_session_args {
1192}; 1194};
1193 1195
1194struct nfs41_create_session_res { 1196struct nfs41_create_session_res {
1195 struct nfs_client *client; 1197 struct nfs4_sessionid sessionid;
1198 uint32_t seqid;
1199 uint32_t flags;
1200 struct nfs4_channel_attrs fc_attrs; /* Fore Channel */
1201 struct nfs4_channel_attrs bc_attrs; /* Back Channel */
1196}; 1202};
1197 1203
1198struct nfs41_reclaim_complete_args { 1204struct nfs41_reclaim_complete_args {