diff options
author | Pavel Shilovsky <piastry@etersoft.ru> | 2012-03-23 14:28:02 -0400 |
---|---|---|
committer | Jeff Layton <jlayton@redhat.com> | 2012-03-23 14:28:02 -0400 |
commit | 792af7b05b8a78def080ec757a4d4420b9fd0cc2 (patch) | |
tree | 6f6d556f155194295375f3d4ad6cbfabbd7aeeeb /fs | |
parent | 934e18b5cb4531cc6e81865bf54115cfd21d1ac6 (diff) |
CIFS: Separate protocol-specific code from transport routines
that lets us use this functions for SMB2.
Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifs_debug.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 21 | ||||
-rw-r--r-- | fs/cifs/misc.c | 5 | ||||
-rw-r--r-- | fs/cifs/transport.c | 171 |
6 files changed, 119 insertions, 88 deletions
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 8942b28cf807..0a234c1db947 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h | |||
@@ -32,7 +32,7 @@ void cifs_dump_mids(struct TCP_Server_Info *); | |||
32 | #define DBG2 0 | 32 | #define DBG2 0 |
33 | #endif | 33 | #endif |
34 | extern int traceSMB; /* flag which enables the function below */ | 34 | extern int traceSMB; /* flag which enables the function below */ |
35 | void dump_smb(struct smb_hdr *, int); | 35 | void dump_smb(void *, int); |
36 | #define CIFS_INFO 0x01 | 36 | #define CIFS_INFO 0x01 |
37 | #define CIFS_RC 0x02 | 37 | #define CIFS_RC 0x02 |
38 | #define CIFS_TIMER 0x04 | 38 | #define CIFS_TIMER 0x04 |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 339ebe3ebc0d..c3c7d7c46220 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -230,6 +230,12 @@ struct cifs_mnt_data { | |||
230 | int flags; | 230 | int flags; |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static inline unsigned int | ||
234 | get_rfc1002_length(void *buf) | ||
235 | { | ||
236 | return be32_to_cpu(*((__be32 *)buf)); | ||
237 | } | ||
238 | |||
233 | struct TCP_Server_Info { | 239 | struct TCP_Server_Info { |
234 | struct list_head tcp_ses_list; | 240 | struct list_head tcp_ses_list; |
235 | struct list_head smb_ses_list; | 241 | struct list_head smb_ses_list; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 503e73d8bdb7..5f2f266c42a4 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -77,7 +77,7 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, | |||
77 | struct smb_hdr * /* out */ , | 77 | struct smb_hdr * /* out */ , |
78 | int * /* bytes returned */ , const int long_op); | 78 | int * /* bytes returned */ , const int long_op); |
79 | extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, | 79 | extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, |
80 | struct smb_hdr *in_buf, int flags); | 80 | char *in_buf, int flags); |
81 | extern int cifs_check_receive(struct mid_q_entry *mid, | 81 | extern int cifs_check_receive(struct mid_q_entry *mid, |
82 | struct TCP_Server_Info *server, bool log_error); | 82 | struct TCP_Server_Info *server, bool log_error); |
83 | extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, | 83 | extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 70aac35c398f..a7ed01cd0242 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -696,7 +696,7 @@ CIFSSMBTDis(const int xid, struct cifs_tcon *tcon) | |||
696 | if (rc) | 696 | if (rc) |
697 | return rc; | 697 | return rc; |
698 | 698 | ||
699 | rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); | 699 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0); |
700 | if (rc) | 700 | if (rc) |
701 | cFYI(1, "Tree disconnect failed %d", rc); | 701 | cFYI(1, "Tree disconnect failed %d", rc); |
702 | 702 | ||
@@ -792,7 +792,7 @@ CIFSSMBLogoff(const int xid, struct cifs_ses *ses) | |||
792 | pSMB->hdr.Uid = ses->Suid; | 792 | pSMB->hdr.Uid = ses->Suid; |
793 | 793 | ||
794 | pSMB->AndXCommand = 0xFF; | 794 | pSMB->AndXCommand = 0xFF; |
795 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); | 795 | rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0); |
796 | session_already_dead: | 796 | session_already_dead: |
797 | mutex_unlock(&ses->session_mutex); | 797 | mutex_unlock(&ses->session_mutex); |
798 | 798 | ||
@@ -2420,8 +2420,7 @@ CIFSSMBLock(const int xid, struct cifs_tcon *tcon, | |||
2420 | (struct smb_hdr *) pSMB, &bytes_returned); | 2420 | (struct smb_hdr *) pSMB, &bytes_returned); |
2421 | cifs_small_buf_release(pSMB); | 2421 | cifs_small_buf_release(pSMB); |
2422 | } else { | 2422 | } else { |
2423 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, | 2423 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout); |
2424 | timeout); | ||
2425 | /* SMB buffer freed by function above */ | 2424 | /* SMB buffer freed by function above */ |
2426 | } | 2425 | } |
2427 | cifs_stats_inc(&tcon->num_locks); | 2426 | cifs_stats_inc(&tcon->num_locks); |
@@ -2588,7 +2587,7 @@ CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2588 | pSMB->FileID = (__u16) smb_file_id; | 2587 | pSMB->FileID = (__u16) smb_file_id; |
2589 | pSMB->LastWriteTime = 0xFFFFFFFF; | 2588 | pSMB->LastWriteTime = 0xFFFFFFFF; |
2590 | pSMB->ByteCount = 0; | 2589 | pSMB->ByteCount = 0; |
2591 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 2590 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
2592 | cifs_stats_inc(&tcon->num_closes); | 2591 | cifs_stats_inc(&tcon->num_closes); |
2593 | if (rc) { | 2592 | if (rc) { |
2594 | if (rc != -EINTR) { | 2593 | if (rc != -EINTR) { |
@@ -2617,7 +2616,7 @@ CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id) | |||
2617 | 2616 | ||
2618 | pSMB->FileID = (__u16) smb_file_id; | 2617 | pSMB->FileID = (__u16) smb_file_id; |
2619 | pSMB->ByteCount = 0; | 2618 | pSMB->ByteCount = 0; |
2620 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 2619 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
2621 | cifs_stats_inc(&tcon->num_flushes); | 2620 | cifs_stats_inc(&tcon->num_flushes); |
2622 | if (rc) | 2621 | if (rc) |
2623 | cERROR(1, "Send error in Flush = %d", rc); | 2622 | cERROR(1, "Send error in Flush = %d", rc); |
@@ -4625,7 +4624,7 @@ CIFSFindClose(const int xid, struct cifs_tcon *tcon, | |||
4625 | 4624 | ||
4626 | pSMB->FileID = searchHandle; | 4625 | pSMB->FileID = searchHandle; |
4627 | pSMB->ByteCount = 0; | 4626 | pSMB->ByteCount = 0; |
4628 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 4627 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
4629 | if (rc) | 4628 | if (rc) |
4630 | cERROR(1, "Send error in FindClose = %d", rc); | 4629 | cERROR(1, "Send error in FindClose = %d", rc); |
4631 | 4630 | ||
@@ -5646,7 +5645,7 @@ CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size, | |||
5646 | pSMB->Reserved4 = 0; | 5645 | pSMB->Reserved4 = 0; |
5647 | inc_rfc1001_len(pSMB, byte_count); | 5646 | inc_rfc1001_len(pSMB, byte_count); |
5648 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5647 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5649 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5648 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5650 | if (rc) { | 5649 | if (rc) { |
5651 | cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); | 5650 | cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); |
5652 | } | 5651 | } |
@@ -5715,7 +5714,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, | |||
5715 | inc_rfc1001_len(pSMB, byte_count); | 5714 | inc_rfc1001_len(pSMB, byte_count); |
5716 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5715 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5717 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); | 5716 | memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); |
5718 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5717 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5719 | if (rc) | 5718 | if (rc) |
5720 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); | 5719 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); |
5721 | 5720 | ||
@@ -5774,7 +5773,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, | |||
5774 | inc_rfc1001_len(pSMB, byte_count); | 5773 | inc_rfc1001_len(pSMB, byte_count); |
5775 | pSMB->ByteCount = cpu_to_le16(byte_count); | 5774 | pSMB->ByteCount = cpu_to_le16(byte_count); |
5776 | *data_offset = delete_file ? 1 : 0; | 5775 | *data_offset = delete_file ? 1 : 0; |
5777 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 5776 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
5778 | if (rc) | 5777 | if (rc) |
5779 | cFYI(1, "Send error in SetFileDisposition = %d", rc); | 5778 | cFYI(1, "Send error in SetFileDisposition = %d", rc); |
5780 | 5779 | ||
@@ -6006,7 +6005,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, | |||
6006 | 6005 | ||
6007 | cifs_fill_unix_set_info(data_offset, args); | 6006 | cifs_fill_unix_set_info(data_offset, args); |
6008 | 6007 | ||
6009 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | 6008 | rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); |
6010 | if (rc) | 6009 | if (rc) |
6011 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); | 6010 | cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); |
6012 | 6011 | ||
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index c273c12de98e..e88601fc6f22 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -604,16 +604,15 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
604 | } | 604 | } |
605 | 605 | ||
606 | void | 606 | void |
607 | dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) | 607 | dump_smb(void *buf, int smb_buf_length) |
608 | { | 608 | { |
609 | int i, j; | 609 | int i, j; |
610 | char debug_line[17]; | 610 | char debug_line[17]; |
611 | unsigned char *buffer; | 611 | unsigned char *buffer = buf; |
612 | 612 | ||
613 | if (traceSMB == 0) | 613 | if (traceSMB == 0) |
614 | return; | 614 | return; |
615 | 615 | ||
616 | buffer = (unsigned char *) smb_buf; | ||
617 | for (i = 0, j = 0; i < smb_buf_length; i++, j++) { | 616 | for (i = 0, j = 0; i < smb_buf_length; i++, j++) { |
618 | if (i % 8 == 0) { | 617 | if (i % 8 == 0) { |
619 | /* have reached the beginning of line */ | 618 | /* have reached the beginning of line */ |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 310918b6fcb4..3bb447d07a1d 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -126,11 +126,11 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
126 | int rc = 0; | 126 | int rc = 0; |
127 | int i = 0; | 127 | int i = 0; |
128 | struct msghdr smb_msg; | 128 | struct msghdr smb_msg; |
129 | struct smb_hdr *smb_buffer = iov[0].iov_base; | 129 | __be32 *buf_len = (__be32 *)(iov[0].iov_base); |
130 | unsigned int len = iov[0].iov_len; | 130 | unsigned int len = iov[0].iov_len; |
131 | unsigned int total_len; | 131 | unsigned int total_len; |
132 | int first_vec = 0; | 132 | int first_vec = 0; |
133 | unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length); | 133 | unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); |
134 | struct socket *ssocket = server->ssocket; | 134 | struct socket *ssocket = server->ssocket; |
135 | 135 | ||
136 | if (ssocket == NULL) | 136 | if (ssocket == NULL) |
@@ -150,7 +150,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
150 | total_len += iov[i].iov_len; | 150 | total_len += iov[i].iov_len; |
151 | 151 | ||
152 | cFYI(1, "Sending smb: total_len %d", total_len); | 152 | cFYI(1, "Sending smb: total_len %d", total_len); |
153 | dump_smb(smb_buffer, len); | 153 | dump_smb(iov[0].iov_base, len); |
154 | 154 | ||
155 | i = 0; | 155 | i = 0; |
156 | while (total_len) { | 156 | while (total_len) { |
@@ -158,24 +158,24 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
158 | n_vec - first_vec, total_len); | 158 | n_vec - first_vec, total_len); |
159 | if ((rc == -ENOSPC) || (rc == -EAGAIN)) { | 159 | if ((rc == -ENOSPC) || (rc == -EAGAIN)) { |
160 | i++; | 160 | i++; |
161 | /* if blocking send we try 3 times, since each can block | 161 | /* |
162 | for 5 seconds. For nonblocking we have to try more | 162 | * If blocking send we try 3 times, since each can block |
163 | but wait increasing amounts of time allowing time for | 163 | * for 5 seconds. For nonblocking we have to try more |
164 | socket to clear. The overall time we wait in either | 164 | * but wait increasing amounts of time allowing time for |
165 | case to send on the socket is about 15 seconds. | 165 | * socket to clear. The overall time we wait in either |
166 | Similarly we wait for 15 seconds for | 166 | * case to send on the socket is about 15 seconds. |
167 | a response from the server in SendReceive[2] | 167 | * Similarly we wait for 15 seconds for a response from |
168 | for the server to send a response back for | 168 | * the server in SendReceive[2] for the server to send |
169 | most types of requests (except SMB Write | 169 | * a response back for most types of requests (except |
170 | past end of file which can be slow, and | 170 | * SMB Write past end of file which can be slow, and |
171 | blocking lock operations). NFS waits slightly longer | 171 | * blocking lock operations). NFS waits slightly longer |
172 | than CIFS, but this can make it take longer for | 172 | * than CIFS, but this can make it take longer for |
173 | nonresponsive servers to be detected and 15 seconds | 173 | * nonresponsive servers to be detected and 15 seconds |
174 | is more than enough time for modern networks to | 174 | * is more than enough time for modern networks to |
175 | send a packet. In most cases if we fail to send | 175 | * send a packet. In most cases if we fail to send |
176 | after the retries we will kill the socket and | 176 | * after the retries we will kill the socket and |
177 | reconnect which may clear the network problem. | 177 | * reconnect which may clear the network problem. |
178 | */ | 178 | */ |
179 | if ((i >= 14) || (!server->noblocksnd && (i > 2))) { | 179 | if ((i >= 14) || (!server->noblocksnd && (i > 2))) { |
180 | cERROR(1, "sends on sock %p stuck for 15 seconds", | 180 | cERROR(1, "sends on sock %p stuck for 15 seconds", |
181 | ssocket); | 181 | ssocket); |
@@ -235,9 +235,8 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) | |||
235 | else | 235 | else |
236 | rc = 0; | 236 | rc = 0; |
237 | 237 | ||
238 | /* Don't want to modify the buffer as a | 238 | /* Don't want to modify the buffer as a side effect of this call. */ |
239 | side effect of this call. */ | 239 | *buf_len = cpu_to_be32(smb_buf_length); |
240 | smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length); | ||
241 | 240 | ||
242 | return rc; | 241 | return rc; |
243 | } | 242 | } |
@@ -349,6 +348,33 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) | |||
349 | return 0; | 348 | return 0; |
350 | } | 349 | } |
351 | 350 | ||
351 | static int | ||
352 | cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov, | ||
353 | unsigned int nvec, struct mid_q_entry **ret_mid) | ||
354 | { | ||
355 | int rc; | ||
356 | struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; | ||
357 | struct mid_q_entry *mid; | ||
358 | |||
359 | /* enable signing if server requires it */ | ||
360 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
361 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
362 | |||
363 | mid = AllocMidQEntry(hdr, server); | ||
364 | if (mid == NULL) | ||
365 | return -ENOMEM; | ||
366 | |||
367 | /* put it on the pending_mid_q */ | ||
368 | spin_lock(&GlobalMid_Lock); | ||
369 | list_add_tail(&mid->qhead, &server->pending_mid_q); | ||
370 | spin_unlock(&GlobalMid_Lock); | ||
371 | |||
372 | rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); | ||
373 | if (rc) | ||
374 | delete_mid(mid); | ||
375 | *ret_mid = mid; | ||
376 | return rc; | ||
377 | } | ||
352 | 378 | ||
353 | /* | 379 | /* |
354 | * Send a SMB request and set the callback function in the mid to handle | 380 | * Send a SMB request and set the callback function in the mid to handle |
@@ -361,34 +387,18 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, | |||
361 | { | 387 | { |
362 | int rc; | 388 | int rc; |
363 | struct mid_q_entry *mid; | 389 | struct mid_q_entry *mid; |
364 | struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; | ||
365 | 390 | ||
366 | rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); | 391 | rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); |
367 | if (rc) | 392 | if (rc) |
368 | return rc; | 393 | return rc; |
369 | 394 | ||
370 | /* enable signing if server requires it */ | ||
371 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
372 | hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; | ||
373 | |||
374 | mutex_lock(&server->srv_mutex); | 395 | mutex_lock(&server->srv_mutex); |
375 | mid = AllocMidQEntry(hdr, server); | 396 | rc = cifs_setup_async_request(server, iov, nvec, &mid); |
376 | if (mid == NULL) { | 397 | if (rc) { |
377 | mutex_unlock(&server->srv_mutex); | 398 | mutex_unlock(&server->srv_mutex); |
378 | cifs_add_credits(server, 1); | 399 | cifs_add_credits(server, 1); |
379 | wake_up(&server->request_q); | 400 | wake_up(&server->request_q); |
380 | return -ENOMEM; | 401 | return rc; |
381 | } | ||
382 | |||
383 | /* put it on the pending_mid_q */ | ||
384 | spin_lock(&GlobalMid_Lock); | ||
385 | list_add_tail(&mid->qhead, &server->pending_mid_q); | ||
386 | spin_unlock(&GlobalMid_Lock); | ||
387 | |||
388 | rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); | ||
389 | if (rc) { | ||
390 | mutex_unlock(&server->srv_mutex); | ||
391 | goto out_err; | ||
392 | } | 402 | } |
393 | 403 | ||
394 | mid->receive = receive; | 404 | mid->receive = receive; |
@@ -424,14 +434,14 @@ out_err: | |||
424 | */ | 434 | */ |
425 | int | 435 | int |
426 | SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, | 436 | SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, |
427 | struct smb_hdr *in_buf, int flags) | 437 | char *in_buf, int flags) |
428 | { | 438 | { |
429 | int rc; | 439 | int rc; |
430 | struct kvec iov[1]; | 440 | struct kvec iov[1]; |
431 | int resp_buf_type; | 441 | int resp_buf_type; |
432 | 442 | ||
433 | iov[0].iov_base = (char *)in_buf; | 443 | iov[0].iov_base = in_buf; |
434 | iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4; | 444 | iov[0].iov_len = get_rfc1002_length(in_buf) + 4; |
435 | flags |= CIFS_NO_RESP; | 445 | flags |= CIFS_NO_RESP; |
436 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); | 446 | rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); |
437 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); | 447 | cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); |
@@ -514,7 +524,7 @@ int | |||
514 | cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | 524 | cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, |
515 | bool log_error) | 525 | bool log_error) |
516 | { | 526 | { |
517 | unsigned int len = be32_to_cpu(mid->resp_buf->smb_buf_length) + 4; | 527 | unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; |
518 | 528 | ||
519 | dump_smb(mid->resp_buf, min_t(u32, 92, len)); | 529 | dump_smb(mid->resp_buf, min_t(u32, 92, len)); |
520 | 530 | ||
@@ -534,6 +544,24 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, | |||
534 | return map_smb_to_linux_error(mid->resp_buf, log_error); | 544 | return map_smb_to_linux_error(mid->resp_buf, log_error); |
535 | } | 545 | } |
536 | 546 | ||
547 | static int | ||
548 | cifs_setup_request(struct cifs_ses *ses, struct kvec *iov, | ||
549 | unsigned int nvec, struct mid_q_entry **ret_mid) | ||
550 | { | ||
551 | int rc; | ||
552 | struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; | ||
553 | struct mid_q_entry *mid; | ||
554 | |||
555 | rc = allocate_mid(ses, hdr, &mid); | ||
556 | if (rc) | ||
557 | return rc; | ||
558 | rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number); | ||
559 | if (rc) | ||
560 | delete_mid(mid); | ||
561 | *ret_mid = mid; | ||
562 | return rc; | ||
563 | } | ||
564 | |||
537 | int | 565 | int |
538 | SendReceive2(const unsigned int xid, struct cifs_ses *ses, | 566 | SendReceive2(const unsigned int xid, struct cifs_ses *ses, |
539 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, | 567 | struct kvec *iov, int n_vec, int *pRespBufType /* ret */, |
@@ -542,53 +570,51 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
542 | int rc = 0; | 570 | int rc = 0; |
543 | int long_op; | 571 | int long_op; |
544 | struct mid_q_entry *midQ; | 572 | struct mid_q_entry *midQ; |
545 | struct smb_hdr *in_buf = iov[0].iov_base; | 573 | char *buf = iov[0].iov_base; |
546 | 574 | ||
547 | long_op = flags & CIFS_TIMEOUT_MASK; | 575 | long_op = flags & CIFS_TIMEOUT_MASK; |
548 | 576 | ||
549 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ | 577 | *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ |
550 | 578 | ||
551 | if ((ses == NULL) || (ses->server == NULL)) { | 579 | if ((ses == NULL) || (ses->server == NULL)) { |
552 | cifs_small_buf_release(in_buf); | 580 | cifs_small_buf_release(buf); |
553 | cERROR(1, "Null session"); | 581 | cERROR(1, "Null session"); |
554 | return -EIO; | 582 | return -EIO; |
555 | } | 583 | } |
556 | 584 | ||
557 | if (ses->server->tcpStatus == CifsExiting) { | 585 | if (ses->server->tcpStatus == CifsExiting) { |
558 | cifs_small_buf_release(in_buf); | 586 | cifs_small_buf_release(buf); |
559 | return -ENOENT; | 587 | return -ENOENT; |
560 | } | 588 | } |
561 | 589 | ||
562 | /* Ensure that we do not send more than 50 overlapping requests | 590 | /* |
563 | to the same server. We may make this configurable later or | 591 | * Ensure that we do not send more than 50 overlapping requests |
564 | use ses->maxReq */ | 592 | * to the same server. We may make this configurable later or |
593 | * use ses->maxReq. | ||
594 | */ | ||
565 | 595 | ||
566 | rc = wait_for_free_request(ses->server, long_op); | 596 | rc = wait_for_free_request(ses->server, long_op); |
567 | if (rc) { | 597 | if (rc) { |
568 | cifs_small_buf_release(in_buf); | 598 | cifs_small_buf_release(buf); |
569 | return rc; | 599 | return rc; |
570 | } | 600 | } |
571 | 601 | ||
572 | /* make sure that we sign in the same order that we send on this socket | 602 | /* |
573 | and avoid races inside tcp sendmsg code that could cause corruption | 603 | * Make sure that we sign in the same order that we send on this socket |
574 | of smb data */ | 604 | * and avoid races inside tcp sendmsg code that could cause corruption |
605 | * of smb data. | ||
606 | */ | ||
575 | 607 | ||
576 | mutex_lock(&ses->server->srv_mutex); | 608 | mutex_lock(&ses->server->srv_mutex); |
577 | 609 | ||
578 | rc = allocate_mid(ses, in_buf, &midQ); | 610 | rc = cifs_setup_request(ses, iov, n_vec, &midQ); |
579 | if (rc) { | 611 | if (rc) { |
580 | mutex_unlock(&ses->server->srv_mutex); | 612 | mutex_unlock(&ses->server->srv_mutex); |
581 | cifs_small_buf_release(in_buf); | 613 | cifs_small_buf_release(buf); |
582 | /* Update # of requests on wire to server */ | 614 | /* Update # of requests on wire to server */ |
583 | cifs_add_credits(ses->server, 1); | 615 | cifs_add_credits(ses->server, 1); |
584 | return rc; | 616 | return rc; |
585 | } | 617 | } |
586 | rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); | ||
587 | if (rc) { | ||
588 | mutex_unlock(&ses->server->srv_mutex); | ||
589 | cifs_small_buf_release(in_buf); | ||
590 | goto out; | ||
591 | } | ||
592 | 618 | ||
593 | midQ->midState = MID_REQUEST_SUBMITTED; | 619 | midQ->midState = MID_REQUEST_SUBMITTED; |
594 | cifs_in_send_inc(ses->server); | 620 | cifs_in_send_inc(ses->server); |
@@ -599,30 +625,30 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
599 | mutex_unlock(&ses->server->srv_mutex); | 625 | mutex_unlock(&ses->server->srv_mutex); |
600 | 626 | ||
601 | if (rc < 0) { | 627 | if (rc < 0) { |
602 | cifs_small_buf_release(in_buf); | 628 | cifs_small_buf_release(buf); |
603 | goto out; | 629 | goto out; |
604 | } | 630 | } |
605 | 631 | ||
606 | if (long_op == CIFS_ASYNC_OP) { | 632 | if (long_op == CIFS_ASYNC_OP) { |
607 | cifs_small_buf_release(in_buf); | 633 | cifs_small_buf_release(buf); |
608 | goto out; | 634 | goto out; |
609 | } | 635 | } |
610 | 636 | ||
611 | rc = wait_for_response(ses->server, midQ); | 637 | rc = wait_for_response(ses->server, midQ); |
612 | if (rc != 0) { | 638 | if (rc != 0) { |
613 | send_nt_cancel(ses->server, in_buf, midQ); | 639 | send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ); |
614 | spin_lock(&GlobalMid_Lock); | 640 | spin_lock(&GlobalMid_Lock); |
615 | if (midQ->midState == MID_REQUEST_SUBMITTED) { | 641 | if (midQ->midState == MID_REQUEST_SUBMITTED) { |
616 | midQ->callback = DeleteMidQEntry; | 642 | midQ->callback = DeleteMidQEntry; |
617 | spin_unlock(&GlobalMid_Lock); | 643 | spin_unlock(&GlobalMid_Lock); |
618 | cifs_small_buf_release(in_buf); | 644 | cifs_small_buf_release(buf); |
619 | cifs_add_credits(ses->server, 1); | 645 | cifs_add_credits(ses->server, 1); |
620 | return rc; | 646 | return rc; |
621 | } | 647 | } |
622 | spin_unlock(&GlobalMid_Lock); | 648 | spin_unlock(&GlobalMid_Lock); |
623 | } | 649 | } |
624 | 650 | ||
625 | cifs_small_buf_release(in_buf); | 651 | cifs_small_buf_release(buf); |
626 | 652 | ||
627 | rc = cifs_sync_mid_result(midQ, ses->server); | 653 | rc = cifs_sync_mid_result(midQ, ses->server); |
628 | if (rc != 0) { | 654 | if (rc != 0) { |
@@ -636,8 +662,9 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, | |||
636 | goto out; | 662 | goto out; |
637 | } | 663 | } |
638 | 664 | ||
639 | iov[0].iov_base = (char *)midQ->resp_buf; | 665 | buf = (char *)midQ->resp_buf; |
640 | iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4; | 666 | iov[0].iov_base = buf; |
667 | iov[0].iov_len = get_rfc1002_length(buf) + 4; | ||
641 | if (midQ->largeBuf) | 668 | if (midQ->largeBuf) |
642 | *pRespBufType = CIFS_LARGE_BUFFER; | 669 | *pRespBufType = CIFS_LARGE_BUFFER; |
643 | else | 670 | else |