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