[ACPI] merge 3549 4320 4485 4588 4980 5483 5651 acpica asus fops pnpacpi branches...
[firefly-linux-kernel-4.4.55.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                         iov[1].iov_len = 0;
502
503                         dump_smb(midQ->resp_buf, 80);
504                         /* convert the length into a more usable form */
505                         if((receive_len > 24) &&
506                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
507                                         SECMODE_SIGN_ENABLED))) {
508                                 rc = cifs_verify_signature(midQ->resp_buf,
509                                                 ses->server->mac_signing_key,
510                                                 midQ->sequence_number+1);
511                                 if(rc) {
512                                         cERROR(1,("Unexpected SMB signature"));
513                                         /* BB FIXME add code to kill session */
514                                 }
515                         }
516
517                         /* BB special case reconnect tid and uid here? */
518                         /* BB special case Errbadpassword and pwdexpired here */
519                         rc = map_smb_to_linux_error(midQ->resp_buf);
520
521                         /* convert ByteCount if necessary */
522                         if (receive_len >=
523                             sizeof (struct smb_hdr) -
524                             4 /* do not count RFC1001 header */  +
525                             (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
526                                 BCC(midQ->resp_buf) = 
527                                         le16_to_cpu(BCC_LE(midQ->resp_buf));
528                         midQ->resp_buf = NULL;  /* mark it so will not be freed
529                                                 by DeleteMidQEntry */
530                 } else {
531                         rc = -EIO;
532                         cFYI(1,("Bad MID state?"));
533                 }
534         }
535 cifs_no_response_exit2:
536         DeleteMidQEntry(midQ);
537
538         if(long_op < 3) {
539                 atomic_dec(&ses->server->inFlight); 
540                 wake_up(&ses->server->request_q);
541         }
542
543         return rc;
544
545 out_unlock2:
546         up(&ses->server->tcpSem);
547         /* If not lock req, update # of requests on wire to server */
548         if(long_op < 3) {
549                 atomic_dec(&ses->server->inFlight); 
550                 wake_up(&ses->server->request_q);
551         }
552
553         return rc;
554 }
555
556 int
557 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
558             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
559             int *pbytes_returned, const int long_op)
560 {
561         int rc = 0;
562         unsigned int receive_len;
563         unsigned long timeout;
564         struct mid_q_entry *midQ;
565
566         if (ses == NULL) {
567                 cERROR(1,("Null smb session"));
568                 return -EIO;
569         }
570         if(ses->server == NULL) {
571                 cERROR(1,("Null tcp session"));
572                 return -EIO;
573         }
574
575         if(ses->server->tcpStatus == CifsExiting)
576                 return -ENOENT;
577
578         /* Ensure that we do not send more than 50 overlapping requests 
579            to the same server. We may make this configurable later or
580            use ses->maxReq */
581         if(long_op == -1) {
582                 /* oplock breaks must not be held up */
583                 atomic_inc(&ses->server->inFlight);
584         } else {
585                 spin_lock(&GlobalMid_Lock); 
586                 while(1) {        
587                         if(atomic_read(&ses->server->inFlight) >= 
588                                         cifs_max_pending){
589                                 spin_unlock(&GlobalMid_Lock);
590 #ifdef CONFIG_CIFS_STATS2
591                                 atomic_inc(&ses->server->num_waiters);
592 #endif
593                                 wait_event(ses->server->request_q,
594                                         atomic_read(&ses->server->inFlight)
595                                          < cifs_max_pending);
596 #ifdef CONFIG_CIFS_STATS2
597                                 atomic_dec(&ses->server->num_waiters);
598 #endif
599                                 spin_lock(&GlobalMid_Lock);
600                         } else {
601                                 if(ses->server->tcpStatus == CifsExiting) {
602                                         spin_unlock(&GlobalMid_Lock);
603                                         return -ENOENT;
604                                 }
605
606                         /* can not count locking commands against total since
607                            they are allowed to block on server */
608                                         
609                                 if(long_op < 3) {
610                                 /* update # of requests on the wire to server */
611                                         atomic_inc(&ses->server->inFlight);
612                                 }
613                                 spin_unlock(&GlobalMid_Lock);
614                                 break;
615                         }
616                 }
617         }
618         /* make sure that we sign in the same order that we send on this socket 
619            and avoid races inside tcp sendmsg code that could cause corruption
620            of smb data */
621
622         down(&ses->server->tcpSem); 
623
624         if (ses->server->tcpStatus == CifsExiting) {
625                 rc = -ENOENT;
626                 goto out_unlock;
627         } else if (ses->server->tcpStatus == CifsNeedReconnect) {
628                 cFYI(1,("tcp session dead - return to caller to retry"));
629                 rc = -EAGAIN;
630                 goto out_unlock;
631         } else if (ses->status != CifsGood) {
632                 /* check if SMB session is bad because we are setting it up */
633                 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
634                         (in_buf->Command != SMB_COM_NEGOTIATE)) {
635                         rc = -EAGAIN;
636                         goto out_unlock;
637                 } /* else ok - we are setting up session */
638         }
639         midQ = AllocMidQEntry(in_buf, ses);
640         if (midQ == NULL) {
641                 up(&ses->server->tcpSem);
642                 /* If not lock req, update # of requests on wire to server */
643                 if(long_op < 3) {
644                         atomic_dec(&ses->server->inFlight); 
645                         wake_up(&ses->server->request_q);
646                 }
647                 return -ENOMEM;
648         }
649
650         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
651                 up(&ses->server->tcpSem);
652                 cERROR(1,
653                        ("Illegal length, greater than maximum frame, %d ",
654                         in_buf->smb_buf_length));
655                 DeleteMidQEntry(midQ);
656                 /* If not lock req, update # of requests on wire to server */
657                 if(long_op < 3) {
658                         atomic_dec(&ses->server->inFlight); 
659                         wake_up(&ses->server->request_q);
660                 }
661                 return -EIO;
662         }
663
664         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
665
666         midQ->midState = MID_REQUEST_SUBMITTED;
667 #ifdef CONFIG_CIFS_STATS2
668         atomic_inc(&ses->server->inSend);
669 #endif
670         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
671                       (struct sockaddr *) &(ses->server->addr.sockAddr));
672 #ifdef CONFIG_CIFS_STATS2
673         atomic_dec(&ses->server->inSend);
674         midQ->when_sent = jiffies;
675 #endif
676         if(rc < 0) {
677                 DeleteMidQEntry(midQ);
678                 up(&ses->server->tcpSem);
679                 /* If not lock req, update # of requests on wire to server */
680                 if(long_op < 3) {
681                         atomic_dec(&ses->server->inFlight); 
682                         wake_up(&ses->server->request_q);
683                 }
684                 return rc;
685         } else
686                 up(&ses->server->tcpSem);
687         if (long_op == -1)
688                 goto cifs_no_response_exit;
689         else if (long_op == 2) /* writes past end of file can take loong time */
690                 timeout = 180 * HZ;
691         else if (long_op == 1)
692                 timeout = 45 * HZ; /* should be greater than 
693                         servers oplock break timeout (about 43 seconds) */
694         else if (long_op > 2) {
695                 timeout = MAX_SCHEDULE_TIMEOUT;
696         } else
697                 timeout = 15 * HZ;
698         /* wait for 15 seconds or until woken up due to response arriving or 
699            due to last connection to this server being unmounted */
700         if (signal_pending(current)) {
701                 /* if signal pending do not hold up user for full smb timeout
702                 but we still give response a change to complete */
703                 timeout = 2 * HZ;
704         }   
705
706         /* No user interrupts in wait - wreaks havoc with performance */
707         if(timeout != MAX_SCHEDULE_TIMEOUT) {
708                 timeout += jiffies;
709                 wait_event(ses->server->response_q,
710                         (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
711                         time_after(jiffies, timeout) || 
712                         ((ses->server->tcpStatus != CifsGood) &&
713                          (ses->server->tcpStatus != CifsNew)));
714         } else {
715                 wait_event(ses->server->response_q,
716                         (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
717                         ((ses->server->tcpStatus != CifsGood) &&
718                          (ses->server->tcpStatus != CifsNew)));
719         }
720
721         spin_lock(&GlobalMid_Lock);
722         if (midQ->resp_buf) {
723                 spin_unlock(&GlobalMid_Lock);
724                 receive_len = midQ->resp_buf->smb_buf_length;
725         } else {
726                 cERROR(1,("No response for cmd %d mid %d",
727                           midQ->command, midQ->mid));
728                 if(midQ->midState == MID_REQUEST_SUBMITTED) {
729                         if(ses->server->tcpStatus == CifsExiting)
730                                 rc = -EHOSTDOWN;
731                         else {
732                                 ses->server->tcpStatus = CifsNeedReconnect;
733                                 midQ->midState = MID_RETRY_NEEDED;
734                         }
735                 }
736
737                 if (rc != -EHOSTDOWN) {
738                         if(midQ->midState == MID_RETRY_NEEDED) {
739                                 rc = -EAGAIN;
740                                 cFYI(1,("marking request for retry"));
741                         } else {
742                                 rc = -EIO;
743                         }
744                 }
745                 spin_unlock(&GlobalMid_Lock);
746                 DeleteMidQEntry(midQ);
747                 /* If not lock req, update # of requests on wire to server */
748                 if(long_op < 3) {
749                         atomic_dec(&ses->server->inFlight); 
750                         wake_up(&ses->server->request_q);
751                 }
752                 return rc;
753         }
754   
755         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
756                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
757                         receive_len, xid));
758                 rc = -EIO;
759         } else {                /* rcvd frame is ok */
760
761                 if (midQ->resp_buf && out_buf
762                     && (midQ->midState == MID_RESPONSE_RECEIVED)) {
763                         out_buf->smb_buf_length = receive_len;
764                         memcpy((char *)out_buf + 4,
765                                (char *)midQ->resp_buf + 4,
766                                receive_len);
767
768                         dump_smb(out_buf, 92);
769                         /* convert the length into a more usable form */
770                         if((receive_len > 24) &&
771                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
772                                         SECMODE_SIGN_ENABLED))) {
773                                 rc = cifs_verify_signature(out_buf,
774                                                 ses->server->mac_signing_key,
775                                                 midQ->sequence_number+1);
776                                 if(rc) {
777                                         cERROR(1,("Unexpected SMB signature"));
778                                         /* BB FIXME add code to kill session */
779                                 }
780                         }
781
782                         *pbytes_returned = out_buf->smb_buf_length;
783
784                         /* BB special case reconnect tid and uid here? */
785                         rc = map_smb_to_linux_error(out_buf);
786
787                         /* convert ByteCount if necessary */
788                         if (receive_len >=
789                             sizeof (struct smb_hdr) -
790                             4 /* do not count RFC1001 header */  +
791                             (2 * out_buf->WordCount) + 2 /* bcc */ )
792                                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
793                 } else {
794                         rc = -EIO;
795                         cERROR(1,("Bad MID state?"));
796                 }
797         }
798 cifs_no_response_exit:
799         DeleteMidQEntry(midQ);
800
801         if(long_op < 3) {
802                 atomic_dec(&ses->server->inFlight); 
803                 wake_up(&ses->server->request_q);
804         }
805
806         return rc;
807
808 out_unlock:
809         up(&ses->server->tcpSem);
810         /* If not lock req, update # of requests on wire to server */
811         if(long_op < 3) {
812                 atomic_dec(&ses->server->inFlight); 
813                 wake_up(&ses->server->request_q);
814         }
815
816         return rc;
817 }