Merge branch 'origin'
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / cifs / transport.c
1 /*
2 * fs/cifs/transport.c
3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include <linux/fs.h>
23 #include <linux/list.h>
24 #include <linux/wait.h>
25 #include <linux/net.h>
26 #include <linux/delay.h>
27 #include <asm/uaccess.h>
28 #include <asm/processor.h>
29 #include <linux/mempool.h>
30 #include "cifspdu.h"
31 #include "cifsglob.h"
32 #include "cifsproto.h"
33 #include "cifs_debug.h"
34
35 extern mempool_t *cifs_mid_poolp;
36 extern kmem_cache_t *cifs_oplock_cachep;
37
38 static struct mid_q_entry *
39 AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
40 {
41 struct mid_q_entry *temp;
42
43 if (ses == NULL) {
44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
45 return NULL;
46 }
47 if (ses->server == NULL) {
48 cERROR(1, ("Null TCP session in AllocMidQEntry"));
49 return NULL;
50 }
51
52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
53 SLAB_KERNEL | SLAB_NOFS);
54 if (temp == NULL)
55 return temp;
56 else {
57 memset(temp, 0, sizeof (struct mid_q_entry));
58 temp->mid = smb_buffer->Mid; /* always LE */
59 temp->pid = current->pid;
60 temp->command = smb_buffer->Command;
61 cFYI(1, ("For smb_command %d", temp->command));
62 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
63 /* when mid allocated can be before when sent */
64 temp->when_alloc = jiffies;
65 temp->ses = ses;
66 temp->tsk = current;
67 }
68
69 spin_lock(&GlobalMid_Lock);
70 list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
71 atomic_inc(&midCount);
72 temp->midState = MID_REQUEST_ALLOCATED;
73 spin_unlock(&GlobalMid_Lock);
74 return temp;
75 }
76
77 static void
78 DeleteMidQEntry(struct mid_q_entry *midEntry)
79 {
80 #ifdef CONFIG_CIFS_STATS2
81 unsigned long now;
82 #endif
83 spin_lock(&GlobalMid_Lock);
84 midEntry->midState = MID_FREE;
85 list_del(&midEntry->qhead);
86 atomic_dec(&midCount);
87 spin_unlock(&GlobalMid_Lock);
88 if(midEntry->largeBuf)
89 cifs_buf_release(midEntry->resp_buf);
90 else
91 cifs_small_buf_release(midEntry->resp_buf);
92 #ifdef CONFIG_CIFS_STATS2
93 now = jiffies;
94 /* commands taking longer than one second are indications that
95 something is wrong, unless it is quite a slow link or server */
96 if((now - midEntry->when_alloc) > HZ) {
97 if((cifsFYI & CIFS_TIMER) &&
98 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
99 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
100 midEntry->command, midEntry->mid);
101 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
102 now - midEntry->when_alloc,
103 now - midEntry->when_sent,
104 now - midEntry->when_received);
105 }
106 }
107 #endif
108 mempool_free(midEntry, cifs_mid_poolp);
109 }
110
111 struct oplock_q_entry *
112 AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
113 {
114 struct oplock_q_entry *temp;
115 if ((pinode== NULL) || (tcon == NULL)) {
116 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
117 return NULL;
118 }
119 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
120 SLAB_KERNEL);
121 if (temp == NULL)
122 return temp;
123 else {
124 temp->pinode = pinode;
125 temp->tcon = tcon;
126 temp->netfid = fid;
127 spin_lock(&GlobalMid_Lock);
128 list_add_tail(&temp->qhead, &GlobalOplock_Q);
129 spin_unlock(&GlobalMid_Lock);
130 }
131 return temp;
132
133 }
134
135 void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
136 {
137 spin_lock(&GlobalMid_Lock);
138 /* should we check if list empty first? */
139 list_del(&oplockEntry->qhead);
140 spin_unlock(&GlobalMid_Lock);
141 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
142 }
143
144 int
145 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
146 unsigned int smb_buf_length, struct sockaddr *sin)
147 {
148 int rc = 0;
149 int i = 0;
150 struct msghdr smb_msg;
151 struct kvec iov;
152 unsigned len = smb_buf_length + 4;
153
154 if(ssocket == NULL)
155 return -ENOTSOCK; /* BB eventually add reconnect code here */
156 iov.iov_base = smb_buffer;
157 iov.iov_len = len;
158
159 smb_msg.msg_name = sin;
160 smb_msg.msg_namelen = sizeof (struct sockaddr);
161 smb_msg.msg_control = NULL;
162 smb_msg.msg_controllen = 0;
163 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
164
165 /* smb header is converted in header_assemble. bcc and rest of SMB word
166 area, and byte area if necessary, is converted to littleendian in
167 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
168 Flags2 is converted in SendReceive */
169
170 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
171 cFYI(1, ("Sending smb of length %d", smb_buf_length));
172 dump_smb(smb_buffer, len);
173
174 while (len > 0) {
175 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
176 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
177 i++;
178 /* smaller timeout here than send2 since smaller size */
179 /* Although it may not be required, this also is smaller
180 oplock break time */
181 if(i > 12) {
182 cERROR(1,
183 ("sends on sock %p stuck for 7 seconds",
184 ssocket));
185 rc = -EAGAIN;
186 break;
187 }
188 msleep(1 << i);
189 continue;
190 }
191 if (rc < 0)
192 break;
193 else
194 i = 0; /* reset i after each successful send */
195 iov.iov_base += rc;
196 iov.iov_len -= rc;
197 len -= rc;
198 }
199
200 if (rc < 0) {
201 cERROR(1,("Error %d sending data on socket to server", rc));
202 } else {
203 rc = 0;
204 }
205
206 return rc;
207 }
208
209 static int
210 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
211 struct sockaddr *sin)
212 {
213 int rc = 0;
214 int i = 0;
215 struct msghdr smb_msg;
216 struct smb_hdr *smb_buffer = iov[0].iov_base;
217 unsigned int len = iov[0].iov_len;
218 unsigned int total_len;
219 int first_vec = 0;
220
221 if(ssocket == NULL)
222 return -ENOTSOCK; /* BB eventually add reconnect code here */
223
224 smb_msg.msg_name = sin;
225 smb_msg.msg_namelen = sizeof (struct sockaddr);
226 smb_msg.msg_control = NULL;
227 smb_msg.msg_controllen = 0;
228 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
229
230 /* smb header is converted in header_assemble. bcc and rest of SMB word
231 area, and byte area if necessary, is converted to littleendian in
232 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
233 Flags2 is converted in SendReceive */
234
235
236 total_len = 0;
237 for (i = 0; i < n_vec; i++)
238 total_len += iov[i].iov_len;
239
240 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
241 cFYI(1, ("Sending smb: total_len %d", total_len));
242 dump_smb(smb_buffer, len);
243
244 while (total_len) {
245 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
246 n_vec - first_vec, total_len);
247 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
248 i++;
249 if(i >= 14) {
250 cERROR(1,
251 ("sends on sock %p stuck for 15 seconds",
252 ssocket));
253 rc = -EAGAIN;
254 break;
255 }
256 msleep(1 << i);
257 continue;
258 }
259 if (rc < 0)
260 break;
261
262 if (rc >= total_len) {
263 WARN_ON(rc > total_len);
264 break;
265 }
266 if(rc == 0) {
267 /* should never happen, letting socket clear before
268 retrying is our only obvious option here */
269 cERROR(1,("tcp sent no data"));
270 msleep(500);
271 continue;
272 }
273 total_len -= rc;
274 /* the line below resets i */
275 for (i = first_vec; i < n_vec; i++) {
276 if (iov[i].iov_len) {
277 if (rc > iov[i].iov_len) {
278 rc -= iov[i].iov_len;
279 iov[i].iov_len = 0;
280 } else {
281 iov[i].iov_base += rc;
282 iov[i].iov_len -= rc;
283 first_vec = i;
284 break;
285 }
286 }
287 }
288 i = 0; /* in case we get ENOSPC on the next send */
289 }
290
291 if (rc < 0) {
292 cERROR(1,("Error %d sending data on socket to server", rc));
293 } else
294 rc = 0;
295
296 return rc;
297 }
298
299 int
300 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
302 const int long_op)
303 {
304 int rc = 0;
305 unsigned int receive_len;
306 unsigned long timeout;
307 struct mid_q_entry *midQ;
308 struct smb_hdr *in_buf = iov[0].iov_base;
309
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
311
312 if (ses == NULL) {
313 cERROR(1,("Null smb session"));
314 return -EIO;
315 }
316 if(ses->server == NULL) {
317 cERROR(1,("Null tcp session"));
318 return -EIO;
319 }
320
321 if(ses->server->tcpStatus == CifsExiting)
322 return -ENOENT;
323
324 /* Ensure that we do not send more than 50 overlapping requests
325 to the same server. We may make this configurable later or
326 use ses->maxReq */
327 if(long_op == -1) {
328 /* oplock breaks must not be held up */
329 atomic_inc(&ses->server->inFlight);
330 } else {
331 spin_lock(&GlobalMid_Lock);
332 while(1) {
333 if(atomic_read(&ses->server->inFlight) >=
334 cifs_max_pending){
335 spin_unlock(&GlobalMid_Lock);
336 #ifdef CONFIG_CIFS_STATS2
337 atomic_inc(&ses->server->num_waiters);
338 #endif
339 wait_event(ses->server->request_q,
340 atomic_read(&ses->server->inFlight)
341 < cifs_max_pending);
342 #ifdef CONFIG_CIFS_STATS2
343 atomic_dec(&ses->server->num_waiters);
344 #endif
345 spin_lock(&GlobalMid_Lock);
346 } else {
347 if(ses->server->tcpStatus == CifsExiting) {
348 spin_unlock(&GlobalMid_Lock);
349 return -ENOENT;
350 }
351
352 /* can not count locking commands against total since
353 they are allowed to block on server */
354
355 if(long_op < 3) {
356 /* update # of requests on the wire to server */
357 atomic_inc(&ses->server->inFlight);
358 }
359 spin_unlock(&GlobalMid_Lock);
360 break;
361 }
362 }
363 }
364 /* make sure that we sign in the same order that we send on this socket
365 and avoid races inside tcp sendmsg code that could cause corruption
366 of smb data */
367
368 down(&ses->server->tcpSem);
369
370 if (ses->server->tcpStatus == CifsExiting) {
371 rc = -ENOENT;
372 goto out_unlock2;
373 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
374 cFYI(1,("tcp session dead - return to caller to retry"));
375 rc = -EAGAIN;
376 goto out_unlock2;
377 } else if (ses->status != CifsGood) {
378 /* check if SMB session is bad because we are setting it up */
379 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
380 (in_buf->Command != SMB_COM_NEGOTIATE)) {
381 rc = -EAGAIN;
382 goto out_unlock2;
383 } /* else ok - we are setting up session */
384 }
385 midQ = AllocMidQEntry(in_buf, ses);
386 if (midQ == NULL) {
387 up(&ses->server->tcpSem);
388 /* If not lock req, update # of requests on wire to server */
389 if(long_op < 3) {
390 atomic_dec(&ses->server->inFlight);
391 wake_up(&ses->server->request_q);
392 }
393 return -ENOMEM;
394 }
395
396 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
397
398 midQ->midState = MID_REQUEST_SUBMITTED;
399 #ifdef CONFIG_CIFS_STATS2
400 atomic_inc(&ses->server->inSend);
401 #endif
402 rc = smb_send2(ses->server->ssocket, iov, n_vec,
403 (struct sockaddr *) &(ses->server->addr.sockAddr));
404 #ifdef CONFIG_CIFS_STATS2
405 atomic_dec(&ses->server->inSend);
406 midQ->when_sent = jiffies;
407 #endif
408 if(rc < 0) {
409 DeleteMidQEntry(midQ);
410 up(&ses->server->tcpSem);
411 /* If not lock req, update # of requests on wire to server */
412 if(long_op < 3) {
413 atomic_dec(&ses->server->inFlight);
414 wake_up(&ses->server->request_q);
415 }
416 return rc;
417 } else
418 up(&ses->server->tcpSem);
419 if (long_op == -1)
420 goto cifs_no_response_exit2;
421 else if (long_op == 2) /* writes past end of file can take loong time */
422 timeout = 180 * HZ;
423 else if (long_op == 1)
424 timeout = 45 * HZ; /* should be greater than
425 servers oplock break timeout (about 43 seconds) */
426 else if (long_op > 2) {
427 timeout = MAX_SCHEDULE_TIMEOUT;
428 } else
429 timeout = 15 * HZ;
430 /* wait for 15 seconds or until woken up due to response arriving or
431 due to last connection to this server being unmounted */
432 if (signal_pending(current)) {
433 /* if signal pending do not hold up user for full smb timeout
434 but we still give response a change to complete */
435 timeout = 2 * HZ;
436 }
437
438 /* No user interrupts in wait - wreaks havoc with performance */
439 if(timeout != MAX_SCHEDULE_TIMEOUT) {
440 timeout += jiffies;
441 wait_event(ses->server->response_q,
442 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
443 time_after(jiffies, timeout) ||
444 ((ses->server->tcpStatus != CifsGood) &&
445 (ses->server->tcpStatus != CifsNew)));
446 } else {
447 wait_event(ses->server->response_q,
448 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
449 ((ses->server->tcpStatus != CifsGood) &&
450 (ses->server->tcpStatus != CifsNew)));
451 }
452
453 spin_lock(&GlobalMid_Lock);
454 if (midQ->resp_buf) {
455 spin_unlock(&GlobalMid_Lock);
456 receive_len = midQ->resp_buf->smb_buf_length;
457 } else {
458 cERROR(1,("No response to cmd %d mid %d",
459 midQ->command, midQ->mid));
460 if(midQ->midState == MID_REQUEST_SUBMITTED) {
461 if(ses->server->tcpStatus == CifsExiting)
462 rc = -EHOSTDOWN;
463 else {
464 ses->server->tcpStatus = CifsNeedReconnect;
465 midQ->midState = MID_RETRY_NEEDED;
466 }
467 }
468
469 if (rc != -EHOSTDOWN) {
470 if(midQ->midState == MID_RETRY_NEEDED) {
471 rc = -EAGAIN;
472 cFYI(1,("marking request for retry"));
473 } else {
474 rc = -EIO;
475 }
476 }
477 spin_unlock(&GlobalMid_Lock);
478 DeleteMidQEntry(midQ);
479 /* If not lock req, update # of requests on wire to server */
480 if(long_op < 3) {
481 atomic_dec(&ses->server->inFlight);
482 wake_up(&ses->server->request_q);
483 }
484 return rc;
485 }
486
487 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
488 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
489 receive_len, xid));
490 rc = -EIO;
491 } else { /* rcvd frame is ok */
492 if (midQ->resp_buf &&
493 (midQ->midState == MID_RESPONSE_RECEIVED)) {
494
495 iov[0].iov_base = (char *)midQ->resp_buf;
496 if(midQ->largeBuf)
497 *pRespBufType = CIFS_LARGE_BUFFER;
498 else
499 *pRespBufType = CIFS_SMALL_BUFFER;
500 iov[0].iov_len = receive_len + 4;
501
502 dump_smb(midQ->resp_buf, 80);
503 /* convert the length into a more usable form */
504 if((receive_len > 24) &&
505 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
506 SECMODE_SIGN_ENABLED))) {
507 rc = cifs_verify_signature(midQ->resp_buf,
508 ses->server->mac_signing_key,
509 midQ->sequence_number+1);
510 if(rc) {
511 cERROR(1,("Unexpected SMB signature"));
512 /* BB FIXME add code to kill session */
513 }
514 }
515
516 /* BB special case reconnect tid and uid here? */
517 /* BB special case Errbadpassword and pwdexpired here */
518 rc = map_smb_to_linux_error(midQ->resp_buf);
519
520 /* convert ByteCount if necessary */
521 if (receive_len >=
522 sizeof (struct smb_hdr) -
523 4 /* do not count RFC1001 header */ +
524 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
525 BCC(midQ->resp_buf) =
526 le16_to_cpu(BCC_LE(midQ->resp_buf));
527 midQ->resp_buf = NULL; /* mark it so will not be freed
528 by DeleteMidQEntry */
529 } else {
530 rc = -EIO;
531 cFYI(1,("Bad MID state?"));
532 }
533 }
534 cifs_no_response_exit2:
535 DeleteMidQEntry(midQ);
536
537 if(long_op < 3) {
538 atomic_dec(&ses->server->inFlight);
539 wake_up(&ses->server->request_q);
540 }
541
542 return rc;
543
544 out_unlock2:
545 up(&ses->server->tcpSem);
546 /* If not lock req, update # of requests on wire to server */
547 if(long_op < 3) {
548 atomic_dec(&ses->server->inFlight);
549 wake_up(&ses->server->request_q);
550 }
551
552 return rc;
553 }
554
555 int
556 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
557 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
558 int *pbytes_returned, const int long_op)
559 {
560 int rc = 0;
561 unsigned int receive_len;
562 unsigned long timeout;
563 struct mid_q_entry *midQ;
564
565 if (ses == NULL) {
566 cERROR(1,("Null smb session"));
567 return -EIO;
568 }
569 if(ses->server == NULL) {
570 cERROR(1,("Null tcp session"));
571 return -EIO;
572 }
573
574 if(ses->server->tcpStatus == CifsExiting)
575 return -ENOENT;
576
577 /* Ensure that we do not send more than 50 overlapping requests
578 to the same server. We may make this configurable later or
579 use ses->maxReq */
580 if(long_op == -1) {
581 /* oplock breaks must not be held up */
582 atomic_inc(&ses->server->inFlight);
583 } else {
584 spin_lock(&GlobalMid_Lock);
585 while(1) {
586 if(atomic_read(&ses->server->inFlight) >=
587 cifs_max_pending){
588 spin_unlock(&GlobalMid_Lock);
589 #ifdef CONFIG_CIFS_STATS2
590 atomic_inc(&ses->server->num_waiters);
591 #endif
592 wait_event(ses->server->request_q,
593 atomic_read(&ses->server->inFlight)
594 < cifs_max_pending);
595 #ifdef CONFIG_CIFS_STATS2
596 atomic_dec(&ses->server->num_waiters);
597 #endif
598 spin_lock(&GlobalMid_Lock);
599 } else {
600 if(ses->server->tcpStatus == CifsExiting) {
601 spin_unlock(&GlobalMid_Lock);
602 return -ENOENT;
603 }
604
605 /* can not count locking commands against total since
606 they are allowed to block on server */
607
608 if(long_op < 3) {
609 /* update # of requests on the wire to server */
610 atomic_inc(&ses->server->inFlight);
611 }
612 spin_unlock(&GlobalMid_Lock);
613 break;
614 }
615 }
616 }
617 /* make sure that we sign in the same order that we send on this socket
618 and avoid races inside tcp sendmsg code that could cause corruption
619 of smb data */
620
621 down(&ses->server->tcpSem);
622
623 if (ses->server->tcpStatus == CifsExiting) {
624 rc = -ENOENT;
625 goto out_unlock;
626 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
627 cFYI(1,("tcp session dead - return to caller to retry"));
628 rc = -EAGAIN;
629 goto out_unlock;
630 } else if (ses->status != CifsGood) {
631 /* check if SMB session is bad because we are setting it up */
632 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
633 (in_buf->Command != SMB_COM_NEGOTIATE)) {
634 rc = -EAGAIN;
635 goto out_unlock;
636 } /* else ok - we are setting up session */
637 }
638 midQ = AllocMidQEntry(in_buf, ses);
639 if (midQ == NULL) {
640 up(&ses->server->tcpSem);
641 /* If not lock req, update # of requests on wire to server */
642 if(long_op < 3) {
643 atomic_dec(&ses->server->inFlight);
644 wake_up(&ses->server->request_q);
645 }
646 return -ENOMEM;
647 }
648
649 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
650 up(&ses->server->tcpSem);
651 cERROR(1,
652 ("Illegal length, greater than maximum frame, %d ",
653 in_buf->smb_buf_length));
654 DeleteMidQEntry(midQ);
655 /* If not lock req, update # of requests on wire to server */
656 if(long_op < 3) {
657 atomic_dec(&ses->server->inFlight);
658 wake_up(&ses->server->request_q);
659 }
660 return -EIO;
661 }
662
663 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
664
665 midQ->midState = MID_REQUEST_SUBMITTED;
666 #ifdef CONFIG_CIFS_STATS2
667 atomic_inc(&ses->server->inSend);
668 #endif
669 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
670 (struct sockaddr *) &(ses->server->addr.sockAddr));
671 #ifdef CONFIG_CIFS_STATS2
672 atomic_dec(&ses->server->inSend);
673 midQ->when_sent = jiffies;
674 #endif
675 if(rc < 0) {
676 DeleteMidQEntry(midQ);
677 up(&ses->server->tcpSem);
678 /* If not lock req, update # of requests on wire to server */
679 if(long_op < 3) {
680 atomic_dec(&ses->server->inFlight);
681 wake_up(&ses->server->request_q);
682 }
683 return rc;
684 } else
685 up(&ses->server->tcpSem);
686 if (long_op == -1)
687 goto cifs_no_response_exit;
688 else if (long_op == 2) /* writes past end of file can take loong time */
689 timeout = 180 * HZ;
690 else if (long_op == 1)
691 timeout = 45 * HZ; /* should be greater than
692 servers oplock break timeout (about 43 seconds) */
693 else if (long_op > 2) {
694 timeout = MAX_SCHEDULE_TIMEOUT;
695 } else
696 timeout = 15 * HZ;
697 /* wait for 15 seconds or until woken up due to response arriving or
698 due to last connection to this server being unmounted */
699 if (signal_pending(current)) {
700 /* if signal pending do not hold up user for full smb timeout
701 but we still give response a change to complete */
702 timeout = 2 * HZ;
703 }
704
705 /* No user interrupts in wait - wreaks havoc with performance */
706 if(timeout != MAX_SCHEDULE_TIMEOUT) {
707 timeout += jiffies;
708 wait_event(ses->server->response_q,
709 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
710 time_after(jiffies, timeout) ||
711 ((ses->server->tcpStatus != CifsGood) &&
712 (ses->server->tcpStatus != CifsNew)));
713 } else {
714 wait_event(ses->server->response_q,
715 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
716 ((ses->server->tcpStatus != CifsGood) &&
717 (ses->server->tcpStatus != CifsNew)));
718 }
719
720 spin_lock(&GlobalMid_Lock);
721 if (midQ->resp_buf) {
722 spin_unlock(&GlobalMid_Lock);
723 receive_len = midQ->resp_buf->smb_buf_length;
724 } else {
725 cERROR(1,("No response for cmd %d mid %d",
726 midQ->command, midQ->mid));
727 if(midQ->midState == MID_REQUEST_SUBMITTED) {
728 if(ses->server->tcpStatus == CifsExiting)
729 rc = -EHOSTDOWN;
730 else {
731 ses->server->tcpStatus = CifsNeedReconnect;
732 midQ->midState = MID_RETRY_NEEDED;
733 }
734 }
735
736 if (rc != -EHOSTDOWN) {
737 if(midQ->midState == MID_RETRY_NEEDED) {
738 rc = -EAGAIN;
739 cFYI(1,("marking request for retry"));
740 } else {
741 rc = -EIO;
742 }
743 }
744 spin_unlock(&GlobalMid_Lock);
745 DeleteMidQEntry(midQ);
746 /* If not lock req, update # of requests on wire to server */
747 if(long_op < 3) {
748 atomic_dec(&ses->server->inFlight);
749 wake_up(&ses->server->request_q);
750 }
751 return rc;
752 }
753
754 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
755 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
756 receive_len, xid));
757 rc = -EIO;
758 } else { /* rcvd frame is ok */
759
760 if (midQ->resp_buf && out_buf
761 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
762 out_buf->smb_buf_length = receive_len;
763 memcpy((char *)out_buf + 4,
764 (char *)midQ->resp_buf + 4,
765 receive_len);
766
767 dump_smb(out_buf, 92);
768 /* convert the length into a more usable form */
769 if((receive_len > 24) &&
770 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
771 SECMODE_SIGN_ENABLED))) {
772 rc = cifs_verify_signature(out_buf,
773 ses->server->mac_signing_key,
774 midQ->sequence_number+1);
775 if(rc) {
776 cERROR(1,("Unexpected SMB signature"));
777 /* BB FIXME add code to kill session */
778 }
779 }
780
781 *pbytes_returned = out_buf->smb_buf_length;
782
783 /* BB special case reconnect tid and uid here? */
784 rc = map_smb_to_linux_error(out_buf);
785
786 /* convert ByteCount if necessary */
787 if (receive_len >=
788 sizeof (struct smb_hdr) -
789 4 /* do not count RFC1001 header */ +
790 (2 * out_buf->WordCount) + 2 /* bcc */ )
791 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
792 } else {
793 rc = -EIO;
794 cERROR(1,("Bad MID state?"));
795 }
796 }
797 cifs_no_response_exit:
798 DeleteMidQEntry(midQ);
799
800 if(long_op < 3) {
801 atomic_dec(&ses->server->inFlight);
802 wake_up(&ses->server->request_q);
803 }
804
805 return rc;
806
807 out_unlock:
808 up(&ses->server->tcpSem);
809 /* If not lock req, update # of requests on wire to server */
810 if(long_op < 3) {
811 atomic_dec(&ses->server->inFlight);
812 wake_up(&ses->server->request_q);
813 }
814
815 return rc;
816 }