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