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