]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - fs/cifs/transport.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild...
[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                         total_len = 0;
295                         break;
296                 } else if (rc > total_len) {
297                         cERROR(1, ("sent %d requested %d", rc, total_len));
298                         break;
299                 }
300                 if (rc == 0) {
301                         /* should never happen, letting socket clear before
302                            retrying is our only obvious option here */
303                         cERROR(1, ("tcp sent no data"));
304                         msleep(500);
305                         continue;
306                 }
307                 total_len -= rc;
308                 /* the line below resets i */
309                 for (i = first_vec; i < n_vec; i++) {
310                         if (iov[i].iov_len) {
311                                 if (rc > iov[i].iov_len) {
312                                         rc -= iov[i].iov_len;
313                                         iov[i].iov_len = 0;
314                                 } else {
315                                         iov[i].iov_base += rc;
316                                         iov[i].iov_len -= rc;
317                                         first_vec = i;
318                                         break;
319                                 }
320                         }
321                 }
322                 i = 0; /* in case we get ENOSPC on the next send */
323         }
324
325         if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
326                 cFYI(1, ("partial send (%d remaining), terminating session",
327                         total_len));
328                 /* If we have only sent part of an SMB then the next SMB
329                    could be taken as the remainder of this one.  We need
330                    to kill the socket so the server throws away the partial
331                    SMB */
332                 server->tcpStatus = CifsNeedReconnect;
333         }
334
335         if (rc < 0) {
336                 cERROR(1, ("Error %d sending data on socket to server", rc));
337         } else
338                 rc = 0;
339
340         /* Don't want to modify the buffer as a
341            side effect of this call. */
342         smb_buffer->smb_buf_length = smb_buf_length;
343
344         return rc;
345 }
346
347 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
348 {
349         if (long_op == CIFS_ASYNC_OP) {
350                 /* oplock breaks must not be held up */
351                 atomic_inc(&ses->server->inFlight);
352         } else {
353                 spin_lock(&GlobalMid_Lock);
354                 while (1) {
355                         if (atomic_read(&ses->server->inFlight) >=
356                                         cifs_max_pending){
357                                 spin_unlock(&GlobalMid_Lock);
358 #ifdef CONFIG_CIFS_STATS2
359                                 atomic_inc(&ses->server->num_waiters);
360 #endif
361                                 wait_event(ses->server->request_q,
362                                         atomic_read(&ses->server->inFlight)
363                                          < cifs_max_pending);
364 #ifdef CONFIG_CIFS_STATS2
365                                 atomic_dec(&ses->server->num_waiters);
366 #endif
367                                 spin_lock(&GlobalMid_Lock);
368                         } else {
369                                 if (ses->server->tcpStatus == CifsExiting) {
370                                         spin_unlock(&GlobalMid_Lock);
371                                         return -ENOENT;
372                                 }
373
374                                 /* can not count locking commands against total
375                                    as they are allowed to block on server */
376
377                                 /* update # of requests on the wire to server */
378                                 if (long_op != CIFS_BLOCKING_OP)
379                                         atomic_inc(&ses->server->inFlight);
380                                 spin_unlock(&GlobalMid_Lock);
381                                 break;
382                         }
383                 }
384         }
385         return 0;
386 }
387
388 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
389                         struct mid_q_entry **ppmidQ)
390 {
391         if (ses->server->tcpStatus == CifsExiting) {
392                 return -ENOENT;
393         } else if (ses->server->tcpStatus == CifsNeedReconnect) {
394                 cFYI(1, ("tcp session dead - return to caller to retry"));
395                 return -EAGAIN;
396         } else if (ses->status != CifsGood) {
397                 /* check if SMB session is bad because we are setting it up */
398                 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
399                         (in_buf->Command != SMB_COM_NEGOTIATE))
400                         return -EAGAIN;
401                 /* else ok - we are setting up session */
402         }
403         *ppmidQ = AllocMidQEntry(in_buf, ses);
404         if (*ppmidQ == NULL)
405                 return -ENOMEM;
406         return 0;
407 }
408
409 static int wait_for_response(struct cifsSesInfo *ses,
410                         struct mid_q_entry *midQ,
411                         unsigned long timeout,
412                         unsigned long time_to_wait)
413 {
414         unsigned long curr_timeout;
415
416         for (;;) {
417                 curr_timeout = timeout + jiffies;
418                 wait_event(ses->server->response_q,
419                         (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
420                         time_after(jiffies, curr_timeout) ||
421                         ((ses->server->tcpStatus != CifsGood) &&
422                          (ses->server->tcpStatus != CifsNew)));
423
424                 if (time_after(jiffies, curr_timeout) &&
425                         (midQ->midState == MID_REQUEST_SUBMITTED) &&
426                         ((ses->server->tcpStatus == CifsGood) ||
427                          (ses->server->tcpStatus == CifsNew))) {
428
429                         unsigned long lrt;
430
431                         /* We timed out. Is the server still
432                            sending replies ? */
433                         spin_lock(&GlobalMid_Lock);
434                         lrt = ses->server->lstrp;
435                         spin_unlock(&GlobalMid_Lock);
436
437                         /* Calculate time_to_wait past last receive time.
438                          Although we prefer not to time out if the
439                          server is still responding - we will time
440                          out if the server takes more than 15 (or 45
441                          or 180) seconds to respond to this request
442                          and has not responded to any request from
443                          other threads on the client within 10 seconds */
444                         lrt += time_to_wait;
445                         if (time_after(jiffies, lrt)) {
446                                 /* No replies for time_to_wait. */
447                                 cERROR(1, ("server not responding"));
448                                 return -1;
449                         }
450                 } else {
451                         return 0;
452                 }
453         }
454 }
455
456
457 /*
458  *
459  * Send an SMB Request.  No response info (other than return code)
460  * needs to be parsed.
461  *
462  * flags indicate the type of request buffer and how long to wait
463  * and whether to log NT STATUS code (error) before mapping it to POSIX error
464  *
465  */
466 int
467 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
468                 struct smb_hdr *in_buf, int flags)
469 {
470         int rc;
471         struct kvec iov[1];
472         int resp_buf_type;
473
474         iov[0].iov_base = (char *)in_buf;
475         iov[0].iov_len = in_buf->smb_buf_length + 4;
476         flags |= CIFS_NO_RESP;
477         rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
478         cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
479
480         return rc;
481 }
482
483 int
484 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
485              struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
486              const int flags)
487 {
488         int rc = 0;
489         int long_op;
490         unsigned int receive_len;
491         unsigned long timeout;
492         struct mid_q_entry *midQ;
493         struct smb_hdr *in_buf = iov[0].iov_base;
494
495         long_op = flags & CIFS_TIMEOUT_MASK;
496
497         *pRespBufType = CIFS_NO_BUFFER;  /* no response buf yet */
498
499         if ((ses == NULL) || (ses->server == NULL)) {
500                 cifs_small_buf_release(in_buf);
501                 cERROR(1, ("Null session"));
502                 return -EIO;
503         }
504
505         if (ses->server->tcpStatus == CifsExiting) {
506                 cifs_small_buf_release(in_buf);
507                 return -ENOENT;
508         }
509
510         /* Ensure that we do not send more than 50 overlapping requests
511            to the same server. We may make this configurable later or
512            use ses->maxReq */
513
514         rc = wait_for_free_request(ses, long_op);
515         if (rc) {
516                 cifs_small_buf_release(in_buf);
517                 return rc;
518         }
519
520         /* make sure that we sign in the same order that we send on this socket
521            and avoid races inside tcp sendmsg code that could cause corruption
522            of smb data */
523
524         down(&ses->server->tcpSem);
525
526         rc = allocate_mid(ses, in_buf, &midQ);
527         if (rc) {
528                 up(&ses->server->tcpSem);
529                 cifs_small_buf_release(in_buf);
530                 /* Update # of requests on wire to server */
531                 atomic_dec(&ses->server->inFlight);
532                 wake_up(&ses->server->request_q);
533                 return rc;
534         }
535         rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
536
537         midQ->midState = MID_REQUEST_SUBMITTED;
538 #ifdef CONFIG_CIFS_STATS2
539         atomic_inc(&ses->server->inSend);
540 #endif
541         rc = smb_send2(ses->server, iov, n_vec,
542                       (struct sockaddr *) &(ses->server->addr.sockAddr),
543                        ses->server->noblocksnd);
544 #ifdef CONFIG_CIFS_STATS2
545         atomic_dec(&ses->server->inSend);
546         midQ->when_sent = jiffies;
547 #endif
548
549         up(&ses->server->tcpSem);
550         cifs_small_buf_release(in_buf);
551
552         if (rc < 0)
553                 goto out;
554
555         if (long_op == CIFS_STD_OP)
556                 timeout = 15 * HZ;
557         else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
558                 timeout = 180 * HZ;
559         else if (long_op == CIFS_LONG_OP)
560                 timeout = 45 * HZ; /* should be greater than
561                         servers oplock break timeout (about 43 seconds) */
562         else if (long_op == CIFS_ASYNC_OP)
563                 goto out;
564         else if (long_op == CIFS_BLOCKING_OP)
565                 timeout = 0x7FFFFFFF; /*  large, but not so large as to wrap */
566         else {
567                 cERROR(1, ("unknown timeout flag %d", long_op));
568                 rc = -EIO;
569                 goto out;
570         }
571
572         /* wait for 15 seconds or until woken up due to response arriving or
573            due to last connection to this server being unmounted */
574         if (signal_pending(current)) {
575                 /* if signal pending do not hold up user for full smb timeout
576                 but we still give response a chance to complete */
577                 timeout = 2 * HZ;
578         }
579
580         /* No user interrupts in wait - wreaks havoc with performance */
581         wait_for_response(ses, midQ, timeout, 10 * HZ);
582
583         spin_lock(&GlobalMid_Lock);
584         if (midQ->resp_buf) {
585                 spin_unlock(&GlobalMid_Lock);
586                 receive_len = midQ->resp_buf->smb_buf_length;
587         } else {
588                 cERROR(1, ("No response to cmd %d mid %d",
589                         midQ->command, midQ->mid));
590                 if (midQ->midState == MID_REQUEST_SUBMITTED) {
591                         if (ses->server->tcpStatus == CifsExiting)
592                                 rc = -EHOSTDOWN;
593                         else {
594                                 ses->server->tcpStatus = CifsNeedReconnect;
595                                 midQ->midState = MID_RETRY_NEEDED;
596                         }
597                 }
598
599                 if (rc != -EHOSTDOWN) {
600                         if (midQ->midState == MID_RETRY_NEEDED) {
601                                 rc = -EAGAIN;
602                                 cFYI(1, ("marking request for retry"));
603                         } else {
604                                 rc = -EIO;
605                         }
606                 }
607                 spin_unlock(&GlobalMid_Lock);
608                 DeleteMidQEntry(midQ);
609                 /* Update # of requests on wire to server */
610                 atomic_dec(&ses->server->inFlight);
611                 wake_up(&ses->server->request_q);
612                 return rc;
613         }
614
615         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
616                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
617                         receive_len, xid));
618                 rc = -EIO;
619         } else {                /* rcvd frame is ok */
620                 if (midQ->resp_buf &&
621                         (midQ->midState == MID_RESPONSE_RECEIVED)) {
622
623                         iov[0].iov_base = (char *)midQ->resp_buf;
624                         if (midQ->largeBuf)
625                                 *pRespBufType = CIFS_LARGE_BUFFER;
626                         else
627                                 *pRespBufType = CIFS_SMALL_BUFFER;
628                         iov[0].iov_len = receive_len + 4;
629
630                         dump_smb(midQ->resp_buf, 80);
631                         /* convert the length into a more usable form */
632                         if ((receive_len > 24) &&
633                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
634                                         SECMODE_SIGN_ENABLED))) {
635                                 rc = cifs_verify_signature(midQ->resp_buf,
636                                                 &ses->server->mac_signing_key,
637                                                 midQ->sequence_number+1);
638                                 if (rc) {
639                                         cERROR(1, ("Unexpected SMB signature"));
640                                         /* BB FIXME add code to kill session */
641                                 }
642                         }
643
644                         /* BB special case reconnect tid and uid here? */
645                         rc = map_smb_to_linux_error(midQ->resp_buf,
646                                                 flags & CIFS_LOG_ERROR);
647
648                         /* convert ByteCount if necessary */
649                         if (receive_len >= sizeof(struct smb_hdr) - 4
650                             /* do not count RFC1001 header */  +
651                             (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
652                                 BCC(midQ->resp_buf) =
653                                         le16_to_cpu(BCC_LE(midQ->resp_buf));
654                         if ((flags & CIFS_NO_RESP) == 0)
655                                 midQ->resp_buf = NULL;  /* mark it so buf will
656                                                            not be freed by
657                                                            DeleteMidQEntry */
658                 } else {
659                         rc = -EIO;
660                         cFYI(1, ("Bad MID state?"));
661                 }
662         }
663
664 out:
665         DeleteMidQEntry(midQ);
666         atomic_dec(&ses->server->inFlight);
667         wake_up(&ses->server->request_q);
668
669         return rc;
670 }
671
672 int
673 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
674             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
675             int *pbytes_returned, const int long_op)
676 {
677         int rc = 0;
678         unsigned int receive_len;
679         unsigned long timeout;
680         struct mid_q_entry *midQ;
681
682         if (ses == NULL) {
683                 cERROR(1, ("Null smb session"));
684                 return -EIO;
685         }
686         if (ses->server == NULL) {
687                 cERROR(1, ("Null tcp session"));
688                 return -EIO;
689         }
690
691         if (ses->server->tcpStatus == CifsExiting)
692                 return -ENOENT;
693
694         /* Ensure that we do not send more than 50 overlapping requests
695            to the same server. We may make this configurable later or
696            use ses->maxReq */
697
698         rc = wait_for_free_request(ses, long_op);
699         if (rc)
700                 return rc;
701
702         /* make sure that we sign in the same order that we send on this socket
703            and avoid races inside tcp sendmsg code that could cause corruption
704            of smb data */
705
706         down(&ses->server->tcpSem);
707
708         rc = allocate_mid(ses, in_buf, &midQ);
709         if (rc) {
710                 up(&ses->server->tcpSem);
711                 /* Update # of requests on wire to server */
712                 atomic_dec(&ses->server->inFlight);
713                 wake_up(&ses->server->request_q);
714                 return rc;
715         }
716
717         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
718                 cERROR(1, ("Illegal length, greater than maximum frame, %d",
719                         in_buf->smb_buf_length));
720                 DeleteMidQEntry(midQ);
721                 up(&ses->server->tcpSem);
722                 /* Update # of requests on wire to server */
723                 atomic_dec(&ses->server->inFlight);
724                 wake_up(&ses->server->request_q);
725                 return -EIO;
726         }
727
728         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
729
730         midQ->midState = MID_REQUEST_SUBMITTED;
731 #ifdef CONFIG_CIFS_STATS2
732         atomic_inc(&ses->server->inSend);
733 #endif
734         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
735                       (struct sockaddr *) &(ses->server->addr.sockAddr),
736                       ses->server->noblocksnd);
737 #ifdef CONFIG_CIFS_STATS2
738         atomic_dec(&ses->server->inSend);
739         midQ->when_sent = jiffies;
740 #endif
741         up(&ses->server->tcpSem);
742
743         if (rc < 0)
744                 goto out;
745
746         if (long_op == CIFS_STD_OP)
747                 timeout = 15 * HZ;
748         /* wait for 15 seconds or until woken up due to response arriving or
749            due to last connection to this server being unmounted */
750         else if (long_op == CIFS_ASYNC_OP)
751                 goto out;
752         else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
753                 timeout = 180 * HZ;
754         else if (long_op == CIFS_LONG_OP)
755                 timeout = 45 * HZ; /* should be greater than
756                         servers oplock break timeout (about 43 seconds) */
757         else if (long_op == CIFS_BLOCKING_OP)
758                 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
759         else {
760                 cERROR(1, ("unknown timeout flag %d", long_op));
761                 rc = -EIO;
762                 goto out;
763         }
764
765         if (signal_pending(current)) {
766                 /* if signal pending do not hold up user for full smb timeout
767                 but we still give response a chance to complete */
768                 timeout = 2 * HZ;
769         }
770
771         /* No user interrupts in wait - wreaks havoc with performance */
772         wait_for_response(ses, midQ, timeout, 10 * HZ);
773
774         spin_lock(&GlobalMid_Lock);
775         if (midQ->resp_buf) {
776                 spin_unlock(&GlobalMid_Lock);
777                 receive_len = midQ->resp_buf->smb_buf_length;
778         } else {
779                 cERROR(1, ("No response for cmd %d mid %d",
780                           midQ->command, midQ->mid));
781                 if (midQ->midState == MID_REQUEST_SUBMITTED) {
782                         if (ses->server->tcpStatus == CifsExiting)
783                                 rc = -EHOSTDOWN;
784                         else {
785                                 ses->server->tcpStatus = CifsNeedReconnect;
786                                 midQ->midState = MID_RETRY_NEEDED;
787                         }
788                 }
789
790                 if (rc != -EHOSTDOWN) {
791                         if (midQ->midState == MID_RETRY_NEEDED) {
792                                 rc = -EAGAIN;
793                                 cFYI(1, ("marking request for retry"));
794                         } else {
795                                 rc = -EIO;
796                         }
797                 }
798                 spin_unlock(&GlobalMid_Lock);
799                 DeleteMidQEntry(midQ);
800                 /* Update # of requests on wire to server */
801                 atomic_dec(&ses->server->inFlight);
802                 wake_up(&ses->server->request_q);
803                 return rc;
804         }
805
806         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
807                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
808                         receive_len, xid));
809                 rc = -EIO;
810         } else {                /* rcvd frame is ok */
811
812                 if (midQ->resp_buf && out_buf
813                     && (midQ->midState == MID_RESPONSE_RECEIVED)) {
814                         out_buf->smb_buf_length = receive_len;
815                         memcpy((char *)out_buf + 4,
816                                (char *)midQ->resp_buf + 4,
817                                receive_len);
818
819                         dump_smb(out_buf, 92);
820                         /* convert the length into a more usable form */
821                         if ((receive_len > 24) &&
822                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
823                                         SECMODE_SIGN_ENABLED))) {
824                                 rc = cifs_verify_signature(out_buf,
825                                                 &ses->server->mac_signing_key,
826                                                 midQ->sequence_number+1);
827                                 if (rc) {
828                                         cERROR(1, ("Unexpected SMB signature"));
829                                         /* BB FIXME add code to kill session */
830                                 }
831                         }
832
833                         *pbytes_returned = out_buf->smb_buf_length;
834
835                         /* BB special case reconnect tid and uid here? */
836                         rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
837
838                         /* convert ByteCount if necessary */
839                         if (receive_len >= sizeof(struct smb_hdr) - 4
840                             /* do not count RFC1001 header */  +
841                             (2 * out_buf->WordCount) + 2 /* bcc */ )
842                                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
843                 } else {
844                         rc = -EIO;
845                         cERROR(1, ("Bad MID state?"));
846                 }
847         }
848
849 out:
850         DeleteMidQEntry(midQ);
851         atomic_dec(&ses->server->inFlight);
852         wake_up(&ses->server->request_q);
853
854         return rc;
855 }
856
857 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
858
859 static int
860 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
861                 struct mid_q_entry *midQ)
862 {
863         int rc = 0;
864         struct cifsSesInfo *ses = tcon->ses;
865         __u16 mid = in_buf->Mid;
866
867         header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
868         in_buf->Mid = mid;
869         down(&ses->server->tcpSem);
870         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
871         if (rc) {
872                 up(&ses->server->tcpSem);
873                 return rc;
874         }
875         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
876               (struct sockaddr *) &(ses->server->addr.sockAddr),
877               ses->server->noblocksnd);
878         up(&ses->server->tcpSem);
879         return rc;
880 }
881
882 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
883    blocking lock to return. */
884
885 static int
886 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
887                         struct smb_hdr *in_buf,
888                         struct smb_hdr *out_buf)
889 {
890         int bytes_returned;
891         struct cifsSesInfo *ses = tcon->ses;
892         LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
893
894         /* We just modify the current in_buf to change
895            the type of lock from LOCKING_ANDX_SHARED_LOCK
896            or LOCKING_ANDX_EXCLUSIVE_LOCK to
897            LOCKING_ANDX_CANCEL_LOCK. */
898
899         pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
900         pSMB->Timeout = 0;
901         pSMB->hdr.Mid = GetNextMid(ses->server);
902
903         return SendReceive(xid, ses, in_buf, out_buf,
904                         &bytes_returned, CIFS_STD_OP);
905 }
906
907 int
908 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
909             struct smb_hdr *in_buf, struct smb_hdr *out_buf,
910             int *pbytes_returned)
911 {
912         int rc = 0;
913         int rstart = 0;
914         unsigned int receive_len;
915         struct mid_q_entry *midQ;
916         struct cifsSesInfo *ses;
917
918         if (tcon == NULL || tcon->ses == NULL) {
919                 cERROR(1, ("Null smb session"));
920                 return -EIO;
921         }
922         ses = tcon->ses;
923
924         if (ses->server == NULL) {
925                 cERROR(1, ("Null tcp session"));
926                 return -EIO;
927         }
928
929         if (ses->server->tcpStatus == CifsExiting)
930                 return -ENOENT;
931
932         /* Ensure that we do not send more than 50 overlapping requests
933            to the same server. We may make this configurable later or
934            use ses->maxReq */
935
936         rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
937         if (rc)
938                 return rc;
939
940         /* make sure that we sign in the same order that we send on this socket
941            and avoid races inside tcp sendmsg code that could cause corruption
942            of smb data */
943
944         down(&ses->server->tcpSem);
945
946         rc = allocate_mid(ses, in_buf, &midQ);
947         if (rc) {
948                 up(&ses->server->tcpSem);
949                 return rc;
950         }
951
952         if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
953                 up(&ses->server->tcpSem);
954                 cERROR(1, ("Illegal length, greater than maximum frame, %d",
955                         in_buf->smb_buf_length));
956                 DeleteMidQEntry(midQ);
957                 return -EIO;
958         }
959
960         rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
961
962         midQ->midState = MID_REQUEST_SUBMITTED;
963 #ifdef CONFIG_CIFS_STATS2
964         atomic_inc(&ses->server->inSend);
965 #endif
966         rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
967                       (struct sockaddr *) &(ses->server->addr.sockAddr),
968                       ses->server->noblocksnd);
969 #ifdef CONFIG_CIFS_STATS2
970         atomic_dec(&ses->server->inSend);
971         midQ->when_sent = jiffies;
972 #endif
973         up(&ses->server->tcpSem);
974
975         if (rc < 0) {
976                 DeleteMidQEntry(midQ);
977                 return rc;
978         }
979
980         /* Wait for a reply - allow signals to interrupt. */
981         rc = wait_event_interruptible(ses->server->response_q,
982                 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
983                 ((ses->server->tcpStatus != CifsGood) &&
984                  (ses->server->tcpStatus != CifsNew)));
985
986         /* Were we interrupted by a signal ? */
987         if ((rc == -ERESTARTSYS) &&
988                 (midQ->midState == MID_REQUEST_SUBMITTED) &&
989                 ((ses->server->tcpStatus == CifsGood) ||
990                  (ses->server->tcpStatus == CifsNew))) {
991
992                 if (in_buf->Command == SMB_COM_TRANSACTION2) {
993                         /* POSIX lock. We send a NT_CANCEL SMB to cause the
994                            blocking lock to return. */
995
996                         rc = send_nt_cancel(tcon, in_buf, midQ);
997                         if (rc) {
998                                 DeleteMidQEntry(midQ);
999                                 return rc;
1000                         }
1001                 } else {
1002                         /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
1003                            to cause the blocking lock to return. */
1004
1005                         rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1006
1007                         /* If we get -ENOLCK back the lock may have
1008                            already been removed. Don't exit in this case. */
1009                         if (rc && rc != -ENOLCK) {
1010                                 DeleteMidQEntry(midQ);
1011                                 return rc;
1012                         }
1013                 }
1014
1015                 /* Wait 5 seconds for the response. */
1016                 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
1017                         /* We got the response - restart system call. */
1018                         rstart = 1;
1019                 }
1020         }
1021
1022         spin_lock(&GlobalMid_Lock);
1023         if (midQ->resp_buf) {
1024                 spin_unlock(&GlobalMid_Lock);
1025                 receive_len = midQ->resp_buf->smb_buf_length;
1026         } else {
1027                 cERROR(1, ("No response for cmd %d mid %d",
1028                           midQ->command, midQ->mid));
1029                 if (midQ->midState == MID_REQUEST_SUBMITTED) {
1030                         if (ses->server->tcpStatus == CifsExiting)
1031                                 rc = -EHOSTDOWN;
1032                         else {
1033                                 ses->server->tcpStatus = CifsNeedReconnect;
1034                                 midQ->midState = MID_RETRY_NEEDED;
1035                         }
1036                 }
1037
1038                 if (rc != -EHOSTDOWN) {
1039                         if (midQ->midState == MID_RETRY_NEEDED) {
1040                                 rc = -EAGAIN;
1041                                 cFYI(1, ("marking request for retry"));
1042                         } else {
1043                                 rc = -EIO;
1044                         }
1045                 }
1046                 spin_unlock(&GlobalMid_Lock);
1047                 DeleteMidQEntry(midQ);
1048                 return rc;
1049         }
1050
1051         if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1052                 cERROR(1, ("Frame too large received.  Length: %d  Xid: %d",
1053                         receive_len, xid));
1054                 rc = -EIO;
1055         } else {                /* rcvd frame is ok */
1056
1057                 if (midQ->resp_buf && out_buf
1058                     && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1059                         out_buf->smb_buf_length = receive_len;
1060                         memcpy((char *)out_buf + 4,
1061                                (char *)midQ->resp_buf + 4,
1062                                receive_len);
1063
1064                         dump_smb(out_buf, 92);
1065                         /* convert the length into a more usable form */
1066                         if ((receive_len > 24) &&
1067                            (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1068                                         SECMODE_SIGN_ENABLED))) {
1069                                 rc = cifs_verify_signature(out_buf,
1070                                                 &ses->server->mac_signing_key,
1071                                                 midQ->sequence_number+1);
1072                                 if (rc) {
1073                                         cERROR(1, ("Unexpected SMB signature"));
1074                                         /* BB FIXME add code to kill session */
1075                                 }
1076                         }
1077
1078                         *pbytes_returned = out_buf->smb_buf_length;
1079
1080                         /* BB special case reconnect tid and uid here? */
1081                         rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1082
1083                         /* convert ByteCount if necessary */
1084                         if (receive_len >= sizeof(struct smb_hdr) - 4
1085                             /* do not count RFC1001 header */  +
1086                             (2 * out_buf->WordCount) + 2 /* bcc */ )
1087                                 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1088                 } else {
1089                         rc = -EIO;
1090                         cERROR(1, ("Bad MID state?"));
1091                 }
1092         }
1093         DeleteMidQEntry(midQ);
1094         if (rstart && rc == -EACCES)
1095                 return -ERESTARTSYS;
1096         return rc;
1097 }