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