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