diff options
author | Jeff Layton <jlayton@redhat.com> | 2011-10-19 15:29:05 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@redhat.com> | 2011-10-19 15:29:05 -0400 |
commit | ea1f4502fc939b64807f9ab0eca259321047fe83 (patch) | |
tree | d572678f31748fa8e4012747008cad6e892b3f9f /fs/cifs | |
parent | 89482a56a079f01c2f4c709f8e23fbf7eeda1b43 (diff) |
cifs: move mid finding into separate routine
Begin breaking up find_cifs_mid into smaller pieces. The parts that
coalesce T2 responses don't really need to be done under the
GlobalMid_lock anyway. Create a new function that just finds the
mid on the list, and then later takes it off the list if the entire
response has been received.
Reviewed-and-Tested-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/connect.c | 113 |
1 files changed, 66 insertions, 47 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 5308bc6e1248..0f69b311d3fc 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -542,61 +542,80 @@ is_smb_response(struct TCP_Server_Info *server, unsigned char type) | |||
542 | } | 542 | } |
543 | 543 | ||
544 | static struct mid_q_entry * | 544 | static struct mid_q_entry * |
545 | find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf, | 545 | find_mid(struct TCP_Server_Info *server, struct smb_hdr *buf) |
546 | int *length, bool is_large_buf, bool *is_multi_rsp, char **bigbuf) | ||
547 | { | 546 | { |
548 | struct mid_q_entry *mid = NULL, *tmp_mid, *ret = NULL; | 547 | struct mid_q_entry *mid; |
549 | 548 | ||
550 | spin_lock(&GlobalMid_Lock); | 549 | spin_lock(&GlobalMid_Lock); |
551 | list_for_each_entry_safe(mid, tmp_mid, &server->pending_mid_q, qhead) { | 550 | list_for_each_entry(mid, &server->pending_mid_q, qhead) { |
552 | if (mid->mid != buf->Mid || | 551 | if (mid->mid == buf->Mid && |
553 | mid->midState != MID_REQUEST_SUBMITTED || | 552 | mid->midState == MID_REQUEST_SUBMITTED && |
554 | mid->command != buf->Command) | 553 | mid->command == buf->Command) { |
555 | continue; | 554 | spin_unlock(&GlobalMid_Lock); |
556 | 555 | return mid; | |
557 | if (*length == 0 && check2ndT2(buf) > 0) { | ||
558 | /* We have a multipart transact2 resp */ | ||
559 | *is_multi_rsp = true; | ||
560 | if (mid->resp_buf) { | ||
561 | /* merge response - fix up 1st*/ | ||
562 | *length = coalesce_t2(buf, mid->resp_buf); | ||
563 | if (*length > 0) { | ||
564 | *length = 0; | ||
565 | mid->multiRsp = true; | ||
566 | break; | ||
567 | } | ||
568 | /* All parts received or packet is malformed. */ | ||
569 | mid->multiEnd = true; | ||
570 | goto multi_t2_fnd; | ||
571 | } | ||
572 | if (!is_large_buf) { | ||
573 | /*FIXME: switch to already allocated largebuf?*/ | ||
574 | cERROR(1, "1st trans2 resp needs bigbuf"); | ||
575 | } else { | ||
576 | /* Have first buffer */ | ||
577 | mid->resp_buf = buf; | ||
578 | mid->largeBuf = true; | ||
579 | *bigbuf = NULL; | ||
580 | } | ||
581 | break; | ||
582 | } | 556 | } |
583 | mid->resp_buf = buf; | 557 | } |
584 | mid->largeBuf = is_large_buf; | 558 | spin_unlock(&GlobalMid_Lock); |
585 | multi_t2_fnd: | 559 | return NULL; |
586 | if (*length == 0) | 560 | } |
587 | mid->midState = MID_RESPONSE_RECEIVED; | 561 | |
588 | else | 562 | static void |
589 | mid->midState = MID_RESPONSE_MALFORMED; | 563 | dequeue_mid(struct mid_q_entry *mid, int malformed) |
564 | { | ||
590 | #ifdef CONFIG_CIFS_STATS2 | 565 | #ifdef CONFIG_CIFS_STATS2 |
591 | mid->when_received = jiffies; | 566 | mid->when_received = jiffies; |
592 | #endif | 567 | #endif |
593 | list_del_init(&mid->qhead); | 568 | spin_lock(&GlobalMid_Lock); |
594 | ret = mid; | 569 | if (!malformed) |
595 | break; | 570 | mid->midState = MID_RESPONSE_RECEIVED; |
596 | } | 571 | else |
572 | mid->midState = MID_RESPONSE_MALFORMED; | ||
573 | list_del_init(&mid->qhead); | ||
597 | spin_unlock(&GlobalMid_Lock); | 574 | spin_unlock(&GlobalMid_Lock); |
575 | } | ||
598 | 576 | ||
599 | return ret; | 577 | static struct mid_q_entry * |
578 | find_cifs_mid(struct TCP_Server_Info *server, struct smb_hdr *buf, | ||
579 | int *malformed, bool is_large_buf, bool *is_multi_rsp, | ||
580 | char **bigbuf) | ||
581 | { | ||
582 | struct mid_q_entry *mid = NULL; | ||
583 | |||
584 | mid = find_mid(server, buf); | ||
585 | if (!mid) | ||
586 | return mid; | ||
587 | |||
588 | if (*malformed == 0 && check2ndT2(buf) > 0) { | ||
589 | /* We have a multipart transact2 resp */ | ||
590 | *is_multi_rsp = true; | ||
591 | if (mid->resp_buf) { | ||
592 | /* merge response - fix up 1st*/ | ||
593 | *malformed = coalesce_t2(buf, mid->resp_buf); | ||
594 | if (*malformed > 0) { | ||
595 | *malformed = 0; | ||
596 | mid->multiRsp = true; | ||
597 | return NULL; | ||
598 | } | ||
599 | /* All parts received or packet is malformed. */ | ||
600 | mid->multiEnd = true; | ||
601 | goto multi_t2_fnd; | ||
602 | } | ||
603 | if (!is_large_buf) { | ||
604 | /*FIXME: switch to already allocated largebuf?*/ | ||
605 | cERROR(1, "1st trans2 resp needs bigbuf"); | ||
606 | } else { | ||
607 | /* Have first buffer */ | ||
608 | mid->resp_buf = buf; | ||
609 | mid->largeBuf = true; | ||
610 | *bigbuf = NULL; | ||
611 | } | ||
612 | return mid; | ||
613 | } | ||
614 | mid->resp_buf = buf; | ||
615 | mid->largeBuf = is_large_buf; | ||
616 | multi_t2_fnd: | ||
617 | dequeue_mid(mid, *malformed); | ||
618 | return mid; | ||
600 | } | 619 | } |
601 | 620 | ||
602 | static void clean_demultiplex_info(struct TCP_Server_Info *server) | 621 | static void clean_demultiplex_info(struct TCP_Server_Info *server) |