diff options
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r-- | fs/cifs/transport.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index bf0e6d8e382a..ba4d66644ebf 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 |
@@ -312,6 +319,16 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
312 | i = 0; /* in case we get ENOSPC on the next send */ | 319 | i = 0; /* in case we get ENOSPC on the next send */ |
313 | } | 320 | } |
314 | 321 | ||
322 | if ((total_len > 0) && (total_len != smb_buf_length + 4)) { | ||
323 | cFYI(1, ("partial send (%d remaining), terminating session", | ||
324 | total_len)); | ||
325 | /* If we have only sent part of an SMB then the next SMB | ||
326 | could be taken as the remainder of this one. We need | ||
327 | to kill the socket so the server throws away the partial | ||
328 | SMB */ | ||
329 | server->tcpStatus = CifsNeedReconnect; | ||
330 | } | ||
331 | |||
315 | if (rc < 0) { | 332 | if (rc < 0) { |
316 | cERROR(1, ("Error %d sending data on socket to server", rc)); | 333 | cERROR(1, ("Error %d sending data on socket to server", rc)); |
317 | } else | 334 | } else |
@@ -518,8 +535,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
518 | #ifdef CONFIG_CIFS_STATS2 | 535 | #ifdef CONFIG_CIFS_STATS2 |
519 | atomic_inc(&ses->server->inSend); | 536 | atomic_inc(&ses->server->inSend); |
520 | #endif | 537 | #endif |
521 | rc = smb_send2(ses->server->ssocket, iov, n_vec, | 538 | rc = smb_send2(ses->server, iov, n_vec, |
522 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 539 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
540 | ses->server->noblocksnd); | ||
523 | #ifdef CONFIG_CIFS_STATS2 | 541 | #ifdef CONFIG_CIFS_STATS2 |
524 | atomic_dec(&ses->server->inSend); | 542 | atomic_dec(&ses->server->inSend); |
525 | midQ->when_sent = jiffies; | 543 | midQ->when_sent = jiffies; |
@@ -711,7 +729,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
711 | atomic_inc(&ses->server->inSend); | 729 | atomic_inc(&ses->server->inSend); |
712 | #endif | 730 | #endif |
713 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 731 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
714 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 732 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
733 | ses->server->noblocksnd); | ||
715 | #ifdef CONFIG_CIFS_STATS2 | 734 | #ifdef CONFIG_CIFS_STATS2 |
716 | atomic_dec(&ses->server->inSend); | 735 | atomic_dec(&ses->server->inSend); |
717 | midQ->when_sent = jiffies; | 736 | midQ->when_sent = jiffies; |
@@ -851,7 +870,8 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, | |||
851 | return rc; | 870 | return rc; |
852 | } | 871 | } |
853 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 872 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
854 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 873 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
874 | ses->server->noblocksnd); | ||
855 | up(&ses->server->tcpSem); | 875 | up(&ses->server->tcpSem); |
856 | return rc; | 876 | return rc; |
857 | } | 877 | } |
@@ -941,7 +961,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
941 | atomic_inc(&ses->server->inSend); | 961 | atomic_inc(&ses->server->inSend); |
942 | #endif | 962 | #endif |
943 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 963 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
944 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 964 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
965 | ses->server->noblocksnd); | ||
945 | #ifdef CONFIG_CIFS_STATS2 | 966 | #ifdef CONFIG_CIFS_STATS2 |
946 | atomic_dec(&ses->server->inSend); | 967 | atomic_dec(&ses->server->inSend); |
947 | midQ->when_sent = jiffies; | 968 | midQ->when_sent = jiffies; |