diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-01-17 13:49:17 -0500 |
---|---|---|
committer | Steve French <smfrench@gmail.com> | 2012-01-17 23:39:34 -0500 |
commit | f5fffcee27c09143ba80e5257dbd1f381d86342f (patch) | |
tree | 14471cf7b68f1845949c6f0bc3bd6852e38ca233 /fs | |
parent | 7250170c9ed00f3b74b11b98afefab45020672dd (diff) |
cifs: better instrumentation for coalesce_t2
When coalesce_t2 returns an error, have it throw a cFYI message that
explains the reason. Also rename some variables to clarify what they
represent.
Reported-and-Tested-by: Konstantinos Skarlatos <k.skarlatos@gmail.com>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/connect.c | 84 |
1 files changed, 50 insertions, 34 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 4666780f315d..5cc15856e4ad 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -225,74 +225,90 @@ static int check2ndT2(struct smb_hdr *pSMB) | |||
225 | 225 | ||
226 | static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) | 226 | static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) |
227 | { | 227 | { |
228 | struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; | 228 | struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)psecond; |
229 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; | 229 | struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; |
230 | char *data_area_of_target; | 230 | char *data_area_of_tgt; |
231 | char *data_area_of_buf2; | 231 | char *data_area_of_src; |
232 | int remaining; | 232 | int remaining; |
233 | unsigned int byte_count, total_in_buf; | 233 | unsigned int byte_count, total_in_tgt; |
234 | __u16 total_data_size, total_in_buf2; | 234 | __u16 tgt_total_cnt, src_total_cnt, total_in_src; |
235 | 235 | ||
236 | total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); | 236 | src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount); |
237 | tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); | ||
237 | 238 | ||
238 | if (total_data_size != | 239 | if (tgt_total_cnt != src_total_cnt) |
239 | get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount)) | 240 | cFYI(1, "total data count of primary and secondary t2 differ " |
240 | cFYI(1, "total data size of primary and secondary t2 differ"); | 241 | "source=%hu target=%hu", src_total_cnt, tgt_total_cnt); |
241 | 242 | ||
242 | total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); | 243 | total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); |
243 | 244 | ||
244 | remaining = total_data_size - total_in_buf; | 245 | remaining = tgt_total_cnt - total_in_tgt; |
245 | 246 | ||
246 | if (remaining < 0) | 247 | if (remaining < 0) { |
248 | cFYI(1, "Server sent too much data. tgt_total_cnt=%hu " | ||
249 | "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt); | ||
247 | return -EPROTO; | 250 | return -EPROTO; |
251 | } | ||
248 | 252 | ||
249 | if (remaining == 0) /* nothing to do, ignore */ | 253 | if (remaining == 0) { |
254 | /* nothing to do, ignore */ | ||
255 | cFYI(1, "no more data remains"); | ||
250 | return 0; | 256 | return 0; |
257 | } | ||
251 | 258 | ||
252 | total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount); | 259 | total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount); |
253 | if (remaining < total_in_buf2) { | 260 | if (remaining < total_in_src) |
254 | cFYI(1, "transact2 2nd response contains too much data"); | 261 | cFYI(1, "transact2 2nd response contains too much data"); |
255 | } | ||
256 | 262 | ||
257 | /* find end of first SMB data area */ | 263 | /* find end of first SMB data area */ |
258 | data_area_of_target = (char *)&pSMBt->hdr.Protocol + | 264 | data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + |
259 | get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); | 265 | get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); |
260 | /* validate target area */ | ||
261 | 266 | ||
262 | data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol + | 267 | /* validate target area */ |
263 | get_unaligned_le16(&pSMB2->t2_rsp.DataOffset); | 268 | data_area_of_src = (char *)&pSMBs->hdr.Protocol + |
269 | get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); | ||
264 | 270 | ||
265 | data_area_of_target += total_in_buf; | 271 | data_area_of_tgt += total_in_tgt; |
266 | 272 | ||
267 | /* copy second buffer into end of first buffer */ | 273 | total_in_tgt += total_in_src; |
268 | total_in_buf += total_in_buf2; | ||
269 | /* is the result too big for the field? */ | 274 | /* is the result too big for the field? */ |
270 | if (total_in_buf > USHRT_MAX) | 275 | if (total_in_tgt > USHRT_MAX) { |
276 | cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt); | ||
271 | return -EPROTO; | 277 | return -EPROTO; |
272 | put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); | 278 | } |
279 | put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); | ||
273 | 280 | ||
274 | /* fix up the BCC */ | 281 | /* fix up the BCC */ |
275 | byte_count = get_bcc(pTargetSMB); | 282 | byte_count = get_bcc(pTargetSMB); |
276 | byte_count += total_in_buf2; | 283 | byte_count += total_in_src; |
277 | /* is the result too big for the field? */ | 284 | /* is the result too big for the field? */ |
278 | if (byte_count > USHRT_MAX) | 285 | if (byte_count > USHRT_MAX) { |
286 | cFYI(1, "coalesced BCC too large (%u)", byte_count); | ||
279 | return -EPROTO; | 287 | return -EPROTO; |
288 | } | ||
280 | put_bcc(byte_count, pTargetSMB); | 289 | put_bcc(byte_count, pTargetSMB); |
281 | 290 | ||
282 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); | 291 | byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); |
283 | byte_count += total_in_buf2; | 292 | byte_count += total_in_src; |
284 | /* don't allow buffer to overflow */ | 293 | /* don't allow buffer to overflow */ |
285 | if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) | 294 | if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { |
295 | cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count); | ||
286 | return -ENOBUFS; | 296 | return -ENOBUFS; |
297 | } | ||
287 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); | 298 | pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); |
288 | 299 | ||
289 | memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); | 300 | /* copy second buffer into end of first buffer */ |
301 | memcpy(data_area_of_tgt, data_area_of_src, total_in_src); | ||
290 | 302 | ||
291 | if (remaining == total_in_buf2) { | 303 | if (remaining != total_in_src) { |
292 | cFYI(1, "found the last secondary response"); | 304 | /* more responses to go */ |
293 | return 0; /* we are done */ | 305 | cFYI(1, "waiting for more secondary responses"); |
294 | } else /* more responses to go */ | ||
295 | return 1; | 306 | return 1; |
307 | } | ||
308 | |||
309 | /* we are done */ | ||
310 | cFYI(1, "found the last secondary response"); | ||
311 | return 0; | ||
296 | } | 312 | } |
297 | 313 | ||
298 | static void | 314 | static void |