RxRPC: Fix a regression in the RXKAD security module
[sfrench/cifs-2.6.git] / fs / cifs / transport.c
1 /*
2  *   fs/cifs/transport.c
3  *
4  *   Copyright (C) International Business Machines  Corp., 2002,2008
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 struct kmem_cache *cifs_oplock_cachep;
38
39 static struct mid_q_entry *
40 AllocMidQEntry(const 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                                                     GFP_KERNEL | GFP_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                                                        GFP_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         /* Don't want to modify the buffer as a
208            side effect of this call. */
209         smb_buffer->smb_buf_length = smb_buf_length;
210
211         return rc;
212 }
213
214 static int
215 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
216           struct sockaddr *sin)
217 {
218         int rc = 0;
219         int i = 0;
220         struct msghdr smb_msg;
221         struct smb_hdr *smb_buffer = iov[0].iov_base;
222         unsigned int len = iov[0].iov_len;
223         unsigned int total_len;
224         int first_vec = 0;
225         unsigned int smb_buf_length = smb_buffer->smb_buf_length;
226
227         if (ssocket == NULL)
228                 return -ENOTSOCK; /* BB eventually add reconnect code here */
229
230         smb_msg.msg_name = sin;
231         smb_msg.msg_namelen = sizeof(struct sockaddr);
232         smb_msg.msg_control = NULL;
233         smb_msg.msg_controllen = 0;
234         smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
235
236         /* smb header is converted in header_assemble. bcc and rest of SMB word
237            area, and byte area if necessary, is converted to littleendian in
238            cifssmb.c and RFC1001 len is converted to bigendian in smb_send
239            Flags2 is converted in SendReceive */
240
241
242         total_len = 0;
243         for (i = 0; i < n_vec; i++)
244                 total_len += iov[i].iov_len;
245
246         smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
247         cFYI(1, ("Sending smb:  total_len %d", total_len));
248         dump_smb(smb_buffer, len);
249
250         while (total_len) {
251                 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
252                                     n_vec - first_vec, total_len);
253                 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
254                         i++;
255                         if (i >= 14) {
256                                 cERROR(1,
257                                    ("sends on sock %p stuck for 15 seconds",
258                                     ssocket));
259                                 rc = -EAGAIN;
260                                 break;
261                         }
262                         msleep(1 << i);
263                         continue;
264                 }
265                 if (rc < 0)
266                         break;
267
268                 if (rc >= total_len) {
269                         WARN_ON(rc > total_len);
270                         break;
271                 }
272                 if (rc == 0) {
273                         /* should never happen, letting socket clear before
274                            retrying is our only obvious option here */
275                         cERROR(1, ("tcp sent no data"));
276                         msleep(500);
277                         continue;
278                 }
279                 total_len -= rc;
280                 /* the line below resets i */
281                 for (i = first_vec; i < n_vec; i++) {
282                         if (iov[i].iov_len) {
283                                 if (rc > iov[i].iov_len) {
284                                         rc -= iov[i].iov_len;
285                                         iov[i].iov_len = 0;
286                                 } else {
287                                         iov[i].iov_base += rc;
288                                         iov[i].iov_len -= rc;
289                                         first_vec = i;
290                                         break;
291                                 }
292                         }
293                 }
294                 i = 0; /* in case we get ENOSPC on the next send */
295         }
296
297         if (rc < 0) {
298                 cERROR(1, ("Error %d sending data on socket to server", rc));
299         } else
300                 rc = 0;
301
302         /* Don't want to modify the buffer as a
303            side effect of this call. */
304         smb_buffer->smb_buf_length = smb_buf_length;
305
306         return rc;
307 }
308
309 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
310 {
311         if (long_op == CIFS_ASYNC_OP) {
312                 /* oplock breaks must not be held up */
313                 atomic_inc(&ses->server->inFlight);
314         } else {
315                 spin_lock(&GlobalMid_Lock);
316                 while (1) {
317                         if (atomic_read(&ses->server->inFlight) >=
318                                         cifs_max_pending){
319                                 spin_unlock(&GlobalMid_Lock);
320 #ifdef CONFIG_CIFS_STATS2
321                                 atomic_inc(&ses->server->num_waiters);
322 #endif
323                                 wait_event(ses->server->request_q,
324                                         atomic_read(&ses->server->inFlight)
325                                          < cifs_max_pending);
326 #ifdef CONFIG_CIFS_STATS2
327                                 atomic_dec(&ses->server->num_waiters);
328 #endif
329                                 spin_lock(&GlobalMid_Lock);
330                         } else {
331                                 if (ses->server->tcpStatus == CifsExiting) {
332                                         spin_unlock(&GlobalMid_Lock);
333                                         return -ENOENT;
334                                 }
335
336                                 /* can not count locking commands against total
337                                    as they are allowed to block on server */
338
339                                 /* update # of requests on the wire to server */
340                                 if (long_op != CIFS_BLOCKING_OP)
341                                         atomic_inc(&ses->server->inFlight);
342                                 spin_unlock(&GlobalMid_Lock);
343                                 break;
344                         }
345                 }
346         }
347         return 0;
348 }
349
350 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
351                         struct mid_q_entry **ppmidQ)
352 {
353         if (ses->server->tcpStatus == CifsExiting) {
354                 return -ENOENT;
355         } else if (ses->server->tcpStatus == CifsNeedReconnect) {
356                 cFYI(1, ("tcp session dead - return to caller to retry"));
357                 return -EAGAIN;
358         } else if (ses->status != CifsGood) {
359                 /* check if SMB session is bad because we are setting it up */
360                 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
361                         (in_buf->Command != SMB_COM_NEGOTIATE))
362                         return -EAGAIN;
363                 /* else ok - we are setting up session */
364         }
365         *ppmidQ = AllocMidQEntry(in_buf, ses);
366         if (*ppmidQ == NULL)
367                 return -ENOMEM;
368         return 0;
369 }
370
371 static int wait_for_response(struct cifsSesInfo *ses,
372                         struct mid_q_entry *midQ,
373                         unsigned long timeout,
374                         unsigned long time_to_wait)
375 {
376         unsigned long curr_timeout;
377
378         for (;;) {
379                 curr_timeout = timeout + jiffies;
380                 wait_event(ses->server->response_q,
381                         (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
382                         time_after(jiffies, curr_timeout) ||
383                         ((ses->server->tcpStatus != CifsGood) &&
384                          (ses->server->tcpStatus != CifsNew)));
385
386                 if (time_after(jiffies, curr_timeout) &&
387                         (midQ->midState == MID_REQUEST_SUBMITTED) &&
388                         ((ses->server->tcpStatus == CifsGood) ||
389                          (ses->server->tcpStatus == CifsNew))) {
390
391                         unsigned long lrt;
392
393                         /* We timed out. Is the server still
394                            sending replies ? */
395                         spin_lock(&GlobalMid_Lock);
396                         lrt = ses->server->lstrp;
397                         spin_unlock(&GlobalMid_Lock);
398
399                         /* Calculate time_to_wait past last receive time.
400                          Although we prefer not to time out if the
401                          server is still responding - we will time
402                          out if the server takes more than 15 (or 45
403                          or 180) seconds to respond to this request
404                          and has not responded to any request from
405                          other threads on the client within 10 seconds */
406                         lrt += time_to_wait;
407                         if (time_after(jiffies, lrt)) {
408                                 /* No replies for time_to_wait. */
409                                 cERROR(1, ("server not responding"));
410                                 return -1;
411                         }
412                 } else {
413                         return 0;
414                 }
415         }
416 }
417
418
419 /*
420  *
421  * Send an SMB Request.  No response info (other than return code)
422  * needs to be parsed.
423  *
424  * flags indicate the type of request buffer and how long to wait
425  * and whether to log NT STATUS code (error) before mapping it to POSIX error
426  *
427  */
428 int
429 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
430                 struct smb_hdr *in_buf, int flags)
431 {
432         int rc;
433         struct kvec iov[1];
434         int resp_buf_type;
435
436         iov[0].iov_base = (char *)in_buf;
437         iov[0].iov_len = in_buf->smb_buf_length + 4;
438         flags |= CIFS_NO_RESP;
439         rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
440         cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
441
442         return rc;
443 }
444
445 int
446 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
447              struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
448              const int flags)
449 {
450         int rc = 0;
451         int long_op;
452         unsigned int receive_len;
453         unsigned long timeout;
454         struct mid_q_entry *midQ;
455         struct smb_hdr *in_buf = iov[0].iov_base;
456
457         long_op = flags & CIFS_TIMEOUT_MASK;
458
459         *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
460
461         if ((ses == NULL) || (ses->server == NULL)) {
462                 cifs_small_buf_release(in_buf);
463                 cERROR(1, ("Null session"));
464                 return -EIO;
465         }
466
467         if (ses->server->tcpStatus == CifsExiting) {
468                 cifs_small_buf_release(in_buf);
469                 return -ENOENT;
470         }
471
472         /* Ensure that we do not send more than 50 overlapping requests
473            to the same server. We may make this configurable later or
474            use ses->maxReq */
475
476         rc = wait_for_free_request(ses, long_op);
477         if (rc) {
478                 cifs_small_buf_release(in_buf);
479                 return rc;
480         }
481
482         /* make sure that we sign in the same order that we send on this socket
483            and avoid races inside tcp sendmsg code that could cause corruption
484            of smb data */
485
486         down(&ses->server->tcpSem);
487
488         rc = allocate_mid(ses, in_buf, &midQ);
489         if (rc) {
490                 up(&ses->server->tcpSem);
491                 cifs_small_buf_release(in_buf);
492                 /* Update # of requests on wire to server */
493                 atomic_dec(&ses->server->inFlight);
494                 wake_up(&ses->server->request_q);
495                 return rc;
496         }
497         rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
498
499         midQ->midState = MID_REQUEST_SUBMITTED;
500 #ifdef CONFIG_CIFS_STATS2
501         atomic_inc(&ses->server->inSend);
502 #endif
503         rc = smb_send2(ses->server->ssocket, iov, n_vec,
504                       (struct sockaddr *) &(ses->server->addr.sockAddr));
505 #ifdef CONFIG_CIFS_STATS2
506         atomic_dec(&ses->server->inSend);
507         midQ->when_sent = jiffies;
508 #endif
509
510         up(&ses->server->tcpSem);
511         cifs_small_buf_release(in_buf);
512
513         if (rc < 0)
514                 goto out;
515
516         if (long_op == CIFS_STD_OP)
517                 timeout = 15 * HZ;
518         else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
519                 timeout = 180 * HZ;
520         else if (long_op == CIFS_LONG_OP)
521                 timeout = 45 * HZ; /* should be greater than
522                         servers oplock break timeout (about 43 seconds) */
523         else if (long_op == CIFS_ASYNC_OP)
524                 goto out;
525         else if (long_op == CIFS_BLOCKING_OP)
526                 timeout = 0x7FFFFFFF; /*  large, but not so large as to wrap */
527         else {
528                 cERROR(1, ("unknown timeout flag %d", long_op));
529                 rc = -EIO;
530                 goto out;
531         }
532
533         /* wait for 15 seconds or until woken up due to response arriving or
534            due to last connection to this server being unmounted */
535         if (signal_pending(current)) {
536                 /* if signal pending do not hold up user for full smb timeout
537                 but we still give response a chance to complete */
538                 timeout = 2 * HZ;
539         }
540
541         /* No user interrupts in wait - wreaks havoc with performance */
542         wait_for_response(ses, midQ, timeout, 10 * HZ);
543
544         spin_lock(&GlobalMid_Lock);
545         if (midQ->resp_buf) {
546                 spin_unlock(&GlobalMid_Lock);
547                 receive_len = midQ->resp_buf->smb_buf_length;
548         } else {
549                 cERROR(1, ("No response to cmd %d mid %d",
550                         midQ->command, midQ->mid));
551                 if (midQ->midState == MID_REQUEST_SUBMITTED) {
552                         if (ses->server->tcpStatus == CifsExiting)
553                                 rc = -EHOSTDOWN;
554                         else {
555                                 ses->server->tcpStatus = CifsNeedReconnect;
556                                 midQ->midState = MID_RETRY_NEEDED;
557                         }
558                 }
559
560                 if (rc != -EHOSTDOWN) {
561                         if (midQ->midState == MID_RETRY_NEEDED) {
562                                 rc = -EAGAIN;
563                                 cFYI(1, ("marking request for retry"));
564                         } else {
565                                 rc = -EIO;
566                         }
567                 }
568                 spin_unlock(&GlobalMid_Lock);
569                 DeleteMidQEntry(midQ);
570                 /* Update # of requests on wire to server */
571                 atomic_dec(&ses->server->inFlight);
572                 wake_up(&ses->server->request_q);
573                 return rc;
574         }
575
576         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
577                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
578                         receive_len, xid));
579                 rc = -EIO;
580         } else {                /* rcvd frame is ok */
581                 if (midQ->resp_buf &&
582                         (midQ->midState == MID_RESPONSE_RECEIVED)) {
583
584                         iov[0].iov_base = (char *)midQ->resp_buf;
585                         if (midQ->largeBuf)
586                                 *pRespBufType = CIFS_LARGE_BUFFER;
587                         else
588                                 *pRespBufType = CIFS_SMALL_BUFFER;
589                         iov[0].iov_len = receive_len + 4;
590
591                         dump_smb(midQ->resp_buf, 80);
592                         /* convert the length into a more usable form */
593                         if ((receive_len > 24) &&
594                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
595                                         SECMODE_SIGN_ENABLED))) {
596                                 rc = cifs_verify_signature(midQ->resp_buf,
597                                                 &ses->server->mac_signing_key,
598                                                 midQ->sequence_number+1);
599                                 if (rc) {
600                                         cERROR(1, ("Unexpected SMB signature"));
601                                         /* BB FIXME add code to kill session */
602                                 }
603                         }
604
605                         /* BB special case reconnect tid and uid here? */
606                         rc = map_smb_to_linux_error(midQ->resp_buf,
607                                                 flags & CIFS_LOG_ERROR);
608
609                         /* convert ByteCount if necessary */
610                         if (receive_len >= sizeof(struct smb_hdr) - 4
611                             /* do not count RFC1001 header */  +
612                             (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
613                                 BCC(midQ->resp_buf) =
614                                         le16_to_cpu(BCC_LE(midQ->resp_buf));
615                         if ((flags & CIFS_NO_RESP) == 0)
616                                 midQ->resp_buf = NULL;  /* mark it so buf will
617                                                            not be freed by
618                                                            DeleteMidQEntry */
619                 } else {
620                         rc = -EIO;
621                         cFYI(1, ("Bad MID state?"));
622                 }
623         }
624
625 out:
626         DeleteMidQEntry(midQ);
627         atomic_dec(&ses->server->inFlight);
628         wake_up(&ses->server->request_q);
629
630         return rc;
631 }
632
633 int
634 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
635             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
636             int *pbytes_returned, const int long_op)
637 {
638         int rc = 0;
639         unsigned int receive_len;
640         unsigned long timeout;
641         struct mid_q_entry *midQ;
642
643         if (ses == NULL) {
644                 cERROR(1, ("Null smb session"));
645                 return -EIO;
646         }
647         if (ses->server == NULL) {
648                 cERROR(1, ("Null tcp session"));
649                 return -EIO;
650         }
651
652         if (ses->server->tcpStatus == CifsExiting)
653                 return -ENOENT;
654
655         /* Ensure that we do not send more than 50 overlapping requests
656            to the same server. We may make this configurable later or
657            use ses->maxReq */
658
659         rc = wait_for_free_request(ses, long_op);
660         if (rc)
661                 return rc;
662
663         /* make sure that we sign in the same order that we send on this socket
664            and avoid races inside tcp sendmsg code that could cause corruption
665            of smb data */
666
667         down(&ses->server->tcpSem);
668
669         rc = allocate_mid(ses, in_buf, &midQ);
670         if (rc) {
671                 up(&ses->server->tcpSem);
672                 /* Update # of requests on wire to server */
673                 atomic_dec(&ses->server->inFlight);
674                 wake_up(&ses->server->request_q);
675                 return rc;
676         }
677
678         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
679                 cERROR(1, ("Illegal length, greater than maximum frame, %d",
680                         in_buf->smb_buf_length));
681                 DeleteMidQEntry(midQ);
682                 up(&ses->server->tcpSem);
683                 /* Update # of requests on wire to server */
684                 atomic_dec(&ses->server->inFlight);
685                 wake_up(&ses->server->request_q);
686                 return -EIO;
687         }
688
689         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
690
691         midQ->midState = MID_REQUEST_SUBMITTED;
692 #ifdef CONFIG_CIFS_STATS2
693         atomic_inc(&ses->server->inSend);
694 #endif
695         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
696                       (struct sockaddr *) &(ses->server->addr.sockAddr));
697 #ifdef CONFIG_CIFS_STATS2
698         atomic_dec(&ses->server->inSend);
699         midQ->when_sent = jiffies;
700 #endif
701         up(&ses->server->tcpSem);
702
703         if (rc < 0)
704                 goto out;
705
706         if (long_op == CIFS_STD_OP)
707                 timeout = 15 * HZ;
708         /* wait for 15 seconds or until woken up due to response arriving or
709            due to last connection to this server being unmounted */
710         else if (long_op == CIFS_ASYNC_OP)
711                 goto out;
712         else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
713                 timeout = 180 * HZ;
714         else if (long_op == CIFS_LONG_OP)
715                 timeout = 45 * HZ; /* should be greater than
716                         servers oplock break timeout (about 43 seconds) */
717         else if (long_op == CIFS_BLOCKING_OP)
718                 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
719         else {
720                 cERROR(1, ("unknown timeout flag %d", long_op));
721                 rc = -EIO;
722                 goto out;
723         }
724
725         if (signal_pending(current)) {
726                 /* if signal pending do not hold up user for full smb timeout
727                 but we still give response a chance to complete */
728                 timeout = 2 * HZ;
729         }
730
731         /* No user interrupts in wait - wreaks havoc with performance */
732         wait_for_response(ses, midQ, timeout, 10 * HZ);
733
734         spin_lock(&GlobalMid_Lock);
735         if (midQ->resp_buf) {
736                 spin_unlock(&GlobalMid_Lock);
737                 receive_len = midQ->resp_buf->smb_buf_length;
738         } else {
739                 cERROR(1, ("No response for cmd %d mid %d",
740                           midQ->command, midQ->mid));
741                 if (midQ->midState == MID_REQUEST_SUBMITTED) {
742                         if (ses->server->tcpStatus == CifsExiting)
743                                 rc = -EHOSTDOWN;
744                         else {
745                                 ses->server->tcpStatus = CifsNeedReconnect;
746                                 midQ->midState = MID_RETRY_NEEDED;
747                         }
748                 }
749
750                 if (rc != -EHOSTDOWN) {
751                         if (midQ->midState == MID_RETRY_NEEDED) {
752                                 rc = -EAGAIN;
753                                 cFYI(1, ("marking request for retry"));
754                         } else {
755                                 rc = -EIO;
756                         }
757                 }
758                 spin_unlock(&GlobalMid_Lock);
759                 DeleteMidQEntry(midQ);
760                 /* Update # of requests on wire to server */
761                 atomic_dec(&ses->server->inFlight);
762                 wake_up(&ses->server->request_q);
763                 return rc;
764         }
765
766         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
767                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
768                         receive_len, xid));
769                 rc = -EIO;
770         } else {                /* rcvd frame is ok */
771
772                 if (midQ->resp_buf && out_buf
773                     && (midQ->midState == MID_RESPONSE_RECEIVED)) {
774                         out_buf->smb_buf_length = receive_len;
775                         memcpy((char *)out_buf + 4,
776                                (char *)midQ->resp_buf + 4,
777                                receive_len);
778
779                         dump_smb(out_buf, 92);
780                         /* convert the length into a more usable form */
781                         if ((receive_len > 24) &&
782                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
783                                         SECMODE_SIGN_ENABLED))) {
784                                 rc = cifs_verify_signature(out_buf,
785                                                 &ses->server->mac_signing_key,
786                                                 midQ->sequence_number+1);
787                                 if (rc) {
788                                         cERROR(1, ("Unexpected SMB signature"));
789                                         /* BB FIXME add code to kill session */
790                                 }
791                         }
792
793                         *pbytes_returned = out_buf->smb_buf_length;
794
795                         /* BB special case reconnect tid and uid here? */
796                         rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
797
798                         /* convert ByteCount if necessary */
799                         if (receive_len >= sizeof(struct smb_hdr) - 4
800                             /* do not count RFC1001 header */  +
801                             (2 * out_buf->WordCount) + 2 /* bcc */ )
802                                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
803                 } else {
804                         rc = -EIO;
805                         cERROR(1, ("Bad MID state?"));
806                 }
807         }
808
809 out:
810         DeleteMidQEntry(midQ);
811         atomic_dec(&ses->server->inFlight);
812         wake_up(&ses->server->request_q);
813
814         return rc;
815 }
816
817 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
818
819 static int
820 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
821                 struct mid_q_entry *midQ)
822 {
823         int rc = 0;
824         struct cifsSesInfo *ses = tcon->ses;
825         __u16 mid = in_buf->Mid;
826
827         header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
828         in_buf->Mid = mid;
829         down(&ses->server->tcpSem);
830         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
831         if (rc) {
832                 up(&ses->server->tcpSem);
833                 return rc;
834         }
835         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
836               (struct sockaddr *) &(ses->server->addr.sockAddr));
837         up(&ses->server->tcpSem);
838         return rc;
839 }
840
841 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
842    blocking lock to return. */
843
844 static int
845 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
846                         struct smb_hdr *in_buf,
847                         struct smb_hdr *out_buf)
848 {
849         int bytes_returned;
850         struct cifsSesInfo *ses = tcon->ses;
851         LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
852
853         /* We just modify the current in_buf to change
854            the type of lock from LOCKING_ANDX_SHARED_LOCK
855            or LOCKING_ANDX_EXCLUSIVE_LOCK to
856            LOCKING_ANDX_CANCEL_LOCK. */
857
858         pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
859         pSMB->Timeout = 0;
860         pSMB->hdr.Mid = GetNextMid(ses->server);
861
862         return SendReceive(xid, ses, in_buf, out_buf,
863                         &bytes_returned, CIFS_STD_OP);
864 }
865
866 int
867 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
868             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
869             int *pbytes_returned)
870 {
871         int rc = 0;
872         int rstart = 0;
873         unsigned int receive_len;
874         struct mid_q_entry *midQ;
875         struct cifsSesInfo *ses;
876
877         if (tcon == NULL || tcon->ses == NULL) {
878                 cERROR(1, ("Null smb session"));
879                 return -EIO;
880         }
881         ses = tcon->ses;
882
883         if (ses->server == NULL) {
884                 cERROR(1, ("Null tcp session"));
885                 return -EIO;
886         }
887
888         if (ses->server->tcpStatus == CifsExiting)
889                 return -ENOENT;
890
891         /* Ensure that we do not send more than 50 overlapping requests
892            to the same server. We may make this configurable later or
893            use ses->maxReq */
894
895         rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
896         if (rc)
897                 return rc;
898
899         /* make sure that we sign in the same order that we send on this socket
900            and avoid races inside tcp sendmsg code that could cause corruption
901            of smb data */
902
903         down(&ses->server->tcpSem);
904
905         rc = allocate_mid(ses, in_buf, &midQ);
906         if (rc) {
907                 up(&ses->server->tcpSem);
908                 return rc;
909         }
910
911         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
912                 up(&ses->server->tcpSem);
913                 cERROR(1, ("Illegal length, greater than maximum frame, %d",
914                         in_buf->smb_buf_length));
915                 DeleteMidQEntry(midQ);
916                 return -EIO;
917         }
918
919         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
920
921         midQ->midState = MID_REQUEST_SUBMITTED;
922 #ifdef CONFIG_CIFS_STATS2
923         atomic_inc(&ses->server->inSend);
924 #endif
925         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
926                       (struct sockaddr *) &(ses->server->addr.sockAddr));
927 #ifdef CONFIG_CIFS_STATS2
928         atomic_dec(&ses->server->inSend);
929         midQ->when_sent = jiffies;
930 #endif
931         up(&ses->server->tcpSem);
932
933         if (rc < 0) {
934                 DeleteMidQEntry(midQ);
935                 return rc;
936         }
937
938         /* Wait for a reply - allow signals to interrupt. */
939         rc = wait_event_interruptible(ses->server->response_q,
940                 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
941                 ((ses->server->tcpStatus != CifsGood) &&
942                  (ses->server->tcpStatus != CifsNew)));
943
944         /* Were we interrupted by a signal ? */
945         if ((rc == -ERESTARTSYS) &&
946                 (midQ->midState == MID_REQUEST_SUBMITTED) &&
947                 ((ses->server->tcpStatus == CifsGood) ||
948                  (ses->server->tcpStatus == CifsNew))) {
949
950                 if (in_buf->Command == SMB_COM_TRANSACTION2) {
951                         /* POSIX lock. We send a NT_CANCEL SMB to cause the
952                            blocking lock to return. */
953
954                         rc = send_nt_cancel(tcon, in_buf, midQ);
955                         if (rc) {
956                                 DeleteMidQEntry(midQ);
957                                 return rc;
958                         }
959                 } else {
960                         /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
961                            to cause the blocking lock to return. */
962
963                         rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
964
965                         /* If we get -ENOLCK back the lock may have
966                            already been removed. Don't exit in this case. */
967                         if (rc && rc != -ENOLCK) {
968                                 DeleteMidQEntry(midQ);
969                                 return rc;
970                         }
971                 }
972
973                 /* Wait 5 seconds for the response. */
974                 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
975                         /* We got the response - restart system call. */
976                         rstart = 1;
977                 }
978         }
979
980         spin_lock(&GlobalMid_Lock);
981         if (midQ->resp_buf) {
982                 spin_unlock(&GlobalMid_Lock);
983                 receive_len = midQ->resp_buf->smb_buf_length;
984         } else {
985                 cERROR(1, ("No response for cmd %d mid %d",
986                           midQ->command, midQ->mid));
987                 if (midQ->midState == MID_REQUEST_SUBMITTED) {
988                         if (ses->server->tcpStatus == CifsExiting)
989                                 rc = -EHOSTDOWN;
990                         else {
991                                 ses->server->tcpStatus = CifsNeedReconnect;
992                                 midQ->midState = MID_RETRY_NEEDED;
993                         }
994                 }
995
996                 if (rc != -EHOSTDOWN) {
997                         if (midQ->midState == MID_RETRY_NEEDED) {
998                                 rc = -EAGAIN;
999                                 cFYI(1, ("marking request for retry"));
1000                         } else {
1001                                 rc = -EIO;
1002                         }
1003                 }
1004                 spin_unlock(&GlobalMid_Lock);
1005                 DeleteMidQEntry(midQ);
1006                 return rc;
1007         }
1008
1009         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1010                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
1011                         receive_len, xid));
1012                 rc = -EIO;
1013         } else {                /* rcvd frame is ok */
1014
1015                 if (midQ->resp_buf && out_buf
1016                     && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1017                         out_buf->smb_buf_length = receive_len;
1018                         memcpy((char *)out_buf + 4,
1019                                (char *)midQ->resp_buf + 4,
1020                                receive_len);
1021
1022                         dump_smb(out_buf, 92);
1023                         /* convert the length into a more usable form */
1024                         if ((receive_len > 24) &&
1025                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1026                                         SECMODE_SIGN_ENABLED))) {
1027                                 rc = cifs_verify_signature(out_buf,
1028                                                 &ses->server->mac_signing_key,
1029                                                 midQ->sequence_number+1);
1030                                 if (rc) {
1031                                         cERROR(1, ("Unexpected SMB signature"));
1032                                         /* BB FIXME add code to kill session */
1033                                 }
1034                         }
1035
1036                         *pbytes_returned = out_buf->smb_buf_length;
1037
1038                         /* BB special case reconnect tid and uid here? */
1039                         rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1040
1041                         /* convert ByteCount if necessary */
1042                         if (receive_len >= sizeof(struct smb_hdr) - 4
1043                             /* do not count RFC1001 header */  +
1044                             (2 * out_buf->WordCount) + 2 /* bcc */ )
1045                                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1046                 } else {
1047                         rc = -EIO;
1048                         cERROR(1, ("Bad MID state?"));
1049                 }
1050         }
1051         DeleteMidQEntry(midQ);
1052         if (rstart && rc == -EACCES)
1053                 return -ERESTARTSYS;
1054         return rc;
1055 }