Merge commit master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6 of HEAD
[linux-2.6/zen-sources.git] / fs / cifs / transport.c
blob17ba329e2b3de5cbf02b973cf0b3a04515736b43
1 /*
2 * fs/cifs/transport.c
4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
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.
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.
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
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"
35 extern mempool_t *cifs_mid_poolp;
36 extern kmem_cache_t *cifs_oplock_cachep;
38 static struct mid_q_entry *
39 AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41 struct mid_q_entry *temp;
43 if (ses == NULL) {
44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
45 return NULL;
47 if (ses->server == NULL) {
48 cERROR(1, ("Null TCP session in AllocMidQEntry"));
49 return NULL;
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;
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;
77 static void
78 DeleteMidQEntry(struct mid_q_entry *midEntry)
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);
107 #endif
108 mempool_free(midEntry, cifs_mid_poolp);
111 struct oplock_q_entry *
112 AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
114 struct oplock_q_entry *temp;
115 if ((pinode== NULL) || (tcon == NULL)) {
116 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
117 return NULL;
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);
131 return temp;
135 void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
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);
145 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
146 unsigned int smb_buf_length, struct sockaddr *sin)
148 int rc = 0;
149 int i = 0;
150 struct msghdr smb_msg;
151 struct kvec iov;
152 unsigned len = smb_buf_length + 4;
154 if(ssocket == NULL)
155 return -ENOTSOCK; /* BB eventually add reconnect code here */
156 iov.iov_base = smb_buffer;
157 iov.iov_len = len;
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?*/
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 */
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);
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;
188 msleep(1 << i);
189 continue;
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;
200 if (rc < 0) {
201 cERROR(1,("Error %d sending data on socket to server", rc));
202 } else {
203 rc = 0;
206 return rc;
209 static int
210 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
211 struct sockaddr *sin)
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;
221 if(ssocket == NULL)
222 return -ENOTSOCK; /* BB eventually add reconnect code here */
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?*/
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 */
236 total_len = 0;
237 for (i = 0; i < n_vec; i++)
238 total_len += iov[i].iov_len;
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);
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;
256 msleep(1 << i);
257 continue;
259 if (rc < 0)
260 break;
262 if (rc >= total_len) {
263 WARN_ON(rc > total_len);
264 break;
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;
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;
288 i = 0; /* in case we get ENOSPC on the next send */
291 if (rc < 0) {
292 cERROR(1,("Error %d sending data on socket to server", rc));
293 } else
294 rc = 0;
296 return rc;
300 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
302 const int long_op)
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;
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
312 if ((ses == NULL) || (ses->server == NULL)) {
313 cifs_small_buf_release(in_buf);
314 cERROR(1,("Null session"));
315 return -EIO;
318 if(ses->server->tcpStatus == CifsExiting) {
319 cifs_small_buf_release(in_buf);
320 return -ENOENT;
323 /* Ensure that we do not send more than 50 overlapping requests
324 to the same server. We may make this configurable later or
325 use ses->maxReq */
326 if(long_op == -1) {
327 /* oplock breaks must not be held up */
328 atomic_inc(&ses->server->inFlight);
329 } else {
330 spin_lock(&GlobalMid_Lock);
331 while(1) {
332 if(atomic_read(&ses->server->inFlight) >=
333 cifs_max_pending){
334 spin_unlock(&GlobalMid_Lock);
335 #ifdef CONFIG_CIFS_STATS2
336 atomic_inc(&ses->server->num_waiters);
337 #endif
338 wait_event(ses->server->request_q,
339 atomic_read(&ses->server->inFlight)
340 < cifs_max_pending);
341 #ifdef CONFIG_CIFS_STATS2
342 atomic_dec(&ses->server->num_waiters);
343 #endif
344 spin_lock(&GlobalMid_Lock);
345 } else {
346 if(ses->server->tcpStatus == CifsExiting) {
347 spin_unlock(&GlobalMid_Lock);
348 cifs_small_buf_release(in_buf);
349 return -ENOENT;
352 /* can not count locking commands against total since
353 they are allowed to block on server */
355 if(long_op < 3) {
356 /* update # of requests on the wire to server */
357 atomic_inc(&ses->server->inFlight);
359 spin_unlock(&GlobalMid_Lock);
360 break;
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 */
368 down(&ses->server->tcpSem);
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 */
385 midQ = AllocMidQEntry(in_buf, ses);
386 if (midQ == NULL) {
387 up(&ses->server->tcpSem);
388 cifs_small_buf_release(in_buf);
389 /* If not lock req, update # of requests on wire to server */
390 if(long_op < 3) {
391 atomic_dec(&ses->server->inFlight);
392 wake_up(&ses->server->request_q);
394 return -ENOMEM;
397 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
399 midQ->midState = MID_REQUEST_SUBMITTED;
400 #ifdef CONFIG_CIFS_STATS2
401 atomic_inc(&ses->server->inSend);
402 #endif
403 rc = smb_send2(ses->server->ssocket, iov, n_vec,
404 (struct sockaddr *) &(ses->server->addr.sockAddr));
405 #ifdef CONFIG_CIFS_STATS2
406 atomic_dec(&ses->server->inSend);
407 midQ->when_sent = jiffies;
408 #endif
409 if(rc < 0) {
410 DeleteMidQEntry(midQ);
411 up(&ses->server->tcpSem);
412 cifs_small_buf_release(in_buf);
413 /* If not lock req, update # of requests on wire to server */
414 if(long_op < 3) {
415 atomic_dec(&ses->server->inFlight);
416 wake_up(&ses->server->request_q);
418 return rc;
419 } else {
420 up(&ses->server->tcpSem);
421 cifs_small_buf_release(in_buf);
424 if (long_op == -1)
425 goto cifs_no_response_exit2;
426 else if (long_op == 2) /* writes past end of file can take loong time */
427 timeout = 180 * HZ;
428 else if (long_op == 1)
429 timeout = 45 * HZ; /* should be greater than
430 servers oplock break timeout (about 43 seconds) */
431 else if (long_op > 2) {
432 timeout = MAX_SCHEDULE_TIMEOUT;
433 } else
434 timeout = 15 * HZ;
435 /* wait for 15 seconds or until woken up due to response arriving or
436 due to last connection to this server being unmounted */
437 if (signal_pending(current)) {
438 /* if signal pending do not hold up user for full smb timeout
439 but we still give response a change to complete */
440 timeout = 2 * HZ;
443 /* No user interrupts in wait - wreaks havoc with performance */
444 if(timeout != MAX_SCHEDULE_TIMEOUT) {
445 timeout += jiffies;
446 wait_event(ses->server->response_q,
447 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
448 time_after(jiffies, timeout) ||
449 ((ses->server->tcpStatus != CifsGood) &&
450 (ses->server->tcpStatus != CifsNew)));
451 } else {
452 wait_event(ses->server->response_q,
453 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
454 ((ses->server->tcpStatus != CifsGood) &&
455 (ses->server->tcpStatus != CifsNew)));
458 spin_lock(&GlobalMid_Lock);
459 if (midQ->resp_buf) {
460 spin_unlock(&GlobalMid_Lock);
461 receive_len = midQ->resp_buf->smb_buf_length;
462 } else {
463 cERROR(1,("No response to cmd %d mid %d",
464 midQ->command, midQ->mid));
465 if(midQ->midState == MID_REQUEST_SUBMITTED) {
466 if(ses->server->tcpStatus == CifsExiting)
467 rc = -EHOSTDOWN;
468 else {
469 ses->server->tcpStatus = CifsNeedReconnect;
470 midQ->midState = MID_RETRY_NEEDED;
474 if (rc != -EHOSTDOWN) {
475 if(midQ->midState == MID_RETRY_NEEDED) {
476 rc = -EAGAIN;
477 cFYI(1,("marking request for retry"));
478 } else {
479 rc = -EIO;
482 spin_unlock(&GlobalMid_Lock);
483 DeleteMidQEntry(midQ);
484 /* If not lock req, update # of requests on wire to server */
485 if(long_op < 3) {
486 atomic_dec(&ses->server->inFlight);
487 wake_up(&ses->server->request_q);
489 return rc;
492 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
493 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
494 receive_len, xid));
495 rc = -EIO;
496 } else { /* rcvd frame is ok */
497 if (midQ->resp_buf &&
498 (midQ->midState == MID_RESPONSE_RECEIVED)) {
500 iov[0].iov_base = (char *)midQ->resp_buf;
501 if(midQ->largeBuf)
502 *pRespBufType = CIFS_LARGE_BUFFER;
503 else
504 *pRespBufType = CIFS_SMALL_BUFFER;
505 iov[0].iov_len = receive_len + 4;
507 dump_smb(midQ->resp_buf, 80);
508 /* convert the length into a more usable form */
509 if((receive_len > 24) &&
510 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
511 SECMODE_SIGN_ENABLED))) {
512 rc = cifs_verify_signature(midQ->resp_buf,
513 ses->server->mac_signing_key,
514 midQ->sequence_number+1);
515 if(rc) {
516 cERROR(1,("Unexpected SMB signature"));
517 /* BB FIXME add code to kill session */
521 /* BB special case reconnect tid and uid here? */
522 /* BB special case Errbadpassword and pwdexpired here */
523 rc = map_smb_to_linux_error(midQ->resp_buf);
525 /* convert ByteCount if necessary */
526 if (receive_len >=
527 sizeof (struct smb_hdr) -
528 4 /* do not count RFC1001 header */ +
529 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
530 BCC(midQ->resp_buf) =
531 le16_to_cpu(BCC_LE(midQ->resp_buf));
532 midQ->resp_buf = NULL; /* mark it so will not be freed
533 by DeleteMidQEntry */
534 } else {
535 rc = -EIO;
536 cFYI(1,("Bad MID state?"));
539 cifs_no_response_exit2:
540 DeleteMidQEntry(midQ);
542 if(long_op < 3) {
543 atomic_dec(&ses->server->inFlight);
544 wake_up(&ses->server->request_q);
547 return rc;
549 out_unlock2:
550 up(&ses->server->tcpSem);
551 cifs_small_buf_release(in_buf);
552 /* If not lock req, update # of requests on wire to server */
553 if(long_op < 3) {
554 atomic_dec(&ses->server->inFlight);
555 wake_up(&ses->server->request_q);
558 return rc;
562 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
563 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
564 int *pbytes_returned, const int long_op)
566 int rc = 0;
567 unsigned int receive_len;
568 unsigned long timeout;
569 struct mid_q_entry *midQ;
571 if (ses == NULL) {
572 cERROR(1,("Null smb session"));
573 return -EIO;
575 if(ses->server == NULL) {
576 cERROR(1,("Null tcp session"));
577 return -EIO;
580 if(ses->server->tcpStatus == CifsExiting)
581 return -ENOENT;
583 /* Ensure that we do not send more than 50 overlapping requests
584 to the same server. We may make this configurable later or
585 use ses->maxReq */
586 if(long_op == -1) {
587 /* oplock breaks must not be held up */
588 atomic_inc(&ses->server->inFlight);
589 } else {
590 spin_lock(&GlobalMid_Lock);
591 while(1) {
592 if(atomic_read(&ses->server->inFlight) >=
593 cifs_max_pending){
594 spin_unlock(&GlobalMid_Lock);
595 #ifdef CONFIG_CIFS_STATS2
596 atomic_inc(&ses->server->num_waiters);
597 #endif
598 wait_event(ses->server->request_q,
599 atomic_read(&ses->server->inFlight)
600 < cifs_max_pending);
601 #ifdef CONFIG_CIFS_STATS2
602 atomic_dec(&ses->server->num_waiters);
603 #endif
604 spin_lock(&GlobalMid_Lock);
605 } else {
606 if(ses->server->tcpStatus == CifsExiting) {
607 spin_unlock(&GlobalMid_Lock);
608 return -ENOENT;
611 /* can not count locking commands against total since
612 they are allowed to block on server */
614 if(long_op < 3) {
615 /* update # of requests on the wire to server */
616 atomic_inc(&ses->server->inFlight);
618 spin_unlock(&GlobalMid_Lock);
619 break;
623 /* make sure that we sign in the same order that we send on this socket
624 and avoid races inside tcp sendmsg code that could cause corruption
625 of smb data */
627 down(&ses->server->tcpSem);
629 if (ses->server->tcpStatus == CifsExiting) {
630 rc = -ENOENT;
631 goto out_unlock;
632 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
633 cFYI(1,("tcp session dead - return to caller to retry"));
634 rc = -EAGAIN;
635 goto out_unlock;
636 } else if (ses->status != CifsGood) {
637 /* check if SMB session is bad because we are setting it up */
638 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
639 (in_buf->Command != SMB_COM_NEGOTIATE)) {
640 rc = -EAGAIN;
641 goto out_unlock;
642 } /* else ok - we are setting up session */
644 midQ = AllocMidQEntry(in_buf, ses);
645 if (midQ == NULL) {
646 up(&ses->server->tcpSem);
647 /* If not lock req, update # of requests on wire to server */
648 if(long_op < 3) {
649 atomic_dec(&ses->server->inFlight);
650 wake_up(&ses->server->request_q);
652 return -ENOMEM;
655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
656 up(&ses->server->tcpSem);
657 cERROR(1, ("Illegal length, greater than maximum frame, %d",
658 in_buf->smb_buf_length));
659 DeleteMidQEntry(midQ);
660 /* If not lock req, update # of requests on wire to server */
661 if(long_op < 3) {
662 atomic_dec(&ses->server->inFlight);
663 wake_up(&ses->server->request_q);
665 return -EIO;
668 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
670 midQ->midState = MID_REQUEST_SUBMITTED;
671 #ifdef CONFIG_CIFS_STATS2
672 atomic_inc(&ses->server->inSend);
673 #endif
674 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
675 (struct sockaddr *) &(ses->server->addr.sockAddr));
676 #ifdef CONFIG_CIFS_STATS2
677 atomic_dec(&ses->server->inSend);
678 midQ->when_sent = jiffies;
679 #endif
680 if(rc < 0) {
681 DeleteMidQEntry(midQ);
682 up(&ses->server->tcpSem);
683 /* If not lock req, update # of requests on wire to server */
684 if(long_op < 3) {
685 atomic_dec(&ses->server->inFlight);
686 wake_up(&ses->server->request_q);
688 return rc;
689 } else
690 up(&ses->server->tcpSem);
691 if (long_op == -1)
692 goto cifs_no_response_exit;
693 else if (long_op == 2) /* writes past end of file can take loong time */
694 timeout = 180 * HZ;
695 else if (long_op == 1)
696 timeout = 45 * HZ; /* should be greater than
697 servers oplock break timeout (about 43 seconds) */
698 else if (long_op > 2) {
699 timeout = MAX_SCHEDULE_TIMEOUT;
700 } else
701 timeout = 15 * HZ;
702 /* wait for 15 seconds or until woken up due to response arriving or
703 due to last connection to this server being unmounted */
704 if (signal_pending(current)) {
705 /* if signal pending do not hold up user for full smb timeout
706 but we still give response a change to complete */
707 timeout = 2 * HZ;
710 /* No user interrupts in wait - wreaks havoc with performance */
711 if(timeout != MAX_SCHEDULE_TIMEOUT) {
712 timeout += jiffies;
713 wait_event(ses->server->response_q,
714 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
715 time_after(jiffies, timeout) ||
716 ((ses->server->tcpStatus != CifsGood) &&
717 (ses->server->tcpStatus != CifsNew)));
718 } else {
719 wait_event(ses->server->response_q,
720 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
721 ((ses->server->tcpStatus != CifsGood) &&
722 (ses->server->tcpStatus != CifsNew)));
725 spin_lock(&GlobalMid_Lock);
726 if (midQ->resp_buf) {
727 spin_unlock(&GlobalMid_Lock);
728 receive_len = midQ->resp_buf->smb_buf_length;
729 } else {
730 cERROR(1,("No response for cmd %d mid %d",
731 midQ->command, midQ->mid));
732 if(midQ->midState == MID_REQUEST_SUBMITTED) {
733 if(ses->server->tcpStatus == CifsExiting)
734 rc = -EHOSTDOWN;
735 else {
736 ses->server->tcpStatus = CifsNeedReconnect;
737 midQ->midState = MID_RETRY_NEEDED;
741 if (rc != -EHOSTDOWN) {
742 if(midQ->midState == MID_RETRY_NEEDED) {
743 rc = -EAGAIN;
744 cFYI(1,("marking request for retry"));
745 } else {
746 rc = -EIO;
749 spin_unlock(&GlobalMid_Lock);
750 DeleteMidQEntry(midQ);
751 /* If not lock req, update # of requests on wire to server */
752 if(long_op < 3) {
753 atomic_dec(&ses->server->inFlight);
754 wake_up(&ses->server->request_q);
756 return rc;
759 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
760 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
761 receive_len, xid));
762 rc = -EIO;
763 } else { /* rcvd frame is ok */
765 if (midQ->resp_buf && out_buf
766 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
767 out_buf->smb_buf_length = receive_len;
768 memcpy((char *)out_buf + 4,
769 (char *)midQ->resp_buf + 4,
770 receive_len);
772 dump_smb(out_buf, 92);
773 /* convert the length into a more usable form */
774 if((receive_len > 24) &&
775 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
776 SECMODE_SIGN_ENABLED))) {
777 rc = cifs_verify_signature(out_buf,
778 ses->server->mac_signing_key,
779 midQ->sequence_number+1);
780 if(rc) {
781 cERROR(1,("Unexpected SMB signature"));
782 /* BB FIXME add code to kill session */
786 *pbytes_returned = out_buf->smb_buf_length;
788 /* BB special case reconnect tid and uid here? */
789 rc = map_smb_to_linux_error(out_buf);
791 /* convert ByteCount if necessary */
792 if (receive_len >=
793 sizeof (struct smb_hdr) -
794 4 /* do not count RFC1001 header */ +
795 (2 * out_buf->WordCount) + 2 /* bcc */ )
796 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
797 } else {
798 rc = -EIO;
799 cERROR(1,("Bad MID state?"));
802 cifs_no_response_exit:
803 DeleteMidQEntry(midQ);
805 if(long_op < 3) {
806 atomic_dec(&ses->server->inFlight);
807 wake_up(&ses->server->request_q);
810 return rc;
812 out_unlock:
813 up(&ses->server->tcpSem);
814 /* If not lock req, update # of requests on wire to server */
815 if(long_op < 3) {
816 atomic_dec(&ses->server->inFlight);
817 wake_up(&ses->server->request_q);
820 return rc;