diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 42 | ||||
-rw-r--r-- | fs/nfs/nfs4session.h | 6 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 16 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 8 |
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 | ||
7169 | static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) | 7169 | static 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 | ||
7191 | static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session) | 7192 | static 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 | ||
7210 | static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args, | 7212 | static 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 | |||
7223 | static 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 | ||
7221 | static int _nfs4_proc_create_session(struct nfs_client *clp, | 7232 | static 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 | 7268 | out: | |
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 | ||
121 | static 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; |
5665 | out_overflow: | 5663 | out_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 | ||
1186 | struct nfs41_create_session_args { | 1186 | struct 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 | ||
1194 | struct nfs41_create_session_res { | 1196 | struct 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 | ||
1198 | struct nfs41_reclaim_complete_args { | 1204 | struct nfs41_reclaim_complete_args { |