]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/cifs/transport.c
c41c9c4f0a79418f630afe46a27525b051c32947
[karo-tx-linux.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/gfp.h>
26 #include <linux/wait.h>
27 #include <linux/net.h>
28 #include <linux/delay.h>
29 #include <asm/uaccess.h>
30 #include <asm/processor.h>
31 #include <linux/mempool.h>
32 #include "cifspdu.h"
33 #include "cifsglob.h"
34 #include "cifsproto.h"
35 #include "cifs_debug.h"
36
37 extern mempool_t *cifs_mid_poolp;
38
39 static struct mid_q_entry *
40 AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
41 {
42         struct mid_q_entry *temp;
43
44         if (server == NULL) {
45                 cERROR(1, "Null TCP session in AllocMidQEntry");
46                 return NULL;
47         }
48
49         temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
50         if (temp == NULL)
51                 return temp;
52         else {
53                 memset(temp, 0, sizeof(struct mid_q_entry));
54                 temp->mid = smb_buffer->Mid;    /* always LE */
55                 temp->pid = current->pid;
56                 temp->command = smb_buffer->Command;
57                 cFYI(1, "For smb_command %d", temp->command);
58         /*      do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
59                 /* when mid allocated can be before when sent */
60                 temp->when_alloc = jiffies;
61                 temp->tsk = current;
62         }
63
64         atomic_inc(&midCount);
65         temp->midState = MID_REQUEST_ALLOCATED;
66         return temp;
67 }
68
69 static void
70 DeleteMidQEntry(struct mid_q_entry *midEntry)
71 {
72 #ifdef CONFIG_CIFS_STATS2
73         unsigned long now;
74 #endif
75         midEntry->midState = MID_FREE;
76         atomic_dec(&midCount);
77         if (midEntry->largeBuf)
78                 cifs_buf_release(midEntry->resp_buf);
79         else
80                 cifs_small_buf_release(midEntry->resp_buf);
81 #ifdef CONFIG_CIFS_STATS2
82         now = jiffies;
83         /* commands taking longer than one second are indications that
84            something is wrong, unless it is quite a slow link or server */
85         if ((now - midEntry->when_alloc) > HZ) {
86                 if ((cifsFYI & CIFS_TIMER) &&
87                    (midEntry->command != SMB_COM_LOCKING_ANDX)) {
88                         printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
89                                midEntry->command, midEntry->mid);
90                         printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
91                                now - midEntry->when_alloc,
92                                now - midEntry->when_sent,
93                                now - midEntry->when_received);
94                 }
95         }
96 #endif
97         mempool_free(midEntry, cifs_mid_poolp);
98 }
99
100 static void
101 delete_mid(struct mid_q_entry *mid)
102 {
103         spin_lock(&GlobalMid_Lock);
104         list_del(&mid->qhead);
105         spin_unlock(&GlobalMid_Lock);
106
107         DeleteMidQEntry(mid);
108 }
109
110 static int
111 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
112 {
113         int rc = 0;
114         int i = 0;
115         struct msghdr smb_msg;
116         struct smb_hdr *smb_buffer = iov[0].iov_base;
117         unsigned int len = iov[0].iov_len;
118         unsigned int total_len;
119         int first_vec = 0;
120         unsigned int smb_buf_length = smb_buffer->smb_buf_length;
121         struct socket *ssocket = server->ssocket;
122
123         if (ssocket == NULL)
124                 return -ENOTSOCK; /* BB eventually add reconnect code here */
125
126         smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
127         smb_msg.msg_namelen = sizeof(struct sockaddr);
128         smb_msg.msg_control = NULL;
129         smb_msg.msg_controllen = 0;
130         if (server->noblocksnd)
131                 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
132         else
133                 smb_msg.msg_flags = MSG_NOSIGNAL;
134
135         /* smb header is converted in header_assemble. bcc and rest of SMB word
136            area, and byte area if necessary, is converted to littleendian in
137            cifssmb.c and RFC1001 len is converted to bigendian in smb_send
138            Flags2 is converted in SendReceive */
139
140
141         total_len = 0;
142         for (i = 0; i < n_vec; i++)
143                 total_len += iov[i].iov_len;
144
145         smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
146         cFYI(1, "Sending smb:  total_len %d", total_len);
147         dump_smb(smb_buffer, len);
148
149         i = 0;
150         while (total_len) {
151                 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
152                                     n_vec - first_vec, total_len);
153                 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
154                         i++;
155                         /* if blocking send we try 3 times, since each can block
156                            for 5 seconds. For nonblocking  we have to try more
157                            but wait increasing amounts of time allowing time for
158                            socket to clear.  The overall time we wait in either
159                            case to send on the socket is about 15 seconds.
160                            Similarly we wait for 15 seconds for
161                            a response from the server in SendReceive[2]
162                            for the server to send a response back for
163                            most types of requests (except SMB Write
164                            past end of file which can be slow, and
165                            blocking lock operations). NFS waits slightly longer
166                            than CIFS, but this can make it take longer for
167                            nonresponsive servers to be detected and 15 seconds
168                            is more than enough time for modern networks to
169                            send a packet.  In most cases if we fail to send
170                            after the retries we will kill the socket and
171                            reconnect which may clear the network problem.
172                         */
173                         if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
174                                 cERROR(1, "sends on sock %p stuck for 15 seconds",
175                                     ssocket);
176                                 rc = -EAGAIN;
177                                 break;
178                         }
179                         msleep(1 << i);
180                         continue;
181                 }
182                 if (rc < 0)
183                         break;
184
185                 if (rc == total_len) {
186                         total_len = 0;
187                         break;
188                 } else if (rc > total_len) {
189                         cERROR(1, "sent %d requested %d", rc, total_len);
190                         break;
191                 }
192                 if (rc == 0) {
193                         /* should never happen, letting socket clear before
194                            retrying is our only obvious option here */
195                         cERROR(1, "tcp sent no data");
196                         msleep(500);
197                         continue;
198                 }
199                 total_len -= rc;
200                 /* the line below resets i */
201                 for (i = first_vec; i < n_vec; i++) {
202                         if (iov[i].iov_len) {
203                                 if (rc > iov[i].iov_len) {
204                                         rc -= iov[i].iov_len;
205                                         iov[i].iov_len = 0;
206                                 } else {
207                                         iov[i].iov_base += rc;
208                                         iov[i].iov_len -= rc;
209                                         first_vec = i;
210                                         break;
211                                 }
212                         }
213                 }
214                 i = 0; /* in case we get ENOSPC on the next send */
215         }
216
217         if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
218                 cFYI(1, "partial send (%d remaining), terminating session",
219                         total_len);
220                 /* If we have only sent part of an SMB then the next SMB
221                    could be taken as the remainder of this one.  We need
222                    to kill the socket so the server throws away the partial
223                    SMB */
224                 server->tcpStatus = CifsNeedReconnect;
225         }
226
227         if (rc < 0) {
228                 cERROR(1, "Error %d sending data on socket to server", rc);
229         } else
230                 rc = 0;
231
232         /* Don't want to modify the buffer as a
233            side effect of this call. */
234         smb_buffer->smb_buf_length = smb_buf_length;
235
236         return rc;
237 }
238
239 int
240 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
241          unsigned int smb_buf_length)
242 {
243         struct kvec iov;
244
245         iov.iov_base = smb_buffer;
246         iov.iov_len = smb_buf_length + 4;
247
248         return smb_sendv(server, &iov, 1);
249 }
250
251 static int wait_for_free_request(struct TCP_Server_Info *server,
252                                  const int long_op)
253 {
254         if (long_op == CIFS_ASYNC_OP) {
255                 /* oplock breaks must not be held up */
256                 atomic_inc(&server->inFlight);
257                 return 0;
258         }
259
260         spin_lock(&GlobalMid_Lock);
261         while (1) {
262                 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
263                         spin_unlock(&GlobalMid_Lock);
264 #ifdef CONFIG_CIFS_STATS2
265                         atomic_inc(&server->num_waiters);
266 #endif
267                         wait_event(server->request_q,
268                                    atomic_read(&server->inFlight)
269                                      < cifs_max_pending);
270 #ifdef CONFIG_CIFS_STATS2
271                         atomic_dec(&server->num_waiters);
272 #endif
273                         spin_lock(&GlobalMid_Lock);
274                 } else {
275                         if (server->tcpStatus == CifsExiting) {
276                                 spin_unlock(&GlobalMid_Lock);
277                                 return -ENOENT;
278                         }
279
280                         /* can not count locking commands against total
281                            as they are allowed to block on server */
282
283                         /* update # of requests on the wire to server */
284                         if (long_op != CIFS_BLOCKING_OP)
285                                 atomic_inc(&server->inFlight);
286                         spin_unlock(&GlobalMid_Lock);
287                         break;
288                 }
289         }
290         return 0;
291 }
292
293 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
294                         struct mid_q_entry **ppmidQ)
295 {
296         if (ses->server->tcpStatus == CifsExiting) {
297                 return -ENOENT;
298         }
299
300         if (ses->server->tcpStatus == CifsNeedReconnect) {
301                 cFYI(1, "tcp session dead - return to caller to retry");
302                 return -EAGAIN;
303         }
304
305         if (ses->status != CifsGood) {
306                 /* check if SMB session is bad because we are setting it up */
307                 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
308                         (in_buf->Command != SMB_COM_NEGOTIATE))
309                         return -EAGAIN;
310                 /* else ok - we are setting up session */
311         }
312         *ppmidQ = AllocMidQEntry(in_buf, ses->server);
313         if (*ppmidQ == NULL)
314                 return -ENOMEM;
315         spin_lock(&GlobalMid_Lock);
316         list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
317         spin_unlock(&GlobalMid_Lock);
318         return 0;
319 }
320
321 static int
322 wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
323 {
324         int error;
325
326         error = wait_event_killable(server->response_q,
327                                     midQ->midState != MID_REQUEST_SUBMITTED);
328         if (error < 0)
329                 return -ERESTARTSYS;
330
331         return 0;
332 }
333
334
335 /*
336  *
337  * Send an SMB Request.  No response info (other than return code)
338  * needs to be parsed.
339  *
340  * flags indicate the type of request buffer and how long to wait
341  * and whether to log NT STATUS code (error) before mapping it to POSIX error
342  *
343  */
344 int
345 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
346                 struct smb_hdr *in_buf, int flags)
347 {
348         int rc;
349         struct kvec iov[1];
350         int resp_buf_type;
351
352         iov[0].iov_base = (char *)in_buf;
353         iov[0].iov_len = in_buf->smb_buf_length + 4;
354         flags |= CIFS_NO_RESP;
355         rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
356         cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
357
358         return rc;
359 }
360
361 static int
362 sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
363 {
364         int rc = 0;
365
366         spin_lock(&GlobalMid_Lock);
367
368         if (mid->resp_buf) {
369                 spin_unlock(&GlobalMid_Lock);
370                 return rc;
371         }
372
373         cERROR(1, "No response to cmd %d mid %d", mid->command, mid->mid);
374         if (mid->midState == MID_REQUEST_SUBMITTED) {
375                 if (server->tcpStatus == CifsExiting)
376                         rc = -EHOSTDOWN;
377                 else {
378                         server->tcpStatus = CifsNeedReconnect;
379                         mid->midState = MID_RETRY_NEEDED;
380                 }
381         }
382
383         if (rc != -EHOSTDOWN) {
384                 if (mid->midState == MID_RETRY_NEEDED) {
385                         rc = -EAGAIN;
386                         cFYI(1, "marking request for retry");
387                 } else {
388                         rc = -EIO;
389                 }
390         }
391         spin_unlock(&GlobalMid_Lock);
392
393         delete_mid(mid);
394         return rc;
395 }
396
397 int
398 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
399              struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
400              const int flags)
401 {
402         int rc = 0;
403         int long_op;
404         unsigned int receive_len;
405         struct mid_q_entry *midQ;
406         struct smb_hdr *in_buf = iov[0].iov_base;
407
408         long_op = flags & CIFS_TIMEOUT_MASK;
409
410         *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
411
412         if ((ses == NULL) || (ses->server == NULL)) {
413                 cifs_small_buf_release(in_buf);
414                 cERROR(1, "Null session");
415                 return -EIO;
416         }
417
418         if (ses->server->tcpStatus == CifsExiting) {
419                 cifs_small_buf_release(in_buf);
420                 return -ENOENT;
421         }
422
423         /* Ensure that we do not send more than 50 overlapping requests
424            to the same server. We may make this configurable later or
425            use ses->maxReq */
426
427         rc = wait_for_free_request(ses->server, long_op);
428         if (rc) {
429                 cifs_small_buf_release(in_buf);
430                 return rc;
431         }
432
433         /* make sure that we sign in the same order that we send on this socket
434            and avoid races inside tcp sendmsg code that could cause corruption
435            of smb data */
436
437         mutex_lock(&ses->server->srv_mutex);
438
439         rc = allocate_mid(ses, in_buf, &midQ);
440         if (rc) {
441                 mutex_unlock(&ses->server->srv_mutex);
442                 cifs_small_buf_release(in_buf);
443                 /* Update # of requests on wire to server */
444                 atomic_dec(&ses->server->inFlight);
445                 wake_up(&ses->server->request_q);
446                 return rc;
447         }
448         rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
449         if (rc) {
450                 mutex_unlock(&ses->server->srv_mutex);
451                 cifs_small_buf_release(in_buf);
452                 goto out;
453         }
454
455         midQ->midState = MID_REQUEST_SUBMITTED;
456 #ifdef CONFIG_CIFS_STATS2
457         atomic_inc(&ses->server->inSend);
458 #endif
459         rc = smb_sendv(ses->server, iov, n_vec);
460 #ifdef CONFIG_CIFS_STATS2
461         atomic_dec(&ses->server->inSend);
462         midQ->when_sent = jiffies;
463 #endif
464
465         mutex_unlock(&ses->server->srv_mutex);
466         cifs_small_buf_release(in_buf);
467
468         if (rc < 0)
469                 goto out;
470
471         if (long_op == CIFS_ASYNC_OP)
472                 goto out;
473
474         rc = wait_for_response(ses->server, midQ);
475         if (rc != 0)
476                 goto out;
477
478         rc = sync_mid_result(midQ, ses->server);
479         if (rc != 0) {
480                 atomic_dec(&ses->server->inFlight);
481                 wake_up(&ses->server->request_q);
482                 return rc;
483         }
484
485         receive_len = midQ->resp_buf->smb_buf_length;
486
487         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
488                 cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
489                         receive_len, xid);
490                 rc = -EIO;
491                 goto out;
492         }
493
494         /* rcvd frame is ok */
495
496         if (midQ->resp_buf &&
497             (midQ->midState == MID_RESPONSE_RECEIVED)) {
498
499                 iov[0].iov_base = (char *)midQ->resp_buf;
500                 if (midQ->largeBuf)
501                         *pRespBufType = CIFS_LARGE_BUFFER;
502                 else
503                         *pRespBufType = CIFS_SMALL_BUFFER;
504                 iov[0].iov_len = receive_len + 4;
505
506                 dump_smb(midQ->resp_buf, 80);
507                 /* convert the length into a more usable form */
508                 if ((receive_len > 24) &&
509                     (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
510                                              SECMODE_SIGN_ENABLED))) {
511                         rc = cifs_verify_signature(midQ->resp_buf,
512                                                 ses->server,
513                                                 midQ->sequence_number+1);
514                         if (rc) {
515                                 cERROR(1, "Unexpected SMB signature");
516                                 /* BB FIXME add code to kill session */
517                         }
518                 }
519
520                 /* BB special case reconnect tid and uid here? */
521                 rc = map_smb_to_linux_error(midQ->resp_buf,
522                                             flags & CIFS_LOG_ERROR);
523
524                 /* convert ByteCount if necessary */
525                 if (receive_len >= sizeof(struct smb_hdr) - 4
526                     /* do not count RFC1001 header */  +
527                     (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
528                         BCC(midQ->resp_buf) =
529                                 le16_to_cpu(BCC_LE(midQ->resp_buf));
530                 if ((flags & CIFS_NO_RESP) == 0)
531                         midQ->resp_buf = NULL;  /* mark it so buf will
532                                                    not be freed by
533                                                    delete_mid */
534         } else {
535                 rc = -EIO;
536                 cFYI(1, "Bad MID state?");
537         }
538
539 out:
540         delete_mid(midQ);
541         atomic_dec(&ses->server->inFlight);
542         wake_up(&ses->server->request_q);
543
544         return rc;
545 }
546
547 int
548 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
549             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
550             int *pbytes_returned, const int long_op)
551 {
552         int rc = 0;
553         unsigned int receive_len;
554         struct mid_q_entry *midQ;
555
556         if (ses == NULL) {
557                 cERROR(1, "Null smb session");
558                 return -EIO;
559         }
560         if (ses->server == NULL) {
561                 cERROR(1, "Null tcp session");
562                 return -EIO;
563         }
564
565         if (ses->server->tcpStatus == CifsExiting)
566                 return -ENOENT;
567
568         /* Ensure that we do not send more than 50 overlapping requests
569            to the same server. We may make this configurable later or
570            use ses->maxReq */
571
572         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
573                 cERROR(1, "Illegal length, greater than maximum frame, %d",
574                            in_buf->smb_buf_length);
575                 return -EIO;
576         }
577
578         rc = wait_for_free_request(ses->server, long_op);
579         if (rc)
580                 return rc;
581
582         /* make sure that we sign in the same order that we send on this socket
583            and avoid races inside tcp sendmsg code that could cause corruption
584            of smb data */
585
586         mutex_lock(&ses->server->srv_mutex);
587
588         rc = allocate_mid(ses, in_buf, &midQ);
589         if (rc) {
590                 mutex_unlock(&ses->server->srv_mutex);
591                 /* Update # of requests on wire to server */
592                 atomic_dec(&ses->server->inFlight);
593                 wake_up(&ses->server->request_q);
594                 return rc;
595         }
596
597         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
598         if (rc) {
599                 mutex_unlock(&ses->server->srv_mutex);
600                 goto out;
601         }
602
603         midQ->midState = MID_REQUEST_SUBMITTED;
604 #ifdef CONFIG_CIFS_STATS2
605         atomic_inc(&ses->server->inSend);
606 #endif
607         rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
608 #ifdef CONFIG_CIFS_STATS2
609         atomic_dec(&ses->server->inSend);
610         midQ->when_sent = jiffies;
611 #endif
612         mutex_unlock(&ses->server->srv_mutex);
613
614         if (rc < 0)
615                 goto out;
616
617         if (long_op == CIFS_ASYNC_OP)
618                 goto out;
619
620         rc = wait_for_response(ses->server, midQ);
621         if (rc != 0)
622                 goto out;
623
624         rc = sync_mid_result(midQ, ses->server);
625         if (rc != 0) {
626                 atomic_dec(&ses->server->inFlight);
627                 wake_up(&ses->server->request_q);
628                 return rc;
629         }
630
631         receive_len = midQ->resp_buf->smb_buf_length;
632
633         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
634                 cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
635                         receive_len, xid);
636                 rc = -EIO;
637                 goto out;
638         }
639
640         /* rcvd frame is ok */
641
642         if (midQ->resp_buf && out_buf
643             && (midQ->midState == MID_RESPONSE_RECEIVED)) {
644                 out_buf->smb_buf_length = receive_len;
645                 memcpy((char *)out_buf + 4,
646                        (char *)midQ->resp_buf + 4,
647                        receive_len);
648
649                 dump_smb(out_buf, 92);
650                 /* convert the length into a more usable form */
651                 if ((receive_len > 24) &&
652                     (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
653                                              SECMODE_SIGN_ENABLED))) {
654                         rc = cifs_verify_signature(out_buf,
655                                                 ses->server,
656                                                 midQ->sequence_number+1);
657                         if (rc) {
658                                 cERROR(1, "Unexpected SMB signature");
659                                 /* BB FIXME add code to kill session */
660                         }
661                 }
662
663                 *pbytes_returned = out_buf->smb_buf_length;
664
665                 /* BB special case reconnect tid and uid here? */
666                 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
667
668                 /* convert ByteCount if necessary */
669                 if (receive_len >= sizeof(struct smb_hdr) - 4
670                     /* do not count RFC1001 header */  +
671                     (2 * out_buf->WordCount) + 2 /* bcc */ )
672                         BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
673         } else {
674                 rc = -EIO;
675                 cERROR(1, "Bad MID state?");
676         }
677
678 out:
679         delete_mid(midQ);
680         atomic_dec(&ses->server->inFlight);
681         wake_up(&ses->server->request_q);
682
683         return rc;
684 }
685
686 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
687
688 static int
689 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
690                 struct mid_q_entry *midQ)
691 {
692         int rc = 0;
693         struct cifsSesInfo *ses = tcon->ses;
694         __u16 mid = in_buf->Mid;
695
696         header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
697         in_buf->Mid = mid;
698         mutex_lock(&ses->server->srv_mutex);
699         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
700         if (rc) {
701                 mutex_unlock(&ses->server->srv_mutex);
702                 return rc;
703         }
704         rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
705         mutex_unlock(&ses->server->srv_mutex);
706         return rc;
707 }
708
709 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
710    blocking lock to return. */
711
712 static int
713 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
714                         struct smb_hdr *in_buf,
715                         struct smb_hdr *out_buf)
716 {
717         int bytes_returned;
718         struct cifsSesInfo *ses = tcon->ses;
719         LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
720
721         /* We just modify the current in_buf to change
722            the type of lock from LOCKING_ANDX_SHARED_LOCK
723            or LOCKING_ANDX_EXCLUSIVE_LOCK to
724            LOCKING_ANDX_CANCEL_LOCK. */
725
726         pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
727         pSMB->Timeout = 0;
728         pSMB->hdr.Mid = GetNextMid(ses->server);
729
730         return SendReceive(xid, ses, in_buf, out_buf,
731                         &bytes_returned, CIFS_STD_OP);
732 }
733
734 int
735 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
736             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
737             int *pbytes_returned)
738 {
739         int rc = 0;
740         int rstart = 0;
741         unsigned int receive_len;
742         struct mid_q_entry *midQ;
743         struct cifsSesInfo *ses;
744
745         if (tcon == NULL || tcon->ses == NULL) {
746                 cERROR(1, "Null smb session");
747                 return -EIO;
748         }
749         ses = tcon->ses;
750
751         if (ses->server == NULL) {
752                 cERROR(1, "Null tcp session");
753                 return -EIO;
754         }
755
756         if (ses->server->tcpStatus == CifsExiting)
757                 return -ENOENT;
758
759         /* Ensure that we do not send more than 50 overlapping requests
760            to the same server. We may make this configurable later or
761            use ses->maxReq */
762
763         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
764                 cERROR(1, "Illegal length, greater than maximum frame, %d",
765                            in_buf->smb_buf_length);
766                 return -EIO;
767         }
768
769         rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
770         if (rc)
771                 return rc;
772
773         /* make sure that we sign in the same order that we send on this socket
774            and avoid races inside tcp sendmsg code that could cause corruption
775            of smb data */
776
777         mutex_lock(&ses->server->srv_mutex);
778
779         rc = allocate_mid(ses, in_buf, &midQ);
780         if (rc) {
781                 mutex_unlock(&ses->server->srv_mutex);
782                 return rc;
783         }
784
785         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
786         if (rc) {
787                 delete_mid(midQ);
788                 mutex_unlock(&ses->server->srv_mutex);
789                 return rc;
790         }
791
792         midQ->midState = MID_REQUEST_SUBMITTED;
793 #ifdef CONFIG_CIFS_STATS2
794         atomic_inc(&ses->server->inSend);
795 #endif
796         rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
797 #ifdef CONFIG_CIFS_STATS2
798         atomic_dec(&ses->server->inSend);
799         midQ->when_sent = jiffies;
800 #endif
801         mutex_unlock(&ses->server->srv_mutex);
802
803         if (rc < 0) {
804                 delete_mid(midQ);
805                 return rc;
806         }
807
808         /* Wait for a reply - allow signals to interrupt. */
809         rc = wait_event_interruptible(ses->server->response_q,
810                 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
811                 ((ses->server->tcpStatus != CifsGood) &&
812                  (ses->server->tcpStatus != CifsNew)));
813
814         /* Were we interrupted by a signal ? */
815         if ((rc == -ERESTARTSYS) &&
816                 (midQ->midState == MID_REQUEST_SUBMITTED) &&
817                 ((ses->server->tcpStatus == CifsGood) ||
818                  (ses->server->tcpStatus == CifsNew))) {
819
820                 if (in_buf->Command == SMB_COM_TRANSACTION2) {
821                         /* POSIX lock. We send a NT_CANCEL SMB to cause the
822                            blocking lock to return. */
823
824                         rc = send_nt_cancel(tcon, in_buf, midQ);
825                         if (rc) {
826                                 delete_mid(midQ);
827                                 return rc;
828                         }
829                 } else {
830                         /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
831                            to cause the blocking lock to return. */
832
833                         rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
834
835                         /* If we get -ENOLCK back the lock may have
836                            already been removed. Don't exit in this case. */
837                         if (rc && rc != -ENOLCK) {
838                                 delete_mid(midQ);
839                                 return rc;
840                         }
841                 }
842
843                 if (wait_for_response(ses->server, midQ) == 0) {
844                         /* We got the response - restart system call. */
845                         rstart = 1;
846                 }
847         }
848
849         rc = sync_mid_result(midQ, ses->server);
850         if (rc != 0)
851                 return rc;
852
853         receive_len = midQ->resp_buf->smb_buf_length;
854         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
855                 cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
856                         receive_len, xid);
857                 rc = -EIO;
858                 goto out;
859         }
860
861         /* rcvd frame is ok */
862
863         if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
864                 rc = -EIO;
865                 cERROR(1, "Bad MID state?");
866                 goto out;
867         }
868
869         out_buf->smb_buf_length = receive_len;
870         memcpy((char *)out_buf + 4,
871                (char *)midQ->resp_buf + 4,
872                receive_len);
873
874         dump_smb(out_buf, 92);
875         /* convert the length into a more usable form */
876         if ((receive_len > 24) &&
877             (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
878                                      SECMODE_SIGN_ENABLED))) {
879                 rc = cifs_verify_signature(out_buf,
880                                            ses->server,
881                                            midQ->sequence_number+1);
882                 if (rc) {
883                         cERROR(1, "Unexpected SMB signature");
884                         /* BB FIXME add code to kill session */
885                 }
886         }
887
888         *pbytes_returned = out_buf->smb_buf_length;
889
890         /* BB special case reconnect tid and uid here? */
891         rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
892
893         /* convert ByteCount if necessary */
894         if (receive_len >= sizeof(struct smb_hdr) - 4
895             /* do not count RFC1001 header */  +
896             (2 * out_buf->WordCount) + 2 /* bcc */ )
897                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
898
899 out:
900         delete_mid(midQ);
901         if (rstart && rc == -EACCES)
902                 return -ERESTARTSYS;
903         return rc;
904 }