aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c95
1 files changed, 55 insertions, 40 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 9e8e85a8d186..38b3b2463ae4 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -147,16 +147,19 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
147 Flags2 is converted in SendReceive */ 147 Flags2 is converted in SendReceive */
148 148
149 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 149 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
150 cFYI(1, ("Sending smb of length %d ", smb_buf_length)); 150 cFYI(1, ("Sending smb of length %d", smb_buf_length));
151 dump_smb(smb_buffer, len); 151 dump_smb(smb_buffer, len);
152 152
153 while (len > 0) { 153 while (len > 0) {
154 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len); 154 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
155 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 155 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
156 i++; 156 i++;
157 if(i > 60) { 157 /* smaller timeout here than send2 since smaller size */
158 /* Although it may not be required, this also is smaller
159 oplock break time */
160 if(i > 30) {
158 cERROR(1, 161 cERROR(1,
159 ("sends on sock %p stuck for 30 seconds", 162 ("sends on sock %p stuck for 15 seconds",
160 ssocket)); 163 ssocket));
161 rc = -EAGAIN; 164 rc = -EAGAIN;
162 break; 165 break;
@@ -172,7 +175,7 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
172 } 175 }
173 176
174 if (rc < 0) { 177 if (rc < 0) {
175 cERROR(1,("Error %d sending data on socket to server.", rc)); 178 cERROR(1,("Error %d sending data on socket to server", rc));
176 } else { 179 } else {
177 rc = 0; 180 rc = 0;
178 } 181 }
@@ -182,22 +185,20 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
182 185
183#ifdef CONFIG_CIFS_EXPERIMENTAL 186#ifdef CONFIG_CIFS_EXPERIMENTAL
184static int 187static int
185smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer, 188smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
186 unsigned int smb_hdr_length, const char * data, unsigned int datalen, 189 struct sockaddr *sin)
187 struct sockaddr *sin)
188{ 190{
189 int rc = 0; 191 int rc = 0;
190 int i = 0; 192 int i = 0;
191 struct msghdr smb_msg; 193 struct msghdr smb_msg;
192 struct kvec iov[2]; 194 struct smb_hdr *smb_buffer = iov[0].iov_base;
193 unsigned len = smb_hdr_length + 4; 195 unsigned int len = iov[0].iov_len;
196 unsigned int total_len;
197 int first_vec = 0;
194 198
195 if(ssocket == NULL) 199 if(ssocket == NULL)
196 return -ENOTSOCK; /* BB eventually add reconnect code here */ 200 return -ENOTSOCK; /* BB eventually add reconnect code here */
197 iov[0].iov_base = smb_buffer; 201
198 iov[0].iov_len = len;
199 iov[1].iov_base = data;
200 iov[1].iov_len = datalen;
201 smb_msg.msg_name = sin; 202 smb_msg.msg_name = sin;
202 smb_msg.msg_namelen = sizeof (struct sockaddr); 203 smb_msg.msg_namelen = sizeof (struct sockaddr);
203 smb_msg.msg_control = NULL; 204 smb_msg.msg_control = NULL;
@@ -209,18 +210,23 @@ smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
209 cifssmb.c and RFC1001 len is converted to bigendian in smb_send 210 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
210 Flags2 is converted in SendReceive */ 211 Flags2 is converted in SendReceive */
211 212
213
214 total_len = 0;
215 for (i = 0; i < n_vec; i++)
216 total_len += iov[i].iov_len;
217
212 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); 218 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
213 cFYI(1, ("Sending smb: hdrlen %d datalen %d", 219 cFYI(1, ("Sending smb: total_len %d", total_len));
214 smb_hdr_length,datalen));
215 dump_smb(smb_buffer, len); 220 dump_smb(smb_buffer, len);
216 221
217 while (len + datalen > 0) { 222 while (total_len) {
218 rc = kernel_sendmsg(ssocket, &smb_msg, iov, 2, len); 223 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
224 n_vec - first_vec, total_len);
219 if ((rc == -ENOSPC) || (rc == -EAGAIN)) { 225 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
220 i++; 226 i++;
221 if(i > 60) { 227 if(i > 40) {
222 cERROR(1, 228 cERROR(1,
223 ("sends on sock %p stuck for 30 seconds", 229 ("sends on sock %p stuck for 20 seconds",
224 ssocket)); 230 ssocket));
225 rc = -EAGAIN; 231 rc = -EAGAIN;
226 break; 232 break;
@@ -230,43 +236,52 @@ smb_send2(struct socket *ssocket, struct smb_hdr *smb_buffer,
230 } 236 }
231 if (rc < 0) 237 if (rc < 0)
232 break; 238 break;
233 if(iov[0].iov_len > 0) { 239
234 if(rc >= len) { 240 if (rc >= total_len) {
235 iov[0].iov_len = 0; 241 WARN_ON(rc > total_len);
236 rc -= len; 242 break;
237 len = 0; 243 }
238 } else { /* some of hdr was not sent */ 244 if(rc == 0) {
239 len -= rc; 245 /* should never happen, letting socket clear before
240 iov[0].iov_len -= rc; 246 retrying is our only obvious option here */
241 iov[0].iov_base += rc; 247 cERROR(1,("tcp sent no data");
242 continue; 248 msleep(500);
243 } 249 continue;
244 } 250 }
245 if((iov[0].iov_len == 0) && (rc > 0)){ 251 total_len -= rc;
246 iov[1].iov_base += rc; 252 for (i = first_vec; i < n_vec; i++) {
247 iov[1].iov_len -= rc; 253 if (iov[i].iov_len) {
248 datalen -= rc; 254 if (rc > iov[i].iov_len) {
255 rc -= iov[i].iov_len;
256 iov[i].iov_len = 0;
257 } else {
258 iov[i].iov_base += rc;
259 iov[i].iov_len -= rc;
260 first_vec = i;
261 break;
262 }
263 }
249 } 264 }
250 } 265 }
251 266
252 if (rc < 0) { 267 if (rc < 0) {
253 cERROR(1,("Error %d sending data on socket to server.", rc)); 268 cERROR(1,("Error %d sending data on socket to server", rc));
254 } else { 269 } else
255 rc = 0; 270 rc = 0;
256 }
257 271
258 return rc; 272 return rc;
259} 273}
260 274
261int 275int
262SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 276SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
263 struct smb_hdr *in_buf, int hdrlen, const char * data, 277 struct kvec *iov, int n_vec, int *pbytes_returned,
264 int datalen, int *pbytes_returned, const int long_op) 278 const int long_op)
265{ 279{
266 int rc = 0; 280 int rc = 0;
267 unsigned int receive_len; 281 unsigned int receive_len;
268 unsigned long timeout; 282 unsigned long timeout;
269 struct mid_q_entry *midQ; 283 struct mid_q_entry *midQ;
284 struct smb_hdr *in_buf = iov[0].iov_base;
270 285
271 if (ses == NULL) { 286 if (ses == NULL) {
272 cERROR(1,("Null smb session")); 287 cERROR(1,("Null smb session"));
@@ -364,7 +379,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
364/* rc = cifs_sign_smb2(in_buf, data, ses->server, &midQ->sequence_number); */ 379/* rc = cifs_sign_smb2(in_buf, data, ses->server, &midQ->sequence_number); */
365 380
366 midQ->midState = MID_REQUEST_SUBMITTED; 381 midQ->midState = MID_REQUEST_SUBMITTED;
367 rc = smb_send2(ses->server->ssocket, in_buf, hdrlen, data, datalen, 382 rc = smb_send2(ses->server->ssocket, iov, n_vec,
368 (struct sockaddr *) &(ses->server->addr.sockAddr)); 383 (struct sockaddr *) &(ses->server->addr.sockAddr));
369 if(rc < 0) { 384 if(rc < 0) {
370 DeleteMidQEntry(midQ); 385 DeleteMidQEntry(midQ);