cifs: clean up sync_mid_result
[linux-block.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
74dd92a8
JL
366 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
367 mid->mid, mid->midState);
053d5034 368
74dd92a8
JL
369 spin_lock(&GlobalMid_Lock);
370 switch (mid->midState) {
371 case MID_RESPONSE_RECEIVED:
053d5034
JL
372 spin_unlock(&GlobalMid_Lock);
373 return rc;
74dd92a8
JL
374 case MID_REQUEST_SUBMITTED:
375 /* socket is going down, reject all calls */
376 if (server->tcpStatus == CifsExiting) {
377 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
378 __func__, mid->mid, mid->command, mid->midState);
053d5034 379 rc = -EHOSTDOWN;
74dd92a8 380 break;
053d5034 381 }
74dd92a8
JL
382 case MID_RETRY_NEEDED:
383 rc = -EAGAIN;
384 break;
385 default:
386 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
387 mid->mid, mid->midState);
388 rc = -EIO;
053d5034
JL
389 }
390 spin_unlock(&GlobalMid_Lock);
391
392 delete_mid(mid);
393 return rc;
394}
395
7ee1af76 396int
79a58d1f
SF
397SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
398 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 399 const int flags)
7ee1af76
JA
400{
401 int rc = 0;
133672ef 402 int long_op;
7ee1af76 403 unsigned int receive_len;
7ee1af76
JA
404 struct mid_q_entry *midQ;
405 struct smb_hdr *in_buf = iov[0].iov_base;
50c2f753 406
133672ef
SF
407 long_op = flags & CIFS_TIMEOUT_MASK;
408
7ee1af76
JA
409 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
410
411 if ((ses == NULL) || (ses->server == NULL)) {
412 cifs_small_buf_release(in_buf);
b6b38f70 413 cERROR(1, "Null session");
7ee1af76
JA
414 return -EIO;
415 }
416
79a58d1f 417 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76
JA
418 cifs_small_buf_release(in_buf);
419 return -ENOENT;
420 }
421
79a58d1f 422 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
423 to the same server. We may make this configurable later or
424 use ses->maxReq */
425
c5797a94 426 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
427 if (rc) {
428 cifs_small_buf_release(in_buf);
429 return rc;
430 }
431
79a58d1f 432 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
433 and avoid races inside tcp sendmsg code that could cause corruption
434 of smb data */
435
72ca545b 436 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
437
438 rc = allocate_mid(ses, in_buf, &midQ);
439 if (rc) {
72ca545b 440 mutex_unlock(&ses->server->srv_mutex);
4b8f930f 441 cifs_small_buf_release(in_buf);
7ee1af76 442 /* Update # of requests on wire to server */
79a58d1f 443 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
444 wake_up(&ses->server->request_q);
445 return rc;
1da177e4 446 }
79a58d1f 447 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
829049cb
VL
448 if (rc) {
449 mutex_unlock(&ses->server->srv_mutex);
450 cifs_small_buf_release(in_buf);
451 goto out;
452 }
1da177e4
LT
453
454 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
455#ifdef CONFIG_CIFS_STATS2
456 atomic_inc(&ses->server->inSend);
457#endif
0496e02d 458 rc = smb_sendv(ses->server, iov, n_vec);
131afd0b
SF
459#ifdef CONFIG_CIFS_STATS2
460 atomic_dec(&ses->server->inSend);
1047abc1 461 midQ->when_sent = jiffies;
131afd0b 462#endif
7ee1af76 463
72ca545b 464 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
465 cifs_small_buf_release(in_buf);
466
79a58d1f 467 if (rc < 0)
7ee1af76 468 goto out;
4b8f930f 469
0ade640e 470 if (long_op == CIFS_ASYNC_OP)
133672ef 471 goto out;
d6e04ae6 472
0ade640e
JL
473 rc = wait_for_response(ses->server, midQ);
474 if (rc != 0)
475 goto out;
d6e04ae6 476
053d5034
JL
477 rc = sync_mid_result(midQ, ses->server);
478 if (rc != 0) {
79a58d1f 479 atomic_dec(&ses->server->inFlight);
7ee1af76 480 wake_up(&ses->server->request_q);
d6e04ae6
SF
481 return rc;
482 }
50c2f753 483
8e4f2e8a
VL
484 receive_len = midQ->resp_buf->smb_buf_length;
485
d6e04ae6 486 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
b6b38f70
JP
487 cERROR(1, "Frame too large received. Length: %d Xid: %d",
488 receive_len, xid);
d6e04ae6 489 rc = -EIO;
2b2bdfba
SF
490 goto out;
491 }
492
493 /* rcvd frame is ok */
494
495 if (midQ->resp_buf &&
496 (midQ->midState == MID_RESPONSE_RECEIVED)) {
497
498 iov[0].iov_base = (char *)midQ->resp_buf;
499 if (midQ->largeBuf)
500 *pRespBufType = CIFS_LARGE_BUFFER;
501 else
502 *pRespBufType = CIFS_SMALL_BUFFER;
503 iov[0].iov_len = receive_len + 4;
504
505 dump_smb(midQ->resp_buf, 80);
506 /* convert the length into a more usable form */
507 if ((receive_len > 24) &&
508 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
509 SECMODE_SIGN_ENABLED))) {
510 rc = cifs_verify_signature(midQ->resp_buf,
21e73393 511 ses->server,
d6e04ae6 512 midQ->sequence_number+1);
2b2bdfba 513 if (rc) {
b6b38f70 514 cERROR(1, "Unexpected SMB signature");
2b2bdfba 515 /* BB FIXME add code to kill session */
d6e04ae6 516 }
d6e04ae6 517 }
2b2bdfba
SF
518
519 /* BB special case reconnect tid and uid here? */
520 rc = map_smb_to_linux_error(midQ->resp_buf,
521 flags & CIFS_LOG_ERROR);
522
523 /* convert ByteCount if necessary */
524 if (receive_len >= sizeof(struct smb_hdr) - 4
525 /* do not count RFC1001 header */ +
526 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
527 BCC(midQ->resp_buf) =
528 le16_to_cpu(BCC_LE(midQ->resp_buf));
529 if ((flags & CIFS_NO_RESP) == 0)
530 midQ->resp_buf = NULL; /* mark it so buf will
531 not be freed by
ddc8cf8f 532 delete_mid */
2b2bdfba
SF
533 } else {
534 rc = -EIO;
b6b38f70 535 cFYI(1, "Bad MID state?");
d6e04ae6 536 }
1da177e4 537
7ee1af76 538out:
ddc8cf8f 539 delete_mid(midQ);
79a58d1f 540 atomic_dec(&ses->server->inFlight);
7ee1af76 541 wake_up(&ses->server->request_q);
1da177e4 542
d6e04ae6
SF
543 return rc;
544}
1da177e4
LT
545
546int
547SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
548 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
549 int *pbytes_returned, const int long_op)
550{
551 int rc = 0;
552 unsigned int receive_len;
1da177e4
LT
553 struct mid_q_entry *midQ;
554
555 if (ses == NULL) {
b6b38f70 556 cERROR(1, "Null smb session");
1da177e4
LT
557 return -EIO;
558 }
79a58d1f 559 if (ses->server == NULL) {
b6b38f70 560 cERROR(1, "Null tcp session");
1da177e4
LT
561 return -EIO;
562 }
563
79a58d1f 564 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
565 return -ENOENT;
566
79a58d1f 567 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
568 to the same server. We may make this configurable later or
569 use ses->maxReq */
1da177e4 570
6d9c6d54 571 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
b6b38f70
JP
572 cERROR(1, "Illegal length, greater than maximum frame, %d",
573 in_buf->smb_buf_length);
6d9c6d54
VL
574 return -EIO;
575 }
576
c5797a94 577 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
578 if (rc)
579 return rc;
580
79a58d1f 581 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
582 and avoid races inside tcp sendmsg code that could cause corruption
583 of smb data */
584
72ca545b 585 mutex_lock(&ses->server->srv_mutex);
1da177e4 586
7ee1af76
JA
587 rc = allocate_mid(ses, in_buf, &midQ);
588 if (rc) {
72ca545b 589 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 590 /* Update # of requests on wire to server */
79a58d1f 591 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
592 wake_up(&ses->server->request_q);
593 return rc;
1da177e4
LT
594 }
595
ad009ac9 596 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb
VL
597 if (rc) {
598 mutex_unlock(&ses->server->srv_mutex);
599 goto out;
600 }
1da177e4
LT
601
602 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
603#ifdef CONFIG_CIFS_STATS2
604 atomic_inc(&ses->server->inSend);
605#endif
0496e02d 606 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
131afd0b
SF
607#ifdef CONFIG_CIFS_STATS2
608 atomic_dec(&ses->server->inSend);
1047abc1 609 midQ->when_sent = jiffies;
131afd0b 610#endif
72ca545b 611 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 612
79a58d1f 613 if (rc < 0)
7ee1af76
JA
614 goto out;
615
0ade640e 616 if (long_op == CIFS_ASYNC_OP)
7ee1af76 617 goto out;
1da177e4 618
0ade640e
JL
619 rc = wait_for_response(ses->server, midQ);
620 if (rc != 0)
621 goto out;
1da177e4 622
053d5034
JL
623 rc = sync_mid_result(midQ, ses->server);
624 if (rc != 0) {
79a58d1f 625 atomic_dec(&ses->server->inFlight);
7ee1af76 626 wake_up(&ses->server->request_q);
1da177e4
LT
627 return rc;
628 }
50c2f753 629
8e4f2e8a
VL
630 receive_len = midQ->resp_buf->smb_buf_length;
631
1da177e4 632 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
b6b38f70
JP
633 cERROR(1, "Frame too large received. Length: %d Xid: %d",
634 receive_len, xid);
1da177e4 635 rc = -EIO;
2b2bdfba
SF
636 goto out;
637 }
638
639 /* rcvd frame is ok */
640
641 if (midQ->resp_buf && out_buf
642 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
643 out_buf->smb_buf_length = receive_len;
644 memcpy((char *)out_buf + 4,
645 (char *)midQ->resp_buf + 4,
646 receive_len);
647
648 dump_smb(out_buf, 92);
649 /* convert the length into a more usable form */
650 if ((receive_len > 24) &&
651 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
652 SECMODE_SIGN_ENABLED))) {
653 rc = cifs_verify_signature(out_buf,
21e73393 654 ses->server,
ad009ac9 655 midQ->sequence_number+1);
2b2bdfba 656 if (rc) {
b6b38f70 657 cERROR(1, "Unexpected SMB signature");
2b2bdfba 658 /* BB FIXME add code to kill session */
1da177e4 659 }
2b2bdfba 660 }
1da177e4 661
2b2bdfba 662 *pbytes_returned = out_buf->smb_buf_length;
1da177e4 663
2b2bdfba
SF
664 /* BB special case reconnect tid and uid here? */
665 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4 666
2b2bdfba
SF
667 /* convert ByteCount if necessary */
668 if (receive_len >= sizeof(struct smb_hdr) - 4
669 /* do not count RFC1001 header */ +
670 (2 * out_buf->WordCount) + 2 /* bcc */ )
671 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
672 } else {
673 rc = -EIO;
b6b38f70 674 cERROR(1, "Bad MID state?");
1da177e4 675 }
7ee1af76
JA
676
677out:
ddc8cf8f 678 delete_mid(midQ);
79a58d1f 679 atomic_dec(&ses->server->inFlight);
7ee1af76 680 wake_up(&ses->server->request_q);
1da177e4 681
7ee1af76
JA
682 return rc;
683}
1da177e4 684
7ee1af76
JA
685/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
686
687static int
688send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
689 struct mid_q_entry *midQ)
690{
691 int rc = 0;
692 struct cifsSesInfo *ses = tcon->ses;
693 __u16 mid = in_buf->Mid;
694
695 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
696 in_buf->Mid = mid;
72ca545b 697 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
698 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
699 if (rc) {
72ca545b 700 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
701 return rc;
702 }
0496e02d 703 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
72ca545b 704 mutex_unlock(&ses->server->srv_mutex);
1da177e4 705 return rc;
7ee1af76
JA
706}
707
708/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
709 blocking lock to return. */
710
711static int
712send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
713 struct smb_hdr *in_buf,
714 struct smb_hdr *out_buf)
715{
716 int bytes_returned;
717 struct cifsSesInfo *ses = tcon->ses;
718 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
719
720 /* We just modify the current in_buf to change
721 the type of lock from LOCKING_ANDX_SHARED_LOCK
722 or LOCKING_ANDX_EXCLUSIVE_LOCK to
723 LOCKING_ANDX_CANCEL_LOCK. */
724
725 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
726 pSMB->Timeout = 0;
727 pSMB->hdr.Mid = GetNextMid(ses->server);
728
729 return SendReceive(xid, ses, in_buf, out_buf,
133672ef 730 &bytes_returned, CIFS_STD_OP);
7ee1af76
JA
731}
732
733int
734SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
735 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
736 int *pbytes_returned)
737{
738 int rc = 0;
739 int rstart = 0;
740 unsigned int receive_len;
741 struct mid_q_entry *midQ;
742 struct cifsSesInfo *ses;
743
744 if (tcon == NULL || tcon->ses == NULL) {
b6b38f70 745 cERROR(1, "Null smb session");
7ee1af76
JA
746 return -EIO;
747 }
748 ses = tcon->ses;
749
79a58d1f 750 if (ses->server == NULL) {
b6b38f70 751 cERROR(1, "Null tcp session");
7ee1af76
JA
752 return -EIO;
753 }
754
79a58d1f 755 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
756 return -ENOENT;
757
79a58d1f 758 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
759 to the same server. We may make this configurable later or
760 use ses->maxReq */
761
6d9c6d54 762 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
b6b38f70
JP
763 cERROR(1, "Illegal length, greater than maximum frame, %d",
764 in_buf->smb_buf_length);
6d9c6d54
VL
765 return -EIO;
766 }
767
c5797a94 768 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
7ee1af76
JA
769 if (rc)
770 return rc;
771
79a58d1f 772 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
773 and avoid races inside tcp sendmsg code that could cause corruption
774 of smb data */
775
72ca545b 776 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
777
778 rc = allocate_mid(ses, in_buf, &midQ);
779 if (rc) {
72ca545b 780 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
781 return rc;
782 }
783
7ee1af76 784 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb 785 if (rc) {
ddc8cf8f 786 delete_mid(midQ);
829049cb
VL
787 mutex_unlock(&ses->server->srv_mutex);
788 return rc;
789 }
1da177e4 790
7ee1af76
JA
791 midQ->midState = MID_REQUEST_SUBMITTED;
792#ifdef CONFIG_CIFS_STATS2
793 atomic_inc(&ses->server->inSend);
794#endif
0496e02d 795 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
7ee1af76
JA
796#ifdef CONFIG_CIFS_STATS2
797 atomic_dec(&ses->server->inSend);
798 midQ->when_sent = jiffies;
799#endif
72ca545b 800 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 801
79a58d1f 802 if (rc < 0) {
ddc8cf8f 803 delete_mid(midQ);
7ee1af76
JA
804 return rc;
805 }
806
807 /* Wait for a reply - allow signals to interrupt. */
808 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 809 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
810 ((ses->server->tcpStatus != CifsGood) &&
811 (ses->server->tcpStatus != CifsNew)));
812
813 /* Were we interrupted by a signal ? */
814 if ((rc == -ERESTARTSYS) &&
815 (midQ->midState == MID_REQUEST_SUBMITTED) &&
816 ((ses->server->tcpStatus == CifsGood) ||
817 (ses->server->tcpStatus == CifsNew))) {
818
819 if (in_buf->Command == SMB_COM_TRANSACTION2) {
820 /* POSIX lock. We send a NT_CANCEL SMB to cause the
821 blocking lock to return. */
822
823 rc = send_nt_cancel(tcon, in_buf, midQ);
824 if (rc) {
ddc8cf8f 825 delete_mid(midQ);
7ee1af76
JA
826 return rc;
827 }
828 } else {
829 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
830 to cause the blocking lock to return. */
831
832 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
833
834 /* If we get -ENOLCK back the lock may have
835 already been removed. Don't exit in this case. */
836 if (rc && rc != -ENOLCK) {
ddc8cf8f 837 delete_mid(midQ);
7ee1af76
JA
838 return rc;
839 }
840 }
841
0ade640e 842 if (wait_for_response(ses->server, midQ) == 0) {
7ee1af76
JA
843 /* We got the response - restart system call. */
844 rstart = 1;
845 }
846 }
847
053d5034
JL
848 rc = sync_mid_result(midQ, ses->server);
849 if (rc != 0)
7ee1af76 850 return rc;
50c2f753 851
053d5034 852 receive_len = midQ->resp_buf->smb_buf_length;
7ee1af76 853 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
b6b38f70
JP
854 cERROR(1, "Frame too large received. Length: %d Xid: %d",
855 receive_len, xid);
7ee1af76 856 rc = -EIO;
17c8bfed
VL
857 goto out;
858 }
7ee1af76 859
17c8bfed 860 /* rcvd frame is ok */
7ee1af76 861
ac6a3ef4 862 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
698e96a8 863 rc = -EIO;
b6b38f70 864 cERROR(1, "Bad MID state?");
698e96a8
VL
865 goto out;
866 }
1da177e4 867
698e96a8
VL
868 out_buf->smb_buf_length = receive_len;
869 memcpy((char *)out_buf + 4,
870 (char *)midQ->resp_buf + 4,
871 receive_len);
872
873 dump_smb(out_buf, 92);
874 /* convert the length into a more usable form */
875 if ((receive_len > 24) &&
876 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
877 SECMODE_SIGN_ENABLED))) {
878 rc = cifs_verify_signature(out_buf,
21e73393 879 ses->server,
698e96a8
VL
880 midQ->sequence_number+1);
881 if (rc) {
b6b38f70 882 cERROR(1, "Unexpected SMB signature");
698e96a8 883 /* BB FIXME add code to kill session */
7ee1af76 884 }
698e96a8 885 }
17c8bfed 886
698e96a8 887 *pbytes_returned = out_buf->smb_buf_length;
17c8bfed 888
698e96a8
VL
889 /* BB special case reconnect tid and uid here? */
890 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
17c8bfed 891
698e96a8
VL
892 /* convert ByteCount if necessary */
893 if (receive_len >= sizeof(struct smb_hdr) - 4
894 /* do not count RFC1001 header */ +
895 (2 * out_buf->WordCount) + 2 /* bcc */ )
896 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
17c8bfed
VL
897
898out:
ddc8cf8f 899 delete_mid(midQ);
7ee1af76
JA
900 if (rstart && rc == -EACCES)
901 return -ERESTARTSYS;
1da177e4
LT
902 return rc;
903}