]> err.no Git - linux-2.6/blob - fs/cifs/transport.c
[CIFS] Do not time out posix brl requests when using new posix setfileinfo
[linux-2.6] / 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) || (ses->server == NULL)) {
313                 cifs_small_buf_release(in_buf);
314                 cERROR(1,("Null session"));
315                 return -EIO;
316         }
317
318         if(ses->server->tcpStatus == CifsExiting) {
319                 cifs_small_buf_release(in_buf);
320                 return -ENOENT;
321         }
322
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;
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                 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);
393                 }
394                 return -ENOMEM;
395         }
396
397         rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
398
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);
417                 }
418                 return rc;
419         } else {
420                 up(&ses->server->tcpSem);
421                 cifs_small_buf_release(in_buf);
422         }
423
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;
441         }   
442
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                                 time_after(jiffies, ses->server->lstrp + HZ)) ||
450                         ((ses->server->tcpStatus != CifsGood) &&
451                          (ses->server->tcpStatus != CifsNew)));
452         } else {
453                 wait_event(ses->server->response_q,
454                         (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
455                         ((ses->server->tcpStatus != CifsGood) &&
456                          (ses->server->tcpStatus != CifsNew)));
457         }
458
459         spin_lock(&GlobalMid_Lock);
460         if (midQ->resp_buf) {
461                 spin_unlock(&GlobalMid_Lock);
462                 receive_len = midQ->resp_buf->smb_buf_length;
463         } else {
464                 cERROR(1,("No response to cmd %d mid %d",
465                         midQ->command, midQ->mid));
466                 if(midQ->midState == MID_REQUEST_SUBMITTED) {
467                         if(ses->server->tcpStatus == CifsExiting)
468                                 rc = -EHOSTDOWN;
469                         else {
470                                 ses->server->tcpStatus = CifsNeedReconnect;
471                                 midQ->midState = MID_RETRY_NEEDED;
472                         }
473                 }
474
475                 if (rc != -EHOSTDOWN) {
476                         if(midQ->midState == MID_RETRY_NEEDED) {
477                                 rc = -EAGAIN;
478                                 cFYI(1,("marking request for retry"));
479                         } else {
480                                 rc = -EIO;
481                         }
482                 }
483                 spin_unlock(&GlobalMid_Lock);
484                 DeleteMidQEntry(midQ);
485                 /* If not lock req, update # of requests on wire to server */
486                 if(long_op < 3) {
487                         atomic_dec(&ses->server->inFlight); 
488                         wake_up(&ses->server->request_q);
489                 }
490                 return rc;
491         }
492   
493         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
494                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
495                         receive_len, xid));
496                 rc = -EIO;
497         } else {                /* rcvd frame is ok */
498                 if (midQ->resp_buf && 
499                         (midQ->midState == MID_RESPONSE_RECEIVED)) {
500
501                         iov[0].iov_base = (char *)midQ->resp_buf;
502                         if(midQ->largeBuf)
503                                 *pRespBufType = CIFS_LARGE_BUFFER;
504                         else
505                                 *pRespBufType = CIFS_SMALL_BUFFER;
506                         iov[0].iov_len = receive_len + 4;
507
508                         dump_smb(midQ->resp_buf, 80);
509                         /* convert the length into a more usable form */
510                         if((receive_len > 24) &&
511                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
512                                         SECMODE_SIGN_ENABLED))) {
513                                 rc = cifs_verify_signature(midQ->resp_buf,
514                                                 ses->server->mac_signing_key,
515                                                 midQ->sequence_number+1);
516                                 if(rc) {
517                                         cERROR(1,("Unexpected SMB signature"));
518                                         /* BB FIXME add code to kill session */
519                                 }
520                         }
521
522                         /* BB special case reconnect tid and uid here? */
523                         /* BB special case Errbadpassword and pwdexpired here */
524                         rc = map_smb_to_linux_error(midQ->resp_buf);
525
526                         /* convert ByteCount if necessary */
527                         if (receive_len >=
528                             sizeof (struct smb_hdr) -
529                             4 /* do not count RFC1001 header */  +
530                             (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
531                                 BCC(midQ->resp_buf) = 
532                                         le16_to_cpu(BCC_LE(midQ->resp_buf));
533                         midQ->resp_buf = NULL;  /* mark it so will not be freed
534                                                 by DeleteMidQEntry */
535                 } else {
536                         rc = -EIO;
537                         cFYI(1,("Bad MID state?"));
538                 }
539         }
540 cifs_no_response_exit2:
541         DeleteMidQEntry(midQ);
542
543         if(long_op < 3) {
544                 atomic_dec(&ses->server->inFlight); 
545                 wake_up(&ses->server->request_q);
546         }
547
548         return rc;
549
550 out_unlock2:
551         up(&ses->server->tcpSem);
552         cifs_small_buf_release(in_buf);
553         /* If not lock req, update # of requests on wire to server */
554         if(long_op < 3) {
555                 atomic_dec(&ses->server->inFlight); 
556                 wake_up(&ses->server->request_q);
557         }
558
559         return rc;
560 }
561
562 int
563 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
564             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
565             int *pbytes_returned, const int long_op)
566 {
567         int rc = 0;
568         unsigned int receive_len;
569         unsigned long timeout;
570         struct mid_q_entry *midQ;
571
572         if (ses == NULL) {
573                 cERROR(1,("Null smb session"));
574                 return -EIO;
575         }
576         if(ses->server == NULL) {
577                 cERROR(1,("Null tcp session"));
578                 return -EIO;
579         }
580
581         if(ses->server->tcpStatus == CifsExiting)
582                 return -ENOENT;
583
584         /* Ensure that we do not send more than 50 overlapping requests 
585            to the same server. We may make this configurable later or
586            use ses->maxReq */
587         if(long_op == -1) {
588                 /* oplock breaks must not be held up */
589                 atomic_inc(&ses->server->inFlight);
590         } else {
591                 spin_lock(&GlobalMid_Lock); 
592                 while(1) {        
593                         if(atomic_read(&ses->server->inFlight) >= 
594                                         cifs_max_pending){
595                                 spin_unlock(&GlobalMid_Lock);
596 #ifdef CONFIG_CIFS_STATS2
597                                 atomic_inc(&ses->server->num_waiters);
598 #endif
599                                 wait_event(ses->server->request_q,
600                                         atomic_read(&ses->server->inFlight)
601                                          < cifs_max_pending);
602 #ifdef CONFIG_CIFS_STATS2
603                                 atomic_dec(&ses->server->num_waiters);
604 #endif
605                                 spin_lock(&GlobalMid_Lock);
606                         } else {
607                                 if(ses->server->tcpStatus == CifsExiting) {
608                                         spin_unlock(&GlobalMid_Lock);
609                                         return -ENOENT;
610                                 }
611
612                         /* can not count locking commands against total since
613                            they are allowed to block on server */
614                                         
615                                 if(long_op < 3) {
616                                 /* update # of requests on the wire to server */
617                                         atomic_inc(&ses->server->inFlight);
618                                 }
619                                 spin_unlock(&GlobalMid_Lock);
620                                 break;
621                         }
622                 }
623         }
624         /* make sure that we sign in the same order that we send on this socket 
625            and avoid races inside tcp sendmsg code that could cause corruption
626            of smb data */
627
628         down(&ses->server->tcpSem); 
629
630         if (ses->server->tcpStatus == CifsExiting) {
631                 rc = -ENOENT;
632                 goto out_unlock;
633         } else if (ses->server->tcpStatus == CifsNeedReconnect) {
634                 cFYI(1,("tcp session dead - return to caller to retry"));
635                 rc = -EAGAIN;
636                 goto out_unlock;
637         } else if (ses->status != CifsGood) {
638                 /* check if SMB session is bad because we are setting it up */
639                 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 
640                         (in_buf->Command != SMB_COM_NEGOTIATE)) {
641                         rc = -EAGAIN;
642                         goto out_unlock;
643                 } /* else ok - we are setting up session */
644         }
645         midQ = AllocMidQEntry(in_buf, ses);
646         if (midQ == NULL) {
647                 up(&ses->server->tcpSem);
648                 /* If not lock req, update # of requests on wire to server */
649                 if(long_op < 3) {
650                         atomic_dec(&ses->server->inFlight); 
651                         wake_up(&ses->server->request_q);
652                 }
653                 return -ENOMEM;
654         }
655
656         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
657                 up(&ses->server->tcpSem);
658                 cERROR(1, ("Illegal length, greater than maximum frame, %d",
659                         in_buf->smb_buf_length));
660                 DeleteMidQEntry(midQ);
661                 /* If not lock req, update # of requests on wire to server */
662                 if(long_op < 3) {
663                         atomic_dec(&ses->server->inFlight); 
664                         wake_up(&ses->server->request_q);
665                 }
666                 return -EIO;
667         }
668
669         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
670
671         midQ->midState = MID_REQUEST_SUBMITTED;
672 #ifdef CONFIG_CIFS_STATS2
673         atomic_inc(&ses->server->inSend);
674 #endif
675         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
676                       (struct sockaddr *) &(ses->server->addr.sockAddr));
677 #ifdef CONFIG_CIFS_STATS2
678         atomic_dec(&ses->server->inSend);
679         midQ->when_sent = jiffies;
680 #endif
681         if(rc < 0) {
682                 DeleteMidQEntry(midQ);
683                 up(&ses->server->tcpSem);
684                 /* If not lock req, update # of requests on wire to server */
685                 if(long_op < 3) {
686                         atomic_dec(&ses->server->inFlight); 
687                         wake_up(&ses->server->request_q);
688                 }
689                 return rc;
690         } else
691                 up(&ses->server->tcpSem);
692         if (long_op == -1)
693                 goto cifs_no_response_exit;
694         else if (long_op == 2) /* writes past end of file can take loong time */
695                 timeout = 180 * HZ;
696         else if (long_op == 1)
697                 timeout = 45 * HZ; /* should be greater than 
698                         servers oplock break timeout (about 43 seconds) */
699         else if (long_op > 2) {
700                 timeout = MAX_SCHEDULE_TIMEOUT;
701         } else
702                 timeout = 15 * HZ;
703         /* wait for 15 seconds or until woken up due to response arriving or 
704            due to last connection to this server being unmounted */
705         if (signal_pending(current)) {
706                 /* if signal pending do not hold up user for full smb timeout
707                 but we still give response a change to complete */
708                 timeout = 2 * HZ;
709         }   
710
711         /* No user interrupts in wait - wreaks havoc with performance */
712         if(timeout != MAX_SCHEDULE_TIMEOUT) {
713                 timeout += jiffies;
714                 /* although we prefer not to time out if the server is still
715                 responding - we will time out if the server takes
716                 more than 15 (or 45 or 180) seconds to respond to this request
717                 and has not responded to any request from other threads
718                 on this client within a second (note that it is not worth
719                 grabbing the GlobalMid_Lock and slowing things down in this
720                 wait event to more accurately check the lstrsp field on some 
721                 arch since we are already in an error path that will retry */
722                 wait_event(ses->server->response_q,
723                         (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
724                         (time_after(jiffies, timeout) &&
725                                 time_after(jiffies, ses->server->lstrp + HZ)) ||
726                         ((ses->server->tcpStatus != CifsGood) &&
727                          (ses->server->tcpStatus != CifsNew)));
728         } else {
729                 wait_event(ses->server->response_q,
730                         (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
731                         ((ses->server->tcpStatus != CifsGood) &&
732                          (ses->server->tcpStatus != CifsNew)));
733         }
734
735         spin_lock(&GlobalMid_Lock);
736         if (midQ->resp_buf) {
737                 spin_unlock(&GlobalMid_Lock);
738                 receive_len = midQ->resp_buf->smb_buf_length;
739         } else {
740                 cERROR(1,("No response for cmd %d mid %d",
741                           midQ->command, midQ->mid));
742                 if(midQ->midState == MID_REQUEST_SUBMITTED) {
743                         if(ses->server->tcpStatus == CifsExiting)
744                                 rc = -EHOSTDOWN;
745                         else {
746                                 ses->server->tcpStatus = CifsNeedReconnect;
747                                 midQ->midState = MID_RETRY_NEEDED;
748                         }
749                 }
750
751                 if (rc != -EHOSTDOWN) {
752                         if(midQ->midState == MID_RETRY_NEEDED) {
753                                 rc = -EAGAIN;
754                                 cFYI(1,("marking request for retry"));
755                         } else {
756                                 rc = -EIO;
757                         }
758                 }
759                 spin_unlock(&GlobalMid_Lock);
760                 DeleteMidQEntry(midQ);
761                 /* If not lock req, update # of requests on wire to server */
762                 if(long_op < 3) {
763                         atomic_dec(&ses->server->inFlight); 
764                         wake_up(&ses->server->request_q);
765                 }
766                 return rc;
767         }
768   
769         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
770                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
771                         receive_len, xid));
772                 rc = -EIO;
773         } else {                /* rcvd frame is ok */
774
775                 if (midQ->resp_buf && out_buf
776                     && (midQ->midState == MID_RESPONSE_RECEIVED)) {
777                         out_buf->smb_buf_length = receive_len;
778                         memcpy((char *)out_buf + 4,
779                                (char *)midQ->resp_buf + 4,
780                                receive_len);
781
782                         dump_smb(out_buf, 92);
783                         /* convert the length into a more usable form */
784                         if((receive_len > 24) &&
785                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
786                                         SECMODE_SIGN_ENABLED))) {
787                                 rc = cifs_verify_signature(out_buf,
788                                                 ses->server->mac_signing_key,
789                                                 midQ->sequence_number+1);
790                                 if(rc) {
791                                         cERROR(1,("Unexpected SMB signature"));
792                                         /* BB FIXME add code to kill session */
793                                 }
794                         }
795
796                         *pbytes_returned = out_buf->smb_buf_length;
797
798                         /* BB special case reconnect tid and uid here? */
799                         rc = map_smb_to_linux_error(out_buf);
800
801                         /* convert ByteCount if necessary */
802                         if (receive_len >=
803                             sizeof (struct smb_hdr) -
804                             4 /* do not count RFC1001 header */  +
805                             (2 * out_buf->WordCount) + 2 /* bcc */ )
806                                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
807                 } else {
808                         rc = -EIO;
809                         cERROR(1,("Bad MID state?"));
810                 }
811         }
812 cifs_no_response_exit:
813         DeleteMidQEntry(midQ);
814
815         if(long_op < 3) {
816                 atomic_dec(&ses->server->inFlight); 
817                 wake_up(&ses->server->request_q);
818         }
819
820         return rc;
821
822 out_unlock:
823         up(&ses->server->tcpSem);
824         /* If not lock req, update # of requests on wire to server */
825         if(long_op < 3) {
826                 atomic_dec(&ses->server->inFlight); 
827                 wake_up(&ses->server->request_q);
828         }
829
830         return rc;
831 }