diff options
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r-- | fs/cifs/transport.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index bf0e6d8e382a..ff8243a8fe3e 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
@@ -161,7 +161,7 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) | |||
161 | 161 | ||
162 | int | 162 | int |
163 | smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | 163 | smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, |
164 | unsigned int smb_buf_length, struct sockaddr *sin) | 164 | unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd) |
165 | { | 165 | { |
166 | int rc = 0; | 166 | int rc = 0; |
167 | int i = 0; | 167 | int i = 0; |
@@ -178,7 +178,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
178 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 178 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
179 | smb_msg.msg_control = NULL; | 179 | smb_msg.msg_control = NULL; |
180 | smb_msg.msg_controllen = 0; | 180 | smb_msg.msg_controllen = 0; |
181 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 181 | if (noblocksnd) |
182 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; | ||
183 | else | ||
184 | smb_msg.msg_flags = MSG_NOSIGNAL; | ||
182 | 185 | ||
183 | /* smb header is converted in header_assemble. bcc and rest of SMB word | 186 | /* smb header is converted in header_assemble. bcc and rest of SMB word |
184 | area, and byte area if necessary, is converted to littleendian in | 187 | area, and byte area if necessary, is converted to littleendian in |
@@ -229,8 +232,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
229 | } | 232 | } |
230 | 233 | ||
231 | static int | 234 | static int |
232 | smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | 235 | smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, |
233 | struct sockaddr *sin) | 236 | struct sockaddr *sin, bool noblocksnd) |
234 | { | 237 | { |
235 | int rc = 0; | 238 | int rc = 0; |
236 | int i = 0; | 239 | int i = 0; |
@@ -240,6 +243,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
240 | unsigned int total_len; | 243 | unsigned int total_len; |
241 | int first_vec = 0; | 244 | int first_vec = 0; |
242 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; | 245 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; |
246 | struct socket *ssocket = server->ssocket; | ||
243 | 247 | ||
244 | if (ssocket == NULL) | 248 | if (ssocket == NULL) |
245 | return -ENOTSOCK; /* BB eventually add reconnect code here */ | 249 | return -ENOTSOCK; /* BB eventually add reconnect code here */ |
@@ -248,7 +252,10 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
248 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 252 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
249 | smb_msg.msg_control = NULL; | 253 | smb_msg.msg_control = NULL; |
250 | smb_msg.msg_controllen = 0; | 254 | smb_msg.msg_controllen = 0; |
251 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 255 | if (noblocksnd) |
256 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; | ||
257 | else | ||
258 | smb_msg.msg_flags = MSG_NOSIGNAL; | ||
252 | 259 | ||
253 | /* smb header is converted in header_assemble. bcc and rest of SMB word | 260 | /* smb header is converted in header_assemble. bcc and rest of SMB word |
254 | area, and byte area if necessary, is converted to littleendian in | 261 | area, and byte area if necessary, is converted to littleendian in |
@@ -283,8 +290,11 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
283 | if (rc < 0) | 290 | if (rc < 0) |
284 | break; | 291 | break; |
285 | 292 | ||
286 | if (rc >= total_len) { | 293 | if (rc == total_len) { |
287 | WARN_ON(rc > total_len); | 294 | total_len = 0; |
295 | break; | ||
296 | } else if (rc > total_len) { | ||
297 | cERROR(1, ("sent %d requested %d", rc, total_len)); | ||
288 | break; | 298 | break; |
289 | } | 299 | } |
290 | if (rc == 0) { | 300 | if (rc == 0) { |
@@ -312,6 +322,16 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
312 | i = 0; /* in case we get ENOSPC on the next send */ | 322 | i = 0; /* in case we get ENOSPC on the next send */ |
313 | } | 323 | } |
314 | 324 | ||
325 | if ((total_len > 0) && (total_len != smb_buf_length + 4)) { | ||
326 | cFYI(1, ("partial send (%d remaining), terminating session", | ||
327 | total_len)); | ||
328 | /* If we have only sent part of an SMB then the next SMB | ||
329 | could be taken as the remainder of this one. We need | ||
330 | to kill the socket so the server throws away the partial | ||
331 | SMB */ | ||
332 | server->tcpStatus = CifsNeedReconnect; | ||
333 | } | ||
334 | |||
315 | if (rc < 0) { | 335 | if (rc < 0) { |
316 | cERROR(1, ("Error %d sending data on socket to server", rc)); | 336 | cERROR(1, ("Error %d sending data on socket to server", rc)); |
317 | } else | 337 | } else |
@@ -518,8 +538,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
518 | #ifdef CONFIG_CIFS_STATS2 | 538 | #ifdef CONFIG_CIFS_STATS2 |
519 | atomic_inc(&ses->server->inSend); | 539 | atomic_inc(&ses->server->inSend); |
520 | #endif | 540 | #endif |
521 | rc = smb_send2(ses->server->ssocket, iov, n_vec, | 541 | rc = smb_send2(ses->server, iov, n_vec, |
522 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 542 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
543 | ses->server->noblocksnd); | ||
523 | #ifdef CONFIG_CIFS_STATS2 | 544 | #ifdef CONFIG_CIFS_STATS2 |
524 | atomic_dec(&ses->server->inSend); | 545 | atomic_dec(&ses->server->inSend); |
525 | midQ->when_sent = jiffies; | 546 | midQ->when_sent = jiffies; |
@@ -711,7 +732,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
711 | atomic_inc(&ses->server->inSend); | 732 | atomic_inc(&ses->server->inSend); |
712 | #endif | 733 | #endif |
713 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 734 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
714 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 735 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
736 | ses->server->noblocksnd); | ||
715 | #ifdef CONFIG_CIFS_STATS2 | 737 | #ifdef CONFIG_CIFS_STATS2 |
716 | atomic_dec(&ses->server->inSend); | 738 | atomic_dec(&ses->server->inSend); |
717 | midQ->when_sent = jiffies; | 739 | midQ->when_sent = jiffies; |
@@ -851,7 +873,8 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, | |||
851 | return rc; | 873 | return rc; |
852 | } | 874 | } |
853 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 875 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
854 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 876 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
877 | ses->server->noblocksnd); | ||
855 | up(&ses->server->tcpSem); | 878 | up(&ses->server->tcpSem); |
856 | return rc; | 879 | return rc; |
857 | } | 880 | } |
@@ -941,7 +964,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
941 | atomic_inc(&ses->server->inSend); | 964 | atomic_inc(&ses->server->inSend); |
942 | #endif | 965 | #endif |
943 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 966 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
944 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 967 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
968 | ses->server->noblocksnd); | ||
945 | #ifdef CONFIG_CIFS_STATS2 | 969 | #ifdef CONFIG_CIFS_STATS2 |
946 | atomic_dec(&ses->server->inSend); | 970 | atomic_dec(&ses->server->inSend); |
947 | midQ->when_sent = jiffies; | 971 | midQ->when_sent = jiffies; |