diff options
author | Jeff Layton <jlayton@redhat.com> | 2011-10-19 15:28:57 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@redhat.com> | 2011-10-19 15:28:57 -0400 |
commit | 89482a56a079f01c2f4c709f8e23fbf7eeda1b43 (patch) | |
tree | 5b61c1e06da9bf78c71c871016909497b7cbe6e1 /fs/cifs/connect.c | |
parent | 1041e3f9919999b22c9c2a453aa0d92cd16b76ee (diff) |
cifs: add a third receive phase to cifs_demultiplex_thread
Have the demultiplex thread receive just enough to get to the MID, and
then find it before receiving the rest. Later, we'll use this to swap
in a preallocated receive buffer for some calls.
Reviewed-and-Tested-by: Pavel Shilovsky <piastry@etersoft.ru>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs/connect.c')
-rw-r--r-- | fs/cifs/connect.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ee70075c5fb1..5308bc6e1248 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -746,11 +746,25 @@ cifs_demultiplex_thread(void *p) | |||
746 | if (!is_smb_response(server, buf[0])) | 746 | if (!is_smb_response(server, buf[0])) |
747 | continue; | 747 | continue; |
748 | 748 | ||
749 | /* check the length */ | 749 | /* make sure we have enough to get to the MID */ |
750 | if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || | 750 | if (pdu_length < sizeof(struct smb_hdr) - 1 - 4) { |
751 | (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { | 751 | cERROR(1, "SMB response too short (%u bytes)", |
752 | cERROR(1, "Invalid size SMB length %d pdu_length %d", | 752 | pdu_length); |
753 | 4, pdu_length + 4); | 753 | cifs_reconnect(server); |
754 | wake_up(&server->response_q); | ||
755 | continue; | ||
756 | } | ||
757 | |||
758 | /* read down to the MID */ | ||
759 | length = read_from_socket(server, buf + 4, | ||
760 | sizeof(struct smb_hdr) - 1 - 4); | ||
761 | if (length < 0) | ||
762 | continue; | ||
763 | total_read += length; | ||
764 | |||
765 | if (pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { | ||
766 | cERROR(1, "SMB response too long (%u bytes)", | ||
767 | pdu_length); | ||
754 | cifs_reconnect(server); | 768 | cifs_reconnect(server); |
755 | wake_up(&server->response_q); | 769 | wake_up(&server->response_q); |
756 | continue; | 770 | continue; |
@@ -759,12 +773,15 @@ cifs_demultiplex_thread(void *p) | |||
759 | /* else length ok */ | 773 | /* else length ok */ |
760 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { | 774 | if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { |
761 | isLargeBuf = true; | 775 | isLargeBuf = true; |
762 | memcpy(bigbuf, smallbuf, 4); | 776 | memcpy(bigbuf, smallbuf, total_read); |
763 | smb_buffer = (struct smb_hdr *)bigbuf; | 777 | smb_buffer = (struct smb_hdr *)bigbuf; |
764 | buf = bigbuf; | 778 | buf = bigbuf; |
765 | } | 779 | } |
766 | 780 | ||
767 | length = read_from_socket(server, buf + 4, pdu_length); | 781 | /* now read the rest */ |
782 | length = read_from_socket(server, | ||
783 | buf + sizeof(struct smb_hdr) - 1, | ||
784 | pdu_length - sizeof(struct smb_hdr) + 1 + 4); | ||
768 | if (length < 0) | 785 | if (length < 0) |
769 | continue; | 786 | continue; |
770 | total_read += length; | 787 | total_read += length; |