[CIFS] Do not time out posix brl requests when using new posix setfileinfo
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / fs / cifs / transport.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/transport.c
3 *
b8643e1b 4 * Copyright (C) International Business Machines Corp., 2002,2005
1da177e4
LT
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <linux/fs.h>
23#include <linux/list.h>
24#include <linux/wait.h>
25#include <linux/net.h>
26#include <linux/delay.h>
27#include <asm/uaccess.h>
28#include <asm/processor.h>
29#include <linux/mempool.h>
30#include "cifspdu.h"
31#include "cifsglob.h"
32#include "cifsproto.h"
33#include "cifs_debug.h"
34
35extern mempool_t *cifs_mid_poolp;
36extern kmem_cache_t *cifs_oplock_cachep;
37
38static struct mid_q_entry *
39AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
40{
41 struct mid_q_entry *temp;
42
43 if (ses == NULL) {
275cde1a 44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
1da177e4
LT
45 return NULL;
46 }
47 if (ses->server == NULL) {
48 cERROR(1, ("Null TCP session in AllocMidQEntry"));
49 return NULL;
50 }
51
d6e04ae6
SF
52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
53 SLAB_KERNEL | SLAB_NOFS);
1da177e4
LT
54 if (temp == NULL)
55 return temp;
56 else {
57 memset(temp, 0, sizeof (struct mid_q_entry));
58 temp->mid = smb_buffer->Mid; /* always LE */
59 temp->pid = current->pid;
60 temp->command = smb_buffer->Command;
61 cFYI(1, ("For smb_command %d", temp->command));
1047abc1
SF
62 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
63 /* when mid allocated can be before when sent */
64 temp->when_alloc = jiffies;
1da177e4
LT
65 temp->ses = ses;
66 temp->tsk = current;
67 }
68
69 spin_lock(&GlobalMid_Lock);
70 list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
71 atomic_inc(&midCount);
72 temp->midState = MID_REQUEST_ALLOCATED;
73 spin_unlock(&GlobalMid_Lock);
74 return temp;
75}
76
77static void
78DeleteMidQEntry(struct mid_q_entry *midEntry)
79{
1047abc1
SF
80#ifdef CONFIG_CIFS_STATS2
81 unsigned long now;
82#endif
1da177e4
LT
83 spin_lock(&GlobalMid_Lock);
84 midEntry->midState = MID_FREE;
85 list_del(&midEntry->qhead);
86 atomic_dec(&midCount);
87 spin_unlock(&GlobalMid_Lock);
b8643e1b
SF
88 if(midEntry->largeBuf)
89 cifs_buf_release(midEntry->resp_buf);
90 else
91 cifs_small_buf_release(midEntry->resp_buf);
1047abc1
SF
92#ifdef CONFIG_CIFS_STATS2
93 now = jiffies;
94 /* commands taking longer than one second are indications that
95 something is wrong, unless it is quite a slow link or server */
96 if((now - midEntry->when_alloc) > HZ) {
97 if((cifsFYI & CIFS_TIMER) &&
98 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
99 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
100 midEntry->command, midEntry->mid);
101 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
102 now - midEntry->when_alloc,
103 now - midEntry->when_sent,
104 now - midEntry->when_received);
105 }
106 }
107#endif
1da177e4
LT
108 mempool_free(midEntry, cifs_mid_poolp);
109}
110
111struct oplock_q_entry *
112AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
113{
114 struct oplock_q_entry *temp;
115 if ((pinode== NULL) || (tcon == NULL)) {
116 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
117 return NULL;
118 }
119 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
120 SLAB_KERNEL);
121 if (temp == NULL)
122 return temp;
123 else {
124 temp->pinode = pinode;
125 temp->tcon = tcon;
126 temp->netfid = fid;
127 spin_lock(&GlobalMid_Lock);
128 list_add_tail(&temp->qhead, &GlobalOplock_Q);
129 spin_unlock(&GlobalMid_Lock);
130 }
131 return temp;
132
133}
134
135void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
136{
137 spin_lock(&GlobalMid_Lock);
138 /* should we check if list empty first? */
139 list_del(&oplockEntry->qhead);
140 spin_unlock(&GlobalMid_Lock);
141 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
142}
143
144int
145smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
146 unsigned int smb_buf_length, struct sockaddr *sin)
147{
148 int rc = 0;
149 int i = 0;
150 struct msghdr smb_msg;
151 struct kvec iov;
152 unsigned len = smb_buf_length + 4;
153
154 if(ssocket == NULL)
155 return -ENOTSOCK; /* BB eventually add reconnect code here */
156 iov.iov_base = smb_buffer;
157 iov.iov_len = len;
158
159 smb_msg.msg_name = sin;
160 smb_msg.msg_namelen = sizeof (struct sockaddr);
161 smb_msg.msg_control = NULL;
162 smb_msg.msg_controllen = 0;
163 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
164
165 /* smb header is converted in header_assemble. bcc and rest of SMB word
166 area, and byte area if necessary, is converted to littleendian in
167 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
168 Flags2 is converted in SendReceive */
169
170 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
3e84469d 171 cFYI(1, ("Sending smb of length %d", smb_buf_length));
1da177e4
LT
172 dump_smb(smb_buffer, len);
173
174 while (len > 0) {
175 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
176 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
177 i++;
3e84469d
SF
178 /* smaller timeout here than send2 since smaller size */
179 /* Although it may not be required, this also is smaller
180 oplock break time */
68058e75 181 if(i > 12) {
1da177e4 182 cERROR(1,
68058e75 183 ("sends on sock %p stuck for 7 seconds",
1da177e4
LT
184 ssocket));
185 rc = -EAGAIN;
186 break;
187 }
68058e75 188 msleep(1 << i);
1da177e4
LT
189 continue;
190 }
191 if (rc < 0)
192 break;
5e1253b5
SF
193 else
194 i = 0; /* reset i after each successful send */
1da177e4
LT
195 iov.iov_base += rc;
196 iov.iov_len -= rc;
197 len -= rc;
198 }
199
200 if (rc < 0) {
3e84469d 201 cERROR(1,("Error %d sending data on socket to server", rc));
1da177e4
LT
202 } else {
203 rc = 0;
204 }
205
206 return rc;
207}
208
d6e04ae6 209static int
3e84469d
SF
210smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
211 struct sockaddr *sin)
1da177e4
LT
212{
213 int rc = 0;
214 int i = 0;
215 struct msghdr smb_msg;
3e84469d
SF
216 struct smb_hdr *smb_buffer = iov[0].iov_base;
217 unsigned int len = iov[0].iov_len;
218 unsigned int total_len;
219 int first_vec = 0;
d6e04ae6 220
1da177e4
LT
221 if(ssocket == NULL)
222 return -ENOTSOCK; /* BB eventually add reconnect code here */
3e84469d 223
1da177e4
LT
224 smb_msg.msg_name = sin;
225 smb_msg.msg_namelen = sizeof (struct sockaddr);
226 smb_msg.msg_control = NULL;
227 smb_msg.msg_controllen = 0;
228 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
229
230 /* smb header is converted in header_assemble. bcc and rest of SMB word
231 area, and byte area if necessary, is converted to littleendian in
232 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
233 Flags2 is converted in SendReceive */
234
3e84469d
SF
235
236 total_len = 0;
237 for (i = 0; i < n_vec; i++)
238 total_len += iov[i].iov_len;
239
1da177e4 240 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
3e84469d 241 cFYI(1, ("Sending smb: total_len %d", total_len));
1da177e4
LT
242 dump_smb(smb_buffer, len);
243
3e84469d
SF
244 while (total_len) {
245 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
246 n_vec - first_vec, total_len);
1da177e4
LT
247 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
248 i++;
68058e75 249 if(i >= 14) {
1da177e4 250 cERROR(1,
68058e75 251 ("sends on sock %p stuck for 15 seconds",
1da177e4
LT
252 ssocket));
253 rc = -EAGAIN;
254 break;
255 }
68058e75 256 msleep(1 << i);
1da177e4
LT
257 continue;
258 }
259 if (rc < 0)
260 break;
3e84469d
SF
261
262 if (rc >= total_len) {
263 WARN_ON(rc > total_len);
264 break;
265 }
266 if(rc == 0) {
267 /* should never happen, letting socket clear before
268 retrying is our only obvious option here */
04c08816 269 cERROR(1,("tcp sent no data"));
3e84469d
SF
270 msleep(500);
271 continue;
d6e04ae6 272 }
3e84469d 273 total_len -= rc;
68058e75 274 /* the line below resets i */
3e84469d
SF
275 for (i = first_vec; i < n_vec; i++) {
276 if (iov[i].iov_len) {
277 if (rc > iov[i].iov_len) {
278 rc -= iov[i].iov_len;
279 iov[i].iov_len = 0;
280 } else {
281 iov[i].iov_base += rc;
282 iov[i].iov_len -= rc;
283 first_vec = i;
284 break;
285 }
286 }
d6e04ae6 287 }
5e1253b5 288 i = 0; /* in case we get ENOSPC on the next send */
1da177e4
LT
289 }
290
291 if (rc < 0) {
3e84469d
SF
292 cERROR(1,("Error %d sending data on socket to server", rc));
293 } else
1da177e4 294 rc = 0;
1da177e4
LT
295
296 return rc;
297}
298
1da177e4 299int
d6e04ae6 300SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
ec637e3f 301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
3e84469d 302 const int long_op)
1da177e4
LT
303{
304 int rc = 0;
d6e04ae6
SF
305 unsigned int receive_len;
306 unsigned long timeout;
307 struct mid_q_entry *midQ;
3e84469d 308 struct smb_hdr *in_buf = iov[0].iov_base;
ec637e3f
SF
309
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
1da177e4 311
4b8f930f
SF
312 if ((ses == NULL) || (ses->server == NULL)) {
313 cifs_small_buf_release(in_buf);
314 cERROR(1,("Null session"));
1da177e4
LT
315 return -EIO;
316 }
1da177e4 317
4b8f930f
SF
318 if(ses->server->tcpStatus == CifsExiting) {
319 cifs_small_buf_release(in_buf);
31ca3bc3 320 return -ENOENT;
4b8f930f 321 }
31ca3bc3 322
1da177e4
LT
323 /* Ensure that we do not send more than 50 overlapping requests
324 to the same server. We may make this configurable later or
325 use ses->maxReq */
326 if(long_op == -1) {
327 /* oplock breaks must not be held up */
328 atomic_inc(&ses->server->inFlight);
329 } else {
330 spin_lock(&GlobalMid_Lock);
331 while(1) {
d6e04ae6
SF
332 if(atomic_read(&ses->server->inFlight) >=
333 cifs_max_pending){
1da177e4 334 spin_unlock(&GlobalMid_Lock);
131afd0b
SF
335#ifdef CONFIG_CIFS_STATS2
336 atomic_inc(&ses->server->num_waiters);
337#endif
1da177e4
LT
338 wait_event(ses->server->request_q,
339 atomic_read(&ses->server->inFlight)
340 < cifs_max_pending);
131afd0b
SF
341#ifdef CONFIG_CIFS_STATS2
342 atomic_dec(&ses->server->num_waiters);
343#endif
1da177e4
LT
344 spin_lock(&GlobalMid_Lock);
345 } else {
346 if(ses->server->tcpStatus == CifsExiting) {
347 spin_unlock(&GlobalMid_Lock);
4b8f930f 348 cifs_small_buf_release(in_buf);
1da177e4
LT
349 return -ENOENT;
350 }
351
352 /* can not count locking commands against total since
353 they are allowed to block on server */
354
355 if(long_op < 3) {
356 /* update # of requests on the wire to server */
357 atomic_inc(&ses->server->inFlight);
358 }
359 spin_unlock(&GlobalMid_Lock);
360 break;
361 }
362 }
363 }
364 /* make sure that we sign in the same order that we send on this socket
365 and avoid races inside tcp sendmsg code that could cause corruption
366 of smb data */
367
368 down(&ses->server->tcpSem);
369
370 if (ses->server->tcpStatus == CifsExiting) {
371 rc = -ENOENT;
d6e04ae6 372 goto out_unlock2;
1da177e4
LT
373 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
374 cFYI(1,("tcp session dead - return to caller to retry"));
375 rc = -EAGAIN;
d6e04ae6 376 goto out_unlock2;
1da177e4
LT
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 rc = -EAGAIN;
d6e04ae6 382 goto out_unlock2;
1da177e4
LT
383 } /* else ok - we are setting up session */
384 }
385 midQ = AllocMidQEntry(in_buf, ses);
386 if (midQ == NULL) {
387 up(&ses->server->tcpSem);
4b8f930f 388 cifs_small_buf_release(in_buf);
1da177e4
LT
389 /* If not lock req, update # of requests on wire to server */
390 if(long_op < 3) {
391 atomic_dec(&ses->server->inFlight);
392 wake_up(&ses->server->request_q);
393 }
394 return -ENOMEM;
395 }
396
84afc29b 397 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
1da177e4
LT
398
399 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
400#ifdef CONFIG_CIFS_STATS2
401 atomic_inc(&ses->server->inSend);
402#endif
3e84469d 403 rc = smb_send2(ses->server->ssocket, iov, n_vec,
d6e04ae6 404 (struct sockaddr *) &(ses->server->addr.sockAddr));
131afd0b
SF
405#ifdef CONFIG_CIFS_STATS2
406 atomic_dec(&ses->server->inSend);
1047abc1 407 midQ->when_sent = jiffies;
131afd0b 408#endif
1da177e4
LT
409 if(rc < 0) {
410 DeleteMidQEntry(midQ);
411 up(&ses->server->tcpSem);
4b8f930f 412 cifs_small_buf_release(in_buf);
1da177e4
LT
413 /* If not lock req, update # of requests on wire to server */
414 if(long_op < 3) {
415 atomic_dec(&ses->server->inFlight);
416 wake_up(&ses->server->request_q);
417 }
418 return rc;
4b8f930f 419 } else {
1da177e4 420 up(&ses->server->tcpSem);
4b8f930f
SF
421 cifs_small_buf_release(in_buf);
422 }
423
d6e04ae6
SF
424 if (long_op == -1)
425 goto cifs_no_response_exit2;
426 else if (long_op == 2) /* writes past end of file can take loong time */
37c0eb46 427 timeout = 180 * HZ;
d6e04ae6
SF
428 else if (long_op == 1)
429 timeout = 45 * HZ; /* should be greater than
430 servers oplock break timeout (about 43 seconds) */
431 else if (long_op > 2) {
432 timeout = MAX_SCHEDULE_TIMEOUT;
433 } else
434 timeout = 15 * HZ;
435 /* wait for 15 seconds or until woken up due to response arriving or
436 due to last connection to this server being unmounted */
437 if (signal_pending(current)) {
438 /* if signal pending do not hold up user for full smb timeout
439 but we still give response a change to complete */
440 timeout = 2 * HZ;
441 }
442
443 /* No user interrupts in wait - wreaks havoc with performance */
444 if(timeout != MAX_SCHEDULE_TIMEOUT) {
445 timeout += jiffies;
446 wait_event(ses->server->response_q,
3a5ff61c
SF
447 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
448 (time_after(jiffies, timeout) &&
449 time_after(jiffies, ses->server->lstrp + HZ)) ||
d6e04ae6
SF
450 ((ses->server->tcpStatus != CifsGood) &&
451 (ses->server->tcpStatus != CifsNew)));
452 } else {
453 wait_event(ses->server->response_q,
454 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
455 ((ses->server->tcpStatus != CifsGood) &&
456 (ses->server->tcpStatus != CifsNew)));
457 }
458
459 spin_lock(&GlobalMid_Lock);
460 if (midQ->resp_buf) {
461 spin_unlock(&GlobalMid_Lock);
70ca734a 462 receive_len = midQ->resp_buf->smb_buf_length;
d6e04ae6 463 } else {
37c0eb46
SF
464 cERROR(1,("No response to cmd %d mid %d",
465 midQ->command, midQ->mid));
d6e04ae6
SF
466 if(midQ->midState == MID_REQUEST_SUBMITTED) {
467 if(ses->server->tcpStatus == CifsExiting)
468 rc = -EHOSTDOWN;
469 else {
470 ses->server->tcpStatus = CifsNeedReconnect;
471 midQ->midState = MID_RETRY_NEEDED;
472 }
473 }
474
475 if (rc != -EHOSTDOWN) {
476 if(midQ->midState == MID_RETRY_NEEDED) {
477 rc = -EAGAIN;
478 cFYI(1,("marking request for retry"));
479 } else {
480 rc = -EIO;
481 }
482 }
483 spin_unlock(&GlobalMid_Lock);
484 DeleteMidQEntry(midQ);
485 /* If not lock req, update # of requests on wire to server */
486 if(long_op < 3) {
487 atomic_dec(&ses->server->inFlight);
488 wake_up(&ses->server->request_q);
489 }
490 return rc;
491 }
492
493 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
494 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
495 receive_len, xid));
496 rc = -EIO;
497 } else { /* rcvd frame is ok */
d6e04ae6
SF
498 if (midQ->resp_buf &&
499 (midQ->midState == MID_RESPONSE_RECEIVED)) {
84afc29b 500
ec637e3f
SF
501 iov[0].iov_base = (char *)midQ->resp_buf;
502 if(midQ->largeBuf)
503 *pRespBufType = CIFS_LARGE_BUFFER;
504 else
505 *pRespBufType = CIFS_SMALL_BUFFER;
506 iov[0].iov_len = receive_len + 4;
d6e04ae6 507
ec637e3f 508 dump_smb(midQ->resp_buf, 80);
d6e04ae6
SF
509 /* convert the length into a more usable form */
510 if((receive_len > 24) &&
511 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
512 SECMODE_SIGN_ENABLED))) {
ec637e3f 513 rc = cifs_verify_signature(midQ->resp_buf,
d6e04ae6
SF
514 ses->server->mac_signing_key,
515 midQ->sequence_number+1);
516 if(rc) {
517 cERROR(1,("Unexpected SMB signature"));
518 /* BB FIXME add code to kill session */
519 }
520 }
521
d6e04ae6 522 /* BB special case reconnect tid and uid here? */
6ab16d24 523 /* BB special case Errbadpassword and pwdexpired here */
ec637e3f 524 rc = map_smb_to_linux_error(midQ->resp_buf);
d6e04ae6
SF
525
526 /* convert ByteCount if necessary */
527 if (receive_len >=
528 sizeof (struct smb_hdr) -
529 4 /* do not count RFC1001 header */ +
ec637e3f
SF
530 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
531 BCC(midQ->resp_buf) =
532 le16_to_cpu(BCC_LE(midQ->resp_buf));
533 midQ->resp_buf = NULL; /* mark it so will not be freed
534 by DeleteMidQEntry */
d6e04ae6
SF
535 } else {
536 rc = -EIO;
ab2f218f 537 cFYI(1,("Bad MID state?"));
d6e04ae6
SF
538 }
539 }
540cifs_no_response_exit2:
541 DeleteMidQEntry(midQ);
542
1da177e4 543 if(long_op < 3) {
d6e04ae6 544 atomic_dec(&ses->server->inFlight);
1da177e4
LT
545 wake_up(&ses->server->request_q);
546 }
547
548 return rc;
1da177e4 549
d6e04ae6
SF
550out_unlock2:
551 up(&ses->server->tcpSem);
4b8f930f 552 cifs_small_buf_release(in_buf);
d6e04ae6
SF
553 /* If not lock req, update # of requests on wire to server */
554 if(long_op < 3) {
555 atomic_dec(&ses->server->inFlight);
556 wake_up(&ses->server->request_q);
557 }
1da177e4 558
d6e04ae6
SF
559 return rc;
560}
1da177e4
LT
561
562int
563SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
564 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
565 int *pbytes_returned, const int long_op)
566{
567 int rc = 0;
568 unsigned int receive_len;
569 unsigned long timeout;
570 struct mid_q_entry *midQ;
571
572 if (ses == NULL) {
573 cERROR(1,("Null smb session"));
574 return -EIO;
575 }
576 if(ses->server == NULL) {
577 cERROR(1,("Null tcp session"));
578 return -EIO;
579 }
580
31ca3bc3
SF
581 if(ses->server->tcpStatus == CifsExiting)
582 return -ENOENT;
583
1da177e4
LT
584 /* Ensure that we do not send more than 50 overlapping requests
585 to the same server. We may make this configurable later or
586 use ses->maxReq */
587 if(long_op == -1) {
588 /* oplock breaks must not be held up */
589 atomic_inc(&ses->server->inFlight);
590 } else {
591 spin_lock(&GlobalMid_Lock);
592 while(1) {
275cde1a
SF
593 if(atomic_read(&ses->server->inFlight) >=
594 cifs_max_pending){
1da177e4 595 spin_unlock(&GlobalMid_Lock);
131afd0b
SF
596#ifdef CONFIG_CIFS_STATS2
597 atomic_inc(&ses->server->num_waiters);
598#endif
1da177e4
LT
599 wait_event(ses->server->request_q,
600 atomic_read(&ses->server->inFlight)
601 < cifs_max_pending);
131afd0b
SF
602#ifdef CONFIG_CIFS_STATS2
603 atomic_dec(&ses->server->num_waiters);
604#endif
1da177e4
LT
605 spin_lock(&GlobalMid_Lock);
606 } else {
607 if(ses->server->tcpStatus == CifsExiting) {
608 spin_unlock(&GlobalMid_Lock);
609 return -ENOENT;
610 }
611
612 /* can not count locking commands against total since
613 they are allowed to block on server */
614
615 if(long_op < 3) {
616 /* update # of requests on the wire to server */
617 atomic_inc(&ses->server->inFlight);
618 }
619 spin_unlock(&GlobalMid_Lock);
620 break;
621 }
622 }
623 }
624 /* make sure that we sign in the same order that we send on this socket
625 and avoid races inside tcp sendmsg code that could cause corruption
626 of smb data */
627
628 down(&ses->server->tcpSem);
629
630 if (ses->server->tcpStatus == CifsExiting) {
631 rc = -ENOENT;
632 goto out_unlock;
633 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
634 cFYI(1,("tcp session dead - return to caller to retry"));
635 rc = -EAGAIN;
636 goto out_unlock;
637 } else if (ses->status != CifsGood) {
638 /* check if SMB session is bad because we are setting it up */
639 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
640 (in_buf->Command != SMB_COM_NEGOTIATE)) {
641 rc = -EAGAIN;
642 goto out_unlock;
643 } /* else ok - we are setting up session */
644 }
645 midQ = AllocMidQEntry(in_buf, ses);
646 if (midQ == NULL) {
647 up(&ses->server->tcpSem);
648 /* If not lock req, update # of requests on wire to server */
649 if(long_op < 3) {
650 atomic_dec(&ses->server->inFlight);
651 wake_up(&ses->server->request_q);
652 }
653 return -ENOMEM;
654 }
655
656 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
657 up(&ses->server->tcpSem);
26a21b98 658 cERROR(1, ("Illegal length, greater than maximum frame, %d",
1da177e4
LT
659 in_buf->smb_buf_length));
660 DeleteMidQEntry(midQ);
661 /* If not lock req, update # of requests on wire to server */
662 if(long_op < 3) {
663 atomic_dec(&ses->server->inFlight);
664 wake_up(&ses->server->request_q);
665 }
666 return -EIO;
667 }
668
ad009ac9 669 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4
LT
670
671 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
672#ifdef CONFIG_CIFS_STATS2
673 atomic_inc(&ses->server->inSend);
674#endif
1da177e4
LT
675 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
676 (struct sockaddr *) &(ses->server->addr.sockAddr));
131afd0b
SF
677#ifdef CONFIG_CIFS_STATS2
678 atomic_dec(&ses->server->inSend);
1047abc1 679 midQ->when_sent = jiffies;
131afd0b 680#endif
1da177e4
LT
681 if(rc < 0) {
682 DeleteMidQEntry(midQ);
683 up(&ses->server->tcpSem);
684 /* If not lock req, update # of requests on wire to server */
685 if(long_op < 3) {
686 atomic_dec(&ses->server->inFlight);
687 wake_up(&ses->server->request_q);
688 }
689 return rc;
690 } else
691 up(&ses->server->tcpSem);
692 if (long_op == -1)
693 goto cifs_no_response_exit;
275cde1a 694 else if (long_op == 2) /* writes past end of file can take loong time */
37c0eb46 695 timeout = 180 * HZ;
1da177e4
LT
696 else if (long_op == 1)
697 timeout = 45 * HZ; /* should be greater than
698 servers oplock break timeout (about 43 seconds) */
699 else if (long_op > 2) {
700 timeout = MAX_SCHEDULE_TIMEOUT;
701 } else
702 timeout = 15 * HZ;
703 /* wait for 15 seconds or until woken up due to response arriving or
704 due to last connection to this server being unmounted */
705 if (signal_pending(current)) {
706 /* if signal pending do not hold up user for full smb timeout
707 but we still give response a change to complete */
708 timeout = 2 * HZ;
709 }
710
711 /* No user interrupts in wait - wreaks havoc with performance */
712 if(timeout != MAX_SCHEDULE_TIMEOUT) {
713 timeout += jiffies;
3a5ff61c
SF
714 /* although we prefer not to time out if the server is still
715 responding - we will time out if the server takes
716 more than 15 (or 45 or 180) seconds to respond to this request
717 and has not responded to any request from other threads
718 on this client within a second (note that it is not worth
719 grabbing the GlobalMid_Lock and slowing things down in this
720 wait event to more accurately check the lstrsp field on some
721 arch since we are already in an error path that will retry */
1da177e4
LT
722 wait_event(ses->server->response_q,
723 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
3a5ff61c
SF
724 (time_after(jiffies, timeout) &&
725 time_after(jiffies, ses->server->lstrp + HZ)) ||
1da177e4
LT
726 ((ses->server->tcpStatus != CifsGood) &&
727 (ses->server->tcpStatus != CifsNew)));
728 } else {
729 wait_event(ses->server->response_q,
730 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
731 ((ses->server->tcpStatus != CifsGood) &&
732 (ses->server->tcpStatus != CifsNew)));
733 }
734
735 spin_lock(&GlobalMid_Lock);
736 if (midQ->resp_buf) {
737 spin_unlock(&GlobalMid_Lock);
70ca734a 738 receive_len = midQ->resp_buf->smb_buf_length;
1da177e4 739 } else {
37c0eb46
SF
740 cERROR(1,("No response for cmd %d mid %d",
741 midQ->command, midQ->mid));
1da177e4
LT
742 if(midQ->midState == MID_REQUEST_SUBMITTED) {
743 if(ses->server->tcpStatus == CifsExiting)
744 rc = -EHOSTDOWN;
745 else {
746 ses->server->tcpStatus = CifsNeedReconnect;
747 midQ->midState = MID_RETRY_NEEDED;
748 }
749 }
750
751 if (rc != -EHOSTDOWN) {
752 if(midQ->midState == MID_RETRY_NEEDED) {
753 rc = -EAGAIN;
754 cFYI(1,("marking request for retry"));
755 } else {
756 rc = -EIO;
757 }
758 }
759 spin_unlock(&GlobalMid_Lock);
760 DeleteMidQEntry(midQ);
761 /* If not lock req, update # of requests on wire to server */
762 if(long_op < 3) {
763 atomic_dec(&ses->server->inFlight);
764 wake_up(&ses->server->request_q);
765 }
766 return rc;
767 }
768
769 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
ad009ac9 770 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1da177e4
LT
771 receive_len, xid));
772 rc = -EIO;
773 } else { /* rcvd frame is ok */
774
775 if (midQ->resp_buf && out_buf
776 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
777 out_buf->smb_buf_length = receive_len;
778 memcpy((char *)out_buf + 4,
779 (char *)midQ->resp_buf + 4,
780 receive_len);
781
782 dump_smb(out_buf, 92);
783 /* convert the length into a more usable form */
784 if((receive_len > 24) &&
ad009ac9
SF
785 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
786 SECMODE_SIGN_ENABLED))) {
787 rc = cifs_verify_signature(out_buf,
788 ses->server->mac_signing_key,
789 midQ->sequence_number+1);
790 if(rc) {
275cde1a
SF
791 cERROR(1,("Unexpected SMB signature"));
792 /* BB FIXME add code to kill session */
ad009ac9 793 }
1da177e4
LT
794 }
795
796 *pbytes_returned = out_buf->smb_buf_length;
797
ad009ac9 798 /* BB special case reconnect tid and uid here? */
1da177e4
LT
799 rc = map_smb_to_linux_error(out_buf);
800
801 /* convert ByteCount if necessary */
802 if (receive_len >=
803 sizeof (struct smb_hdr) -
804 4 /* do not count RFC1001 header */ +
805 (2 * out_buf->WordCount) + 2 /* bcc */ )
0f2b27c4 806 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1da177e4
LT
807 } else {
808 rc = -EIO;
ec637e3f 809 cERROR(1,("Bad MID state?"));
1da177e4
LT
810 }
811 }
812cifs_no_response_exit:
813 DeleteMidQEntry(midQ);
814
815 if(long_op < 3) {
816 atomic_dec(&ses->server->inFlight);
817 wake_up(&ses->server->request_q);
818 }
819
820 return rc;
821
822out_unlock:
823 up(&ses->server->tcpSem);
824 /* If not lock req, update # of requests on wire to server */
825 if(long_op < 3) {
826 atomic_dec(&ses->server->inFlight);
827 wake_up(&ses->server->request_q);
828 }
829
830 return rc;
831}