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