diff options
author | Pavel Shilovsky <piastryyy@gmail.com> | 2011-08-01 05:19:40 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-08-01 08:33:44 -0400 |
commit | 3d9c2472a53ee1d26de9803899037aeeb44ccef1 (patch) | |
tree | 71d65fc36988d56aff29e59ec61651faa5d65252 /fs/cifs | |
parent | c4a5534a1b61cdffaa83187efe63712f75544726 (diff) |
CIFS: Move buffer allocation to a separate function
Reviewed-and-Tested-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/connect.c | 92 |
1 files changed, 55 insertions, 37 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 50b3523912ff..217d36587185 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -319,15 +319,53 @@ requeue_echo: | |||
319 | queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); | 319 | queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); |
320 | } | 320 | } |
321 | 321 | ||
322 | static bool | ||
323 | allocate_buffers(char **bigbuf, char **smallbuf, unsigned int size, | ||
324 | bool is_large_buf) | ||
325 | { | ||
326 | char *bbuf = *bigbuf, *sbuf = *smallbuf; | ||
327 | |||
328 | if (bbuf == NULL) { | ||
329 | bbuf = (char *)cifs_buf_get(); | ||
330 | if (!bbuf) { | ||
331 | cERROR(1, "No memory for large SMB response"); | ||
332 | msleep(3000); | ||
333 | /* retry will check if exiting */ | ||
334 | return false; | ||
335 | } | ||
336 | } else if (is_large_buf) { | ||
337 | /* we are reusing a dirty large buf, clear its start */ | ||
338 | memset(bbuf, 0, size); | ||
339 | } | ||
340 | |||
341 | if (sbuf == NULL) { | ||
342 | sbuf = (char *)cifs_small_buf_get(); | ||
343 | if (!sbuf) { | ||
344 | cERROR(1, "No memory for SMB response"); | ||
345 | msleep(1000); | ||
346 | /* retry will check if exiting */ | ||
347 | return false; | ||
348 | } | ||
349 | /* beginning of smb buffer is cleared in our buf_get */ | ||
350 | } else { | ||
351 | /* if existing small buf clear beginning */ | ||
352 | memset(sbuf, 0, size); | ||
353 | } | ||
354 | |||
355 | *bigbuf = bbuf; | ||
356 | *smallbuf = sbuf; | ||
357 | |||
358 | return true; | ||
359 | } | ||
360 | |||
322 | static int | 361 | static int |
323 | cifs_demultiplex_thread(void *p) | 362 | cifs_demultiplex_thread(void *p) |
324 | { | 363 | { |
325 | int length; | 364 | int length; |
326 | struct TCP_Server_Info *server = p; | 365 | struct TCP_Server_Info *server = p; |
327 | unsigned int pdu_length, total_read; | 366 | unsigned int pdu_length, total_read; |
367 | char *buf = NULL, *bigbuf = NULL, *smallbuf = NULL; | ||
328 | struct smb_hdr *smb_buffer = NULL; | 368 | struct smb_hdr *smb_buffer = NULL; |
329 | struct smb_hdr *bigbuf = NULL; | ||
330 | struct smb_hdr *smallbuf = NULL; | ||
331 | struct msghdr smb_msg; | 369 | struct msghdr smb_msg; |
332 | struct kvec iov; | 370 | struct kvec iov; |
333 | struct socket *csocket = server->ssocket; | 371 | struct socket *csocket = server->ssocket; |
@@ -351,35 +389,16 @@ cifs_demultiplex_thread(void *p) | |||
351 | while (server->tcpStatus != CifsExiting) { | 389 | while (server->tcpStatus != CifsExiting) { |
352 | if (try_to_freeze()) | 390 | if (try_to_freeze()) |
353 | continue; | 391 | continue; |
354 | if (bigbuf == NULL) { | ||
355 | bigbuf = cifs_buf_get(); | ||
356 | if (!bigbuf) { | ||
357 | cERROR(1, "No memory for large SMB response"); | ||
358 | msleep(3000); | ||
359 | /* retry will check if exiting */ | ||
360 | continue; | ||
361 | } | ||
362 | } else if (isLargeBuf) { | ||
363 | /* we are reusing a dirty large buf, clear its start */ | ||
364 | memset(bigbuf, 0, sizeof(struct smb_hdr)); | ||
365 | } | ||
366 | 392 | ||
367 | if (smallbuf == NULL) { | 393 | if (!allocate_buffers(&bigbuf, &smallbuf, |
368 | smallbuf = cifs_small_buf_get(); | 394 | sizeof(struct smb_hdr), isLargeBuf)) |
369 | if (!smallbuf) { | 395 | continue; |
370 | cERROR(1, "No memory for SMB response"); | ||
371 | msleep(1000); | ||
372 | /* retry will check if exiting */ | ||
373 | continue; | ||
374 | } | ||
375 | /* beginning of smb buffer is cleared in our buf_get */ | ||
376 | } else /* if existing small buf clear beginning */ | ||
377 | memset(smallbuf, 0, sizeof(struct smb_hdr)); | ||
378 | 396 | ||
379 | isLargeBuf = false; | 397 | isLargeBuf = false; |
380 | isMultiRsp = false; | 398 | isMultiRsp = false; |
381 | smb_buffer = smallbuf; | 399 | smb_buffer = (struct smb_hdr *)smallbuf; |
382 | iov.iov_base = smb_buffer; | 400 | buf = smallbuf; |
401 | iov.iov_base = buf; | ||
383 | iov.iov_len = 4; | 402 | iov.iov_len = 4; |
384 | smb_msg.msg_control = NULL; | 403 | smb_msg.msg_control = NULL; |
385 | smb_msg.msg_controllen = 0; | 404 | smb_msg.msg_controllen = 0; |
@@ -417,8 +436,7 @@ incomplete_rcv: | |||
417 | allowing socket to clear and app threads to set | 436 | allowing socket to clear and app threads to set |
418 | tcpStatus CifsNeedReconnect if server hung */ | 437 | tcpStatus CifsNeedReconnect if server hung */ |
419 | if (pdu_length < 4) { | 438 | if (pdu_length < 4) { |
420 | iov.iov_base = (4 - pdu_length) + | 439 | iov.iov_base = (4 - pdu_length) + buf; |
421 | (char *)smb_buffer; | ||
422 | iov.iov_len = pdu_length; | 440 | iov.iov_len = pdu_length; |
423 | smb_msg.msg_control = NULL; | 441 | smb_msg.msg_control = NULL; |
424 | smb_msg.msg_controllen = 0; | 442 | smb_msg.msg_controllen = 0; |
@@ -446,7 +464,7 @@ incomplete_rcv: | |||
446 | /* the first byte big endian of the length field, | 464 | /* the first byte big endian of the length field, |
447 | is actually not part of the length but the type | 465 | is actually not part of the length but the type |
448 | with the most common, zero, as regular data */ | 466 | with the most common, zero, as regular data */ |
449 | temp = *((char *) smb_buffer); | 467 | temp = *buf; |
450 | 468 | ||
451 | /* Note that FC 1001 length is big endian on the wire, | 469 | /* Note that FC 1001 length is big endian on the wire, |
452 | but we convert it here so it is always manipulated | 470 | but we convert it here so it is always manipulated |
@@ -480,8 +498,7 @@ incomplete_rcv: | |||
480 | continue; | 498 | continue; |
481 | } else if (temp != (char) 0) { | 499 | } else if (temp != (char) 0) { |
482 | cERROR(1, "Unknown RFC 1002 frame"); | 500 | cERROR(1, "Unknown RFC 1002 frame"); |
483 | cifs_dump_mem(" Received Data: ", (char *)smb_buffer, | 501 | cifs_dump_mem(" Received Data: ", buf, length); |
484 | length); | ||
485 | cifs_reconnect(server); | 502 | cifs_reconnect(server); |
486 | csocket = server->ssocket; | 503 | csocket = server->ssocket; |
487 | continue; | 504 | continue; |
@@ -504,10 +521,11 @@ incomplete_rcv: | |||
504 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { | 521 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { |
505 | isLargeBuf = true; | 522 | isLargeBuf = true; |
506 | memcpy(bigbuf, smallbuf, 4); | 523 | memcpy(bigbuf, smallbuf, 4); |
507 | smb_buffer = bigbuf; | 524 | smb_buffer = (struct smb_hdr *)bigbuf; |
525 | buf = bigbuf; | ||
508 | } | 526 | } |
509 | length = 0; | 527 | length = 0; |
510 | iov.iov_base = 4 + (char *)smb_buffer; | 528 | iov.iov_base = 4 + buf; |
511 | iov.iov_len = pdu_length; | 529 | iov.iov_len = pdu_length; |
512 | for (total_read = 0; total_read < pdu_length; | 530 | for (total_read = 0; total_read < pdu_length; |
513 | total_read += length) { | 531 | total_read += length) { |
@@ -562,8 +580,8 @@ incomplete_rcv: | |||
562 | */ | 580 | */ |
563 | length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); | 581 | length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); |
564 | if (length != 0) | 582 | if (length != 0) |
565 | cifs_dump_mem("Bad SMB: ", smb_buffer, | 583 | cifs_dump_mem("Bad SMB: ", buf, |
566 | min_t(unsigned int, total_read, 48)); | 584 | min_t(unsigned int, total_read, 48)); |
567 | 585 | ||
568 | mid_entry = NULL; | 586 | mid_entry = NULL; |
569 | server->lstrp = jiffies; | 587 | server->lstrp = jiffies; |
@@ -648,7 +666,7 @@ multi_t2_fnd: | |||
648 | !isMultiRsp) { | 666 | !isMultiRsp) { |
649 | cERROR(1, "No task to wake, unknown frame received! " | 667 | cERROR(1, "No task to wake, unknown frame received! " |
650 | "NumMids %d", atomic_read(&midCount)); | 668 | "NumMids %d", atomic_read(&midCount)); |
651 | cifs_dump_mem("Received Data is: ", (char *)smb_buffer, | 669 | cifs_dump_mem("Received Data is: ", buf, |
652 | sizeof(struct smb_hdr)); | 670 | sizeof(struct smb_hdr)); |
653 | #ifdef CONFIG_CIFS_DEBUG2 | 671 | #ifdef CONFIG_CIFS_DEBUG2 |
654 | cifs_dump_detail(smb_buffer); | 672 | cifs_dump_detail(smb_buffer); |