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