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