diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/connect.c | 126 |
1 files changed, 61 insertions, 65 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2a53ade3e637..12b2741ef8f7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -473,6 +473,64 @@ check_rfc1002_header(struct TCP_Server_Info *server, char *buf) | |||
473 | return true; | 473 | return true; |
474 | } | 474 | } |
475 | 475 | ||
476 | static struct mid_q_entry * | ||
477 | find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf, | ||
478 | int *length, bool is_large_buf, bool *is_multi_rsp, char **bigbuf) | ||
479 | { | ||
480 | struct mid_q_entry *mid = NULL, *tmp_mid, *ret = NULL; | ||
481 | |||
482 | spin_lock(&GlobalMid_Lock); | ||
483 | list_for_each_entry_safe(mid, tmp_mid, &server->pending_mid_q, qhead) { | ||
484 | if (mid->mid != buf->Mid || | ||
485 | mid->midState != MID_REQUEST_SUBMITTED || | ||
486 | mid->command != buf->Command) | ||
487 | continue; | ||
488 | |||
489 | if (*length == 0 && check2ndT2(buf, server->maxBuf) > 0) { | ||
490 | /* We have a multipart transact2 resp */ | ||
491 | *is_multi_rsp = true; | ||
492 | if (mid->resp_buf) { | ||
493 | /* merge response - fix up 1st*/ | ||
494 | *length = coalesce_t2(buf, mid->resp_buf); | ||
495 | if (*length > 0) { | ||
496 | *length = 0; | ||
497 | mid->multiRsp = true; | ||
498 | break; | ||
499 | } | ||
500 | /* All parts received or packet is malformed. */ | ||
501 | mid->multiEnd = true; | ||
502 | goto multi_t2_fnd; | ||
503 | } | ||
504 | if (!is_large_buf) { | ||
505 | /*FIXME: switch to already allocated largebuf?*/ | ||
506 | cERROR(1, "1st trans2 resp needs bigbuf"); | ||
507 | } else { | ||
508 | /* Have first buffer */ | ||
509 | mid->resp_buf = buf; | ||
510 | mid->largeBuf = true; | ||
511 | *bigbuf = NULL; | ||
512 | } | ||
513 | break; | ||
514 | } | ||
515 | mid->resp_buf = buf; | ||
516 | mid->largeBuf = is_large_buf; | ||
517 | multi_t2_fnd: | ||
518 | if (*length == 0) | ||
519 | mid->midState = MID_RESPONSE_RECEIVED; | ||
520 | else | ||
521 | mid->midState = MID_RESPONSE_MALFORMED; | ||
522 | #ifdef CONFIG_CIFS_STATS2 | ||
523 | mid->when_received = jiffies; | ||
524 | #endif | ||
525 | list_del_init(&mid->qhead); | ||
526 | ret = mid; | ||
527 | break; | ||
528 | } | ||
529 | spin_unlock(&GlobalMid_Lock); | ||
530 | |||
531 | return ret; | ||
532 | } | ||
533 | |||
476 | static int | 534 | static int |
477 | cifs_demultiplex_thread(void *p) | 535 | cifs_demultiplex_thread(void *p) |
478 | { | 536 | { |
@@ -487,7 +545,7 @@ cifs_demultiplex_thread(void *p) | |||
487 | struct task_struct *task_to_wake = NULL; | 545 | struct task_struct *task_to_wake = NULL; |
488 | struct mid_q_entry *mid_entry; | 546 | struct mid_q_entry *mid_entry; |
489 | bool isLargeBuf = false; | 547 | bool isLargeBuf = false; |
490 | bool isMultiRsp; | 548 | bool isMultiRsp = false; |
491 | int rc; | 549 | int rc; |
492 | 550 | ||
493 | current->flags |= PF_MEMALLOC; | 551 | current->flags |= PF_MEMALLOC; |
@@ -589,72 +647,10 @@ incomplete_rcv: | |||
589 | cifs_dump_mem("Bad SMB: ", buf, | 647 | cifs_dump_mem("Bad SMB: ", buf, |
590 | min_t(unsigned int, total_read, 48)); | 648 | min_t(unsigned int, total_read, 48)); |
591 | 649 | ||
592 | mid_entry = NULL; | ||
593 | server->lstrp = jiffies; | 650 | server->lstrp = jiffies; |
594 | 651 | ||
595 | spin_lock(&GlobalMid_Lock); | 652 | mid_entry = find_cifs_mid(server, smb_buffer, &length, |
596 | list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { | 653 | isLargeBuf, &isMultiRsp, &bigbuf); |
597 | mid_entry = list_entry(tmp, struct mid_q_entry, qhead); | ||
598 | |||
599 | if (mid_entry->mid != smb_buffer->Mid || | ||
600 | mid_entry->midState != MID_REQUEST_SUBMITTED || | ||
601 | mid_entry->command != smb_buffer->Command) { | ||
602 | mid_entry = NULL; | ||
603 | continue; | ||
604 | } | ||
605 | |||
606 | if (length == 0 && | ||
607 | check2ndT2(smb_buffer, server->maxBuf) > 0) { | ||
608 | /* We have a multipart transact2 resp */ | ||
609 | isMultiRsp = true; | ||
610 | if (mid_entry->resp_buf) { | ||
611 | /* merge response - fix up 1st*/ | ||
612 | length = coalesce_t2(smb_buffer, | ||
613 | mid_entry->resp_buf); | ||
614 | if (length > 0) { | ||
615 | length = 0; | ||
616 | mid_entry->multiRsp = true; | ||
617 | break; | ||
618 | } else { | ||
619 | /* all parts received or | ||
620 | * packet is malformed | ||
621 | */ | ||
622 | mid_entry->multiEnd = true; | ||
623 | goto multi_t2_fnd; | ||
624 | } | ||
625 | } else { | ||
626 | if (!isLargeBuf) { | ||
627 | /* | ||
628 | * FIXME: switch to already | ||
629 | * allocated largebuf? | ||
630 | */ | ||
631 | cERROR(1, "1st trans2 resp " | ||
632 | "needs bigbuf"); | ||
633 | } else { | ||
634 | /* Have first buffer */ | ||
635 | mid_entry->resp_buf = | ||
636 | smb_buffer; | ||
637 | mid_entry->largeBuf = true; | ||
638 | bigbuf = NULL; | ||
639 | } | ||
640 | } | ||
641 | break; | ||
642 | } | ||
643 | mid_entry->resp_buf = smb_buffer; | ||
644 | mid_entry->largeBuf = isLargeBuf; | ||
645 | multi_t2_fnd: | ||
646 | if (length == 0) | ||
647 | mid_entry->midState = MID_RESPONSE_RECEIVED; | ||
648 | else | ||
649 | mid_entry->midState = MID_RESPONSE_MALFORMED; | ||
650 | #ifdef CONFIG_CIFS_STATS2 | ||
651 | mid_entry->when_received = jiffies; | ||
652 | #endif | ||
653 | list_del_init(&mid_entry->qhead); | ||
654 | break; | ||
655 | } | ||
656 | spin_unlock(&GlobalMid_Lock); | ||
657 | |||
658 | if (mid_entry != NULL) { | 654 | if (mid_entry != NULL) { |
659 | mid_entry->callback(mid_entry); | 655 | mid_entry->callback(mid_entry); |
660 | /* Was previous buf put in mpx struct for multi-rsp? */ | 656 | /* Was previous buf put in mpx struct for multi-rsp? */ |