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 | |
| 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>
| -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); |
