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