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