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