]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/cifs/transport.c
cifs: clean up sync_mid_result
[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         cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
367                 mid->mid, mid->midState);
368
369         spin_lock(&GlobalMid_Lock);
370         switch (mid->midState) {
371         case MID_RESPONSE_RECEIVED:
372                 spin_unlock(&GlobalMid_Lock);
373                 return rc;
374         case MID_REQUEST_SUBMITTED:
375                 /* socket is going down, reject all calls */
376                 if (server->tcpStatus == CifsExiting) {
377                         cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
378                                __func__, mid->mid, mid->command, mid->midState);
379                         rc = -EHOSTDOWN;
380                         break;
381                 }
382         case MID_RETRY_NEEDED:
383                 rc = -EAGAIN;
384                 break;
385         default:
386                 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
387                         mid->mid, mid->midState);
388                 rc = -EIO;
389         }
390         spin_unlock(&GlobalMid_Lock);
391
392         delete_mid(mid);
393         return rc;
394 }
395
396 int
397 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
398              struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
399              const int flags)
400 {
401         int rc = 0;
402         int long_op;
403         unsigned int receive_len;
404         struct mid_q_entry *midQ;
405         struct smb_hdr *in_buf = iov[0].iov_base;
406
407         long_op = flags & CIFS_TIMEOUT_MASK;
408
409         *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
410
411         if ((ses == NULL) || (ses->server == NULL)) {
412                 cifs_small_buf_release(in_buf);
413                 cERROR(1, "Null session");
414                 return -EIO;
415         }
416
417         if (ses->server->tcpStatus == CifsExiting) {
418                 cifs_small_buf_release(in_buf);
419                 return -ENOENT;
420         }
421
422         /* Ensure that we do not send more than 50 overlapping requests
423            to the same server. We may make this configurable later or
424            use ses->maxReq */
425
426         rc = wait_for_free_request(ses->server, long_op);
427         if (rc) {
428                 cifs_small_buf_release(in_buf);
429                 return rc;
430         }
431
432         /* make sure that we sign in the same order that we send on this socket
433            and avoid races inside tcp sendmsg code that could cause corruption
434            of smb data */
435
436         mutex_lock(&ses->server->srv_mutex);
437
438         rc = allocate_mid(ses, in_buf, &midQ);
439         if (rc) {
440                 mutex_unlock(&ses->server->srv_mutex);
441                 cifs_small_buf_release(in_buf);
442                 /* Update # of requests on wire to server */
443                 atomic_dec(&ses->server->inFlight);
444                 wake_up(&ses->server->request_q);
445                 return rc;
446         }
447         rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
448         if (rc) {
449                 mutex_unlock(&ses->server->srv_mutex);
450                 cifs_small_buf_release(in_buf);
451                 goto out;
452         }
453
454         midQ->midState = MID_REQUEST_SUBMITTED;
455 #ifdef CONFIG_CIFS_STATS2
456         atomic_inc(&ses->server->inSend);
457 #endif
458         rc = smb_sendv(ses->server, iov, n_vec);
459 #ifdef CONFIG_CIFS_STATS2
460         atomic_dec(&ses->server->inSend);
461         midQ->when_sent = jiffies;
462 #endif
463
464         mutex_unlock(&ses->server->srv_mutex);
465         cifs_small_buf_release(in_buf);
466
467         if (rc < 0)
468                 goto out;
469
470         if (long_op == CIFS_ASYNC_OP)
471                 goto out;
472
473         rc = wait_for_response(ses->server, midQ);
474         if (rc != 0)
475                 goto out;
476
477         rc = sync_mid_result(midQ, ses->server);
478         if (rc != 0) {
479                 atomic_dec(&ses->server->inFlight);
480                 wake_up(&ses->server->request_q);
481                 return rc;
482         }
483
484         receive_len = midQ->resp_buf->smb_buf_length;
485
486         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
487                 cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
488                         receive_len, xid);
489                 rc = -EIO;
490                 goto out;
491         }
492
493         /* rcvd frame is ok */
494
495         if (midQ->resp_buf &&
496             (midQ->midState == MID_RESPONSE_RECEIVED)) {
497
498                 iov[0].iov_base = (char *)midQ->resp_buf;
499                 if (midQ->largeBuf)
500                         *pRespBufType = CIFS_LARGE_BUFFER;
501                 else
502                         *pRespBufType = CIFS_SMALL_BUFFER;
503                 iov[0].iov_len = receive_len + 4;
504
505                 dump_smb(midQ->resp_buf, 80);
506                 /* convert the length into a more usable form */
507                 if ((receive_len > 24) &&
508                     (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
509                                              SECMODE_SIGN_ENABLED))) {
510                         rc = cifs_verify_signature(midQ->resp_buf,
511                                                 ses->server,
512                                                 midQ->sequence_number+1);
513                         if (rc) {
514                                 cERROR(1, "Unexpected SMB signature");
515                                 /* BB FIXME add code to kill session */
516                         }
517                 }
518
519                 /* BB special case reconnect tid and uid here? */
520                 rc = map_smb_to_linux_error(midQ->resp_buf,
521                                             flags & CIFS_LOG_ERROR);
522
523                 /* convert ByteCount if necessary */
524                 if (receive_len >= sizeof(struct smb_hdr) - 4
525                     /* do not count RFC1001 header */  +
526                     (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
527                         BCC(midQ->resp_buf) =
528                                 le16_to_cpu(BCC_LE(midQ->resp_buf));
529                 if ((flags & CIFS_NO_RESP) == 0)
530                         midQ->resp_buf = NULL;  /* mark it so buf will
531                                                    not be freed by
532                                                    delete_mid */
533         } else {
534                 rc = -EIO;
535                 cFYI(1, "Bad MID state?");
536         }
537
538 out:
539         delete_mid(midQ);
540         atomic_dec(&ses->server->inFlight);
541         wake_up(&ses->server->request_q);
542
543         return rc;
544 }
545
546 int
547 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
548             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
549             int *pbytes_returned, const int long_op)
550 {
551         int rc = 0;
552         unsigned int receive_len;
553         struct mid_q_entry *midQ;
554
555         if (ses == NULL) {
556                 cERROR(1, "Null smb session");
557                 return -EIO;
558         }
559         if (ses->server == NULL) {
560                 cERROR(1, "Null tcp session");
561                 return -EIO;
562         }
563
564         if (ses->server->tcpStatus == CifsExiting)
565                 return -ENOENT;
566
567         /* Ensure that we do not send more than 50 overlapping requests
568            to the same server. We may make this configurable later or
569            use ses->maxReq */
570
571         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
572                 cERROR(1, "Illegal length, greater than maximum frame, %d",
573                            in_buf->smb_buf_length);
574                 return -EIO;
575         }
576
577         rc = wait_for_free_request(ses->server, long_op);
578         if (rc)
579                 return rc;
580
581         /* make sure that we sign in the same order that we send on this socket
582            and avoid races inside tcp sendmsg code that could cause corruption
583            of smb data */
584
585         mutex_lock(&ses->server->srv_mutex);
586
587         rc = allocate_mid(ses, in_buf, &midQ);
588         if (rc) {
589                 mutex_unlock(&ses->server->srv_mutex);
590                 /* Update # of requests on wire to server */
591                 atomic_dec(&ses->server->inFlight);
592                 wake_up(&ses->server->request_q);
593                 return rc;
594         }
595
596         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
597         if (rc) {
598                 mutex_unlock(&ses->server->srv_mutex);
599                 goto out;
600         }
601
602         midQ->midState = MID_REQUEST_SUBMITTED;
603 #ifdef CONFIG_CIFS_STATS2
604         atomic_inc(&ses->server->inSend);
605 #endif
606         rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
607 #ifdef CONFIG_CIFS_STATS2
608         atomic_dec(&ses->server->inSend);
609         midQ->when_sent = jiffies;
610 #endif
611         mutex_unlock(&ses->server->srv_mutex);
612
613         if (rc < 0)
614                 goto out;
615
616         if (long_op == CIFS_ASYNC_OP)
617                 goto out;
618
619         rc = wait_for_response(ses->server, midQ);
620         if (rc != 0)
621                 goto out;
622
623         rc = sync_mid_result(midQ, ses->server);
624         if (rc != 0) {
625                 atomic_dec(&ses->server->inFlight);
626                 wake_up(&ses->server->request_q);
627                 return rc;
628         }
629
630         receive_len = midQ->resp_buf->smb_buf_length;
631
632         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
633                 cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
634                         receive_len, xid);
635                 rc = -EIO;
636                 goto out;
637         }
638
639         /* rcvd frame is ok */
640
641         if (midQ->resp_buf && out_buf
642             && (midQ->midState == MID_RESPONSE_RECEIVED)) {
643                 out_buf->smb_buf_length = receive_len;
644                 memcpy((char *)out_buf + 4,
645                        (char *)midQ->resp_buf + 4,
646                        receive_len);
647
648                 dump_smb(out_buf, 92);
649                 /* convert the length into a more usable form */
650                 if ((receive_len > 24) &&
651                     (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
652                                              SECMODE_SIGN_ENABLED))) {
653                         rc = cifs_verify_signature(out_buf,
654                                                 ses->server,
655                                                 midQ->sequence_number+1);
656                         if (rc) {
657                                 cERROR(1, "Unexpected SMB signature");
658                                 /* BB FIXME add code to kill session */
659                         }
660                 }
661
662                 *pbytes_returned = out_buf->smb_buf_length;
663
664                 /* BB special case reconnect tid and uid here? */
665                 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
666
667                 /* convert ByteCount if necessary */
668                 if (receive_len >= sizeof(struct smb_hdr) - 4
669                     /* do not count RFC1001 header */  +
670                     (2 * out_buf->WordCount) + 2 /* bcc */ )
671                         BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
672         } else {
673                 rc = -EIO;
674                 cERROR(1, "Bad MID state?");
675         }
676
677 out:
678         delete_mid(midQ);
679         atomic_dec(&ses->server->inFlight);
680         wake_up(&ses->server->request_q);
681
682         return rc;
683 }
684
685 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
686
687 static int
688 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
689                 struct mid_q_entry *midQ)
690 {
691         int rc = 0;
692         struct cifsSesInfo *ses = tcon->ses;
693         __u16 mid = in_buf->Mid;
694
695         header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
696         in_buf->Mid = mid;
697         mutex_lock(&ses->server->srv_mutex);
698         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
699         if (rc) {
700                 mutex_unlock(&ses->server->srv_mutex);
701                 return rc;
702         }
703         rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
704         mutex_unlock(&ses->server->srv_mutex);
705         return rc;
706 }
707
708 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
709    blocking lock to return. */
710
711 static int
712 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
713                         struct smb_hdr *in_buf,
714                         struct smb_hdr *out_buf)
715 {
716         int bytes_returned;
717         struct cifsSesInfo *ses = tcon->ses;
718         LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
719
720         /* We just modify the current in_buf to change
721            the type of lock from LOCKING_ANDX_SHARED_LOCK
722            or LOCKING_ANDX_EXCLUSIVE_LOCK to
723            LOCKING_ANDX_CANCEL_LOCK. */
724
725         pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
726         pSMB->Timeout = 0;
727         pSMB->hdr.Mid = GetNextMid(ses->server);
728
729         return SendReceive(xid, ses, in_buf, out_buf,
730                         &bytes_returned, CIFS_STD_OP);
731 }
732
733 int
734 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
735             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
736             int *pbytes_returned)
737 {
738         int rc = 0;
739         int rstart = 0;
740         unsigned int receive_len;
741         struct mid_q_entry *midQ;
742         struct cifsSesInfo *ses;
743
744         if (tcon == NULL || tcon->ses == NULL) {
745                 cERROR(1, "Null smb session");
746                 return -EIO;
747         }
748         ses = tcon->ses;
749
750         if (ses->server == NULL) {
751                 cERROR(1, "Null tcp session");
752                 return -EIO;
753         }
754
755         if (ses->server->tcpStatus == CifsExiting)
756                 return -ENOENT;
757
758         /* Ensure that we do not send more than 50 overlapping requests
759            to the same server. We may make this configurable later or
760            use ses->maxReq */
761
762         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
763                 cERROR(1, "Illegal length, greater than maximum frame, %d",
764                            in_buf->smb_buf_length);
765                 return -EIO;
766         }
767
768         rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
769         if (rc)
770                 return rc;
771
772         /* make sure that we sign in the same order that we send on this socket
773            and avoid races inside tcp sendmsg code that could cause corruption
774            of smb data */
775
776         mutex_lock(&ses->server->srv_mutex);
777
778         rc = allocate_mid(ses, in_buf, &midQ);
779         if (rc) {
780                 mutex_unlock(&ses->server->srv_mutex);
781                 return rc;
782         }
783
784         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
785         if (rc) {
786                 delete_mid(midQ);
787                 mutex_unlock(&ses->server->srv_mutex);
788                 return rc;
789         }
790
791         midQ->midState = MID_REQUEST_SUBMITTED;
792 #ifdef CONFIG_CIFS_STATS2
793         atomic_inc(&ses->server->inSend);
794 #endif
795         rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
796 #ifdef CONFIG_CIFS_STATS2
797         atomic_dec(&ses->server->inSend);
798         midQ->when_sent = jiffies;
799 #endif
800         mutex_unlock(&ses->server->srv_mutex);
801
802         if (rc < 0) {
803                 delete_mid(midQ);
804                 return rc;
805         }
806
807         /* Wait for a reply - allow signals to interrupt. */
808         rc = wait_event_interruptible(ses->server->response_q,
809                 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
810                 ((ses->server->tcpStatus != CifsGood) &&
811                  (ses->server->tcpStatus != CifsNew)));
812
813         /* Were we interrupted by a signal ? */
814         if ((rc == -ERESTARTSYS) &&
815                 (midQ->midState == MID_REQUEST_SUBMITTED) &&
816                 ((ses->server->tcpStatus == CifsGood) ||
817                  (ses->server->tcpStatus == CifsNew))) {
818
819                 if (in_buf->Command == SMB_COM_TRANSACTION2) {
820                         /* POSIX lock. We send a NT_CANCEL SMB to cause the
821                            blocking lock to return. */
822
823                         rc = send_nt_cancel(tcon, in_buf, midQ);
824                         if (rc) {
825                                 delete_mid(midQ);
826                                 return rc;
827                         }
828                 } else {
829                         /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
830                            to cause the blocking lock to return. */
831
832                         rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
833
834                         /* If we get -ENOLCK back the lock may have
835                            already been removed. Don't exit in this case. */
836                         if (rc && rc != -ENOLCK) {
837                                 delete_mid(midQ);
838                                 return rc;
839                         }
840                 }
841
842                 if (wait_for_response(ses->server, midQ) == 0) {
843                         /* We got the response - restart system call. */
844                         rstart = 1;
845                 }
846         }
847
848         rc = sync_mid_result(midQ, ses->server);
849         if (rc != 0)
850                 return rc;
851
852         receive_len = midQ->resp_buf->smb_buf_length;
853         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
854                 cERROR(1, "Frame too large received.  Length: %d  Xid: %d",
855                         receive_len, xid);
856                 rc = -EIO;
857                 goto out;
858         }
859
860         /* rcvd frame is ok */
861
862         if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
863                 rc = -EIO;
864                 cERROR(1, "Bad MID state?");
865                 goto out;
866         }
867
868         out_buf->smb_buf_length = receive_len;
869         memcpy((char *)out_buf + 4,
870                (char *)midQ->resp_buf + 4,
871                receive_len);
872
873         dump_smb(out_buf, 92);
874         /* convert the length into a more usable form */
875         if ((receive_len > 24) &&
876             (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
877                                      SECMODE_SIGN_ENABLED))) {
878                 rc = cifs_verify_signature(out_buf,
879                                            ses->server,
880                                            midQ->sequence_number+1);
881                 if (rc) {
882                         cERROR(1, "Unexpected SMB signature");
883                         /* BB FIXME add code to kill session */
884                 }
885         }
886
887         *pbytes_returned = out_buf->smb_buf_length;
888
889         /* BB special case reconnect tid and uid here? */
890         rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
891
892         /* convert ByteCount if necessary */
893         if (receive_len >= sizeof(struct smb_hdr) - 4
894             /* do not count RFC1001 header */  +
895             (2 * out_buf->WordCount) + 2 /* bcc */ )
896                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
897
898 out:
899         delete_mid(midQ);
900         if (rstart && rc == -EACCES)
901                 return -ERESTARTSYS;
902         return rc;
903 }