]> git.ipfire.org Git - people/ms/linux.git/blame - fs/cifs/transport.c
CIFS: SMBD: Implement function to send data via RDMA send
[people/ms/linux.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>
b8eed283 30#include <linux/tcp.h>
2f8b5444 31#include <linux/bvec.h>
97bc00b3 32#include <linux/highmem.h>
7c0f6ba6 33#include <linux/uaccess.h>
1da177e4
LT
34#include <asm/processor.h>
35#include <linux/mempool.h>
36#include "cifspdu.h"
37#include "cifsglob.h"
38#include "cifsproto.h"
39#include "cifs_debug.h"
50c2f753 40
3cecf486
RS
41/* Max number of iovectors we can use off the stack when sending requests. */
42#define CIFS_MAX_IOV_SIZE 8
43
2dc7e1c0
PS
44void
45cifs_wake_up_task(struct mid_q_entry *mid)
2b84a36c
JL
46{
47 wake_up_process(mid->callback_data);
48}
49
a6827c18 50struct mid_q_entry *
24b9b06b 51AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
1da177e4
LT
52{
53 struct mid_q_entry *temp;
54
24b9b06b 55 if (server == NULL) {
f96637be 56 cifs_dbg(VFS, "Null TCP session in AllocMidQEntry\n");
1da177e4
LT
57 return NULL;
58 }
50c2f753 59
232087cb 60 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
a6f74e80
N
61 memset(temp, 0, sizeof(struct mid_q_entry));
62 temp->mid = get_mid(smb_buffer);
63 temp->pid = current->pid;
64 temp->command = cpu_to_le16(smb_buffer->Command);
65 cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
1047abc1 66 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
a6f74e80
N
67 /* when mid allocated can be before when sent */
68 temp->when_alloc = jiffies;
69 temp->server = server;
2b84a36c 70
a6f74e80
N
71 /*
72 * The default is for the mid to be synchronous, so the
73 * default callback just wakes up the current task.
74 */
75 temp->callback = cifs_wake_up_task;
76 temp->callback_data = current;
1da177e4 77
1da177e4 78 atomic_inc(&midCount);
7c9421e1 79 temp->mid_state = MID_REQUEST_ALLOCATED;
1da177e4
LT
80 return temp;
81}
82
766fdbb5 83void
1da177e4
LT
84DeleteMidQEntry(struct mid_q_entry *midEntry)
85{
1047abc1 86#ifdef CONFIG_CIFS_STATS2
2dc7e1c0 87 __le16 command = midEntry->server->vals->lock_cmd;
1047abc1
SF
88 unsigned long now;
89#endif
7c9421e1 90 midEntry->mid_state = MID_FREE;
8097531a 91 atomic_dec(&midCount);
7c9421e1 92 if (midEntry->large_buf)
b8643e1b
SF
93 cifs_buf_release(midEntry->resp_buf);
94 else
95 cifs_small_buf_release(midEntry->resp_buf);
1047abc1
SF
96#ifdef CONFIG_CIFS_STATS2
97 now = jiffies;
98 /* commands taking longer than one second are indications that
99 something is wrong, unless it is quite a slow link or server */
4328fea7 100 if (time_after(now, midEntry->when_alloc + HZ)) {
2dc7e1c0 101 if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
0b456f04 102 pr_debug(" CIFS slow rsp: cmd %d mid %llu",
1047abc1 103 midEntry->command, midEntry->mid);
0b456f04 104 pr_info(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
1047abc1
SF
105 now - midEntry->when_alloc,
106 now - midEntry->when_sent,
107 now - midEntry->when_received);
108 }
109 }
110#endif
1da177e4
LT
111 mempool_free(midEntry, cifs_mid_poolp);
112}
113
3c1bf7e4
PS
114void
115cifs_delete_mid(struct mid_q_entry *mid)
ddc8cf8f
JL
116{
117 spin_lock(&GlobalMid_Lock);
118 list_del(&mid->qhead);
119 spin_unlock(&GlobalMid_Lock);
120
121 DeleteMidQEntry(mid);
122}
123
6f49f46b
JL
124/*
125 * smb_send_kvec - send an array of kvecs to the server
126 * @server: Server to send the data to
3ab3f2a1 127 * @smb_msg: Message to send
6f49f46b
JL
128 * @sent: amount of data sent on socket is stored here
129 *
130 * Our basic "send data to server" function. Should be called with srv_mutex
131 * held. The caller is responsible for handling the results.
132 */
d6e04ae6 133static int
3ab3f2a1
AV
134smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
135 size_t *sent)
1da177e4
LT
136{
137 int rc = 0;
3ab3f2a1 138 int retries = 0;
edf1ae40 139 struct socket *ssocket = server->ssocket;
50c2f753 140
6f49f46b
JL
141 *sent = 0;
142
3ab3f2a1
AV
143 smb_msg->msg_name = (struct sockaddr *) &server->dstaddr;
144 smb_msg->msg_namelen = sizeof(struct sockaddr);
145 smb_msg->msg_control = NULL;
146 smb_msg->msg_controllen = 0;
0496e02d 147 if (server->noblocksnd)
3ab3f2a1 148 smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
edf1ae40 149 else
3ab3f2a1 150 smb_msg->msg_flags = MSG_NOSIGNAL;
1da177e4 151
3ab3f2a1 152 while (msg_data_left(smb_msg)) {
6f49f46b
JL
153 /*
154 * If blocking send, we try 3 times, since each can block
155 * for 5 seconds. For nonblocking we have to try more
156 * but wait increasing amounts of time allowing time for
157 * socket to clear. The overall time we wait in either
158 * case to send on the socket is about 15 seconds.
159 * Similarly we wait for 15 seconds for a response from
160 * the server in SendReceive[2] for the server to send
161 * a response back for most types of requests (except
162 * SMB Write past end of file which can be slow, and
163 * blocking lock operations). NFS waits slightly longer
164 * than CIFS, but this can make it take longer for
165 * nonresponsive servers to be detected and 15 seconds
166 * is more than enough time for modern networks to
167 * send a packet. In most cases if we fail to send
168 * after the retries we will kill the socket and
169 * reconnect which may clear the network problem.
170 */
3ab3f2a1 171 rc = sock_sendmsg(ssocket, smb_msg);
ce6c44e4 172 if (rc == -EAGAIN) {
3ab3f2a1
AV
173 retries++;
174 if (retries >= 14 ||
175 (!server->noblocksnd && (retries > 2))) {
f96637be
JP
176 cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
177 ssocket);
3ab3f2a1 178 return -EAGAIN;
1da177e4 179 }
3ab3f2a1 180 msleep(1 << retries);
1da177e4
LT
181 continue;
182 }
6f49f46b 183
79a58d1f 184 if (rc < 0)
3ab3f2a1 185 return rc;
6f49f46b 186
79a58d1f 187 if (rc == 0) {
3e84469d
SF
188 /* should never happen, letting socket clear before
189 retrying is our only obvious option here */
f96637be 190 cifs_dbg(VFS, "tcp sent no data\n");
3e84469d
SF
191 msleep(500);
192 continue;
d6e04ae6 193 }
6f49f46b 194
3ab3f2a1
AV
195 /* send was at least partially successful */
196 *sent += rc;
197 retries = 0; /* in case we get ENOSPC on the next send */
1da177e4 198 }
3ab3f2a1 199 return 0;
97bc00b3
JL
200}
201
a26054d1
JL
202static unsigned long
203rqst_len(struct smb_rqst *rqst)
204{
205 unsigned int i;
206 struct kvec *iov = rqst->rq_iov;
207 unsigned long buflen = 0;
208
209 /* total up iov array first */
210 for (i = 0; i < rqst->rq_nvec; i++)
211 buflen += iov[i].iov_len;
212
213 /* add in the page array if there is one */
214 if (rqst->rq_npages) {
215 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
216 buflen += rqst->rq_tailsz;
217 }
218
219 return buflen;
220}
221
6f49f46b 222static int
7fb8986e 223__smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
6f49f46b
JL
224{
225 int rc;
226 struct kvec *iov = rqst->rq_iov;
227 int n_vec = rqst->rq_nvec;
228 unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
a26054d1 229 unsigned long send_length;
97bc00b3 230 unsigned int i;
3ab3f2a1 231 size_t total_len = 0, sent, size;
b8eed283 232 struct socket *ssocket = server->ssocket;
3ab3f2a1 233 struct msghdr smb_msg;
b8eed283 234 int val = 1;
6f49f46b 235
ea702b80
JL
236 if (ssocket == NULL)
237 return -ENOTSOCK;
238
a26054d1
JL
239 /* sanity check send length */
240 send_length = rqst_len(rqst);
241 if (send_length != smb_buf_length + 4) {
242 WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
243 send_length, smb_buf_length);
244 return -EIO;
245 }
246
738f9de5
PS
247 if (n_vec < 2)
248 return -EIO;
249
f96637be 250 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
6f49f46b 251 dump_smb(iov[0].iov_base, iov[0].iov_len);
738f9de5 252 dump_smb(iov[1].iov_base, iov[1].iov_len);
6f49f46b 253
b8eed283
JL
254 /* cork the socket */
255 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
256 (char *)&val, sizeof(val));
257
3ab3f2a1
AV
258 size = 0;
259 for (i = 0; i < n_vec; i++)
260 size += iov[i].iov_len;
261
262 iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size);
263
264 rc = smb_send_kvec(server, &smb_msg, &sent);
97bc00b3
JL
265 if (rc < 0)
266 goto uncork;
267
268 total_len += sent;
269
270 /* now walk the page array and send each page in it */
271 for (i = 0; i < rqst->rq_npages; i++) {
3ab3f2a1
AV
272 size_t len = i == rqst->rq_npages - 1
273 ? rqst->rq_tailsz
274 : rqst->rq_pagesz;
275 struct bio_vec bvec = {
276 .bv_page = rqst->rq_pages[i],
277 .bv_len = len
278 };
279 iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
280 &bvec, 1, len);
281 rc = smb_send_kvec(server, &smb_msg, &sent);
97bc00b3
JL
282 if (rc < 0)
283 break;
284
285 total_len += sent;
286 }
1da177e4 287
97bc00b3 288uncork:
b8eed283
JL
289 /* uncork it */
290 val = 0;
291 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
292 (char *)&val, sizeof(val));
293
edf1ae40 294 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
f96637be
JP
295 cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
296 smb_buf_length + 4, total_len);
6f49f46b
JL
297 /*
298 * If we have only sent part of an SMB then the next SMB could
299 * be taken as the remainder of this one. We need to kill the
300 * socket so the server throws away the partial SMB
301 */
edf1ae40
SF
302 server->tcpStatus = CifsNeedReconnect;
303 }
304
d804d41d 305 if (rc < 0 && rc != -EINTR)
f96637be
JP
306 cifs_dbg(VFS, "Error %d sending data on socket to server\n",
307 rc);
d804d41d 308 else
1da177e4 309 rc = 0;
1da177e4
LT
310
311 return rc;
312}
313
6f49f46b 314static int
7fb8986e 315smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst, int flags)
6f49f46b 316{
7fb8986e
PS
317 struct smb_rqst cur_rqst;
318 int rc;
319
320 if (!(flags & CIFS_TRANSFORM_REQ))
321 return __smb_send_rqst(server, rqst);
322
323 if (!server->ops->init_transform_rq ||
324 !server->ops->free_transform_rq) {
325 cifs_dbg(VFS, "Encryption requested but transform callbacks are missed\n");
326 return -EIO;
327 }
6f49f46b 328
7fb8986e
PS
329 rc = server->ops->init_transform_rq(server, &cur_rqst, rqst);
330 if (rc)
331 return rc;
332
333 rc = __smb_send_rqst(server, &cur_rqst);
334 server->ops->free_transform_rq(&cur_rqst);
335 return rc;
6f49f46b
JL
336}
337
0496e02d
JL
338int
339smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
340 unsigned int smb_buf_length)
341{
738f9de5 342 struct kvec iov[2];
7fb8986e
PS
343 struct smb_rqst rqst = { .rq_iov = iov,
344 .rq_nvec = 2 };
0496e02d 345
738f9de5
PS
346 iov[0].iov_base = smb_buffer;
347 iov[0].iov_len = 4;
348 iov[1].iov_base = (char *)smb_buffer + 4;
349 iov[1].iov_len = smb_buf_length;
0496e02d 350
7fb8986e 351 return __smb_send_rqst(server, &rqst);
0496e02d
JL
352}
353
fc40f9cf 354static int
a891f0f8 355wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
bc205ed1 356 int *credits)
1da177e4 357{
5bc59498
PS
358 int rc;
359
fc40f9cf 360 spin_lock(&server->req_lock);
a891f0f8 361 if (timeout == CIFS_ASYNC_OP) {
1da177e4 362 /* oplock breaks must not be held up */
fc40f9cf 363 server->in_flight++;
bc205ed1 364 *credits -= 1;
fc40f9cf 365 spin_unlock(&server->req_lock);
27a97a61
VL
366 return 0;
367 }
368
27a97a61 369 while (1) {
bc205ed1 370 if (*credits <= 0) {
fc40f9cf 371 spin_unlock(&server->req_lock);
789e6661 372 cifs_num_waiters_inc(server);
5bc59498 373 rc = wait_event_killable(server->request_q,
bc205ed1 374 has_credits(server, credits));
789e6661 375 cifs_num_waiters_dec(server);
5bc59498
PS
376 if (rc)
377 return rc;
fc40f9cf 378 spin_lock(&server->req_lock);
27a97a61 379 } else {
c5797a94 380 if (server->tcpStatus == CifsExiting) {
fc40f9cf 381 spin_unlock(&server->req_lock);
27a97a61 382 return -ENOENT;
1da177e4 383 }
27a97a61 384
2d86dbc9
PS
385 /*
386 * Can not count locking commands against total
387 * as they are allowed to block on server.
388 */
27a97a61
VL
389
390 /* update # of requests on the wire to server */
a891f0f8 391 if (timeout != CIFS_BLOCKING_OP) {
bc205ed1 392 *credits -= 1;
fc40f9cf 393 server->in_flight++;
2d86dbc9 394 }
fc40f9cf 395 spin_unlock(&server->req_lock);
27a97a61 396 break;
1da177e4
LT
397 }
398 }
7ee1af76
JA
399 return 0;
400}
1da177e4 401
bc205ed1 402static int
a891f0f8
PS
403wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
404 const int optype)
bc205ed1 405{
eb4c7df6
SP
406 int *val;
407
408 val = server->ops->get_credits_field(server, optype);
409 /* Since an echo is already inflight, no need to wait to send another */
410 if (*val <= 0 && optype == CIFS_ECHO_OP)
411 return -EAGAIN;
412 return wait_for_free_credits(server, timeout, val);
bc205ed1
PS
413}
414
cb7e9eab
PS
415int
416cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
417 unsigned int *num, unsigned int *credits)
418{
419 *num = size;
420 *credits = 0;
421 return 0;
422}
423
96daf2b0 424static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
7ee1af76
JA
425 struct mid_q_entry **ppmidQ)
426{
1da177e4 427 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 428 return -ENOENT;
8fbbd365
VL
429 }
430
431 if (ses->server->tcpStatus == CifsNeedReconnect) {
f96637be 432 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
7ee1af76 433 return -EAGAIN;
8fbbd365
VL
434 }
435
7f48558e 436 if (ses->status == CifsNew) {
79a58d1f 437 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926 438 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 439 return -EAGAIN;
ad7a2926 440 /* else ok - we are setting up session */
1da177e4 441 }
7f48558e
SP
442
443 if (ses->status == CifsExiting) {
444 /* check if SMB session is bad because we are setting it up */
445 if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
446 return -EAGAIN;
447 /* else ok - we are shutting down session */
448 }
449
24b9b06b 450 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364 451 if (*ppmidQ == NULL)
7ee1af76 452 return -ENOMEM;
ddc8cf8f
JL
453 spin_lock(&GlobalMid_Lock);
454 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
455 spin_unlock(&GlobalMid_Lock);
7ee1af76
JA
456 return 0;
457}
458
0ade640e
JL
459static int
460wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
7ee1af76 461{
0ade640e 462 int error;
7ee1af76 463
5853cc2a 464 error = wait_event_freezekillable_unsafe(server->response_q,
7c9421e1 465 midQ->mid_state != MID_REQUEST_SUBMITTED);
0ade640e
JL
466 if (error < 0)
467 return -ERESTARTSYS;
7ee1af76 468
0ade640e 469 return 0;
7ee1af76
JA
470}
471
fec344e3
JL
472struct mid_q_entry *
473cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
792af7b0
PS
474{
475 int rc;
fec344e3 476 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
792af7b0
PS
477 struct mid_q_entry *mid;
478
738f9de5
PS
479 if (rqst->rq_iov[0].iov_len != 4 ||
480 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
481 return ERR_PTR(-EIO);
482
792af7b0 483 /* enable signing if server requires it */
38d77c50 484 if (server->sign)
792af7b0
PS
485 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
486
487 mid = AllocMidQEntry(hdr, server);
488 if (mid == NULL)
fec344e3 489 return ERR_PTR(-ENOMEM);
792af7b0 490
fec344e3 491 rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
ffc61ccb
SP
492 if (rc) {
493 DeleteMidQEntry(mid);
fec344e3 494 return ERR_PTR(rc);
ffc61ccb
SP
495 }
496
fec344e3 497 return mid;
792af7b0 498}
133672ef 499
a6827c18
JL
500/*
501 * Send a SMB request and set the callback function in the mid to handle
502 * the result. Caller is responsible for dealing with timeouts.
503 */
504int
fec344e3 505cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
9b7c18a2
PS
506 mid_receive_t *receive, mid_callback_t *callback,
507 mid_handle_t *handle, void *cbdata, const int flags)
a6827c18 508{
a891f0f8 509 int rc, timeout, optype;
a6827c18 510 struct mid_q_entry *mid;
cb7e9eab 511 unsigned int credits = 0;
a6827c18 512
a891f0f8
PS
513 timeout = flags & CIFS_TIMEOUT_MASK;
514 optype = flags & CIFS_OP_MASK;
515
cb7e9eab
PS
516 if ((flags & CIFS_HAS_CREDITS) == 0) {
517 rc = wait_for_free_request(server, timeout, optype);
518 if (rc)
519 return rc;
520 credits = 1;
521 }
a6827c18
JL
522
523 mutex_lock(&server->srv_mutex);
fec344e3
JL
524 mid = server->ops->setup_async_request(server, rqst);
525 if (IS_ERR(mid)) {
a6827c18 526 mutex_unlock(&server->srv_mutex);
cb7e9eab 527 add_credits_and_wake_if(server, credits, optype);
fec344e3 528 return PTR_ERR(mid);
a6827c18
JL
529 }
530
44d22d84 531 mid->receive = receive;
a6827c18
JL
532 mid->callback = callback;
533 mid->callback_data = cbdata;
9b7c18a2 534 mid->handle = handle;
7c9421e1 535 mid->mid_state = MID_REQUEST_SUBMITTED;
789e6661 536
ffc61ccb
SP
537 /* put it on the pending_mid_q */
538 spin_lock(&GlobalMid_Lock);
539 list_add_tail(&mid->qhead, &server->pending_mid_q);
540 spin_unlock(&GlobalMid_Lock);
541
93d2cb6c
LL
542 /*
543 * Need to store the time in mid before calling I/O. For call_async,
544 * I/O response may come back and free the mid entry on another thread.
545 */
546 cifs_save_when_sent(mid);
789e6661 547 cifs_in_send_inc(server);
7fb8986e 548 rc = smb_send_rqst(server, rqst, flags);
789e6661 549 cifs_in_send_dec(server);
ad313cb8 550
820962dc 551 if (rc < 0) {
ad313cb8 552 server->sequence_number -= 2;
820962dc
RV
553 cifs_delete_mid(mid);
554 }
555
a6827c18 556 mutex_unlock(&server->srv_mutex);
789e6661 557
ffc61ccb
SP
558 if (rc == 0)
559 return 0;
a6827c18 560
cb7e9eab 561 add_credits_and_wake_if(server, credits, optype);
a6827c18
JL
562 return rc;
563}
564
133672ef
SF
565/*
566 *
567 * Send an SMB Request. No response info (other than return code)
568 * needs to be parsed.
569 *
570 * flags indicate the type of request buffer and how long to wait
571 * and whether to log NT STATUS code (error) before mapping it to POSIX error
572 *
573 */
574int
96daf2b0 575SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
792af7b0 576 char *in_buf, int flags)
133672ef
SF
577{
578 int rc;
579 struct kvec iov[1];
da502f7d 580 struct kvec rsp_iov;
133672ef
SF
581 int resp_buf_type;
582
792af7b0
PS
583 iov[0].iov_base = in_buf;
584 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
133672ef 585 flags |= CIFS_NO_RESP;
da502f7d 586 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
f96637be 587 cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
90c81e0b 588
133672ef
SF
589 return rc;
590}
591
053d5034 592static int
3c1105df 593cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
053d5034
JL
594{
595 int rc = 0;
596
f96637be
JP
597 cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
598 __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
053d5034 599
74dd92a8 600 spin_lock(&GlobalMid_Lock);
7c9421e1 601 switch (mid->mid_state) {
74dd92a8 602 case MID_RESPONSE_RECEIVED:
053d5034
JL
603 spin_unlock(&GlobalMid_Lock);
604 return rc;
74dd92a8
JL
605 case MID_RETRY_NEEDED:
606 rc = -EAGAIN;
607 break;
71823baf
JL
608 case MID_RESPONSE_MALFORMED:
609 rc = -EIO;
610 break;
3c1105df
JL
611 case MID_SHUTDOWN:
612 rc = -EHOSTDOWN;
613 break;
74dd92a8 614 default:
3c1105df 615 list_del_init(&mid->qhead);
f96637be
JP
616 cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
617 __func__, mid->mid, mid->mid_state);
74dd92a8 618 rc = -EIO;
053d5034
JL
619 }
620 spin_unlock(&GlobalMid_Lock);
621
2b84a36c 622 DeleteMidQEntry(mid);
053d5034
JL
623 return rc;
624}
625
121b046a 626static inline int
fb2036d8
PS
627send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
628 struct mid_q_entry *mid)
76dcc26f 629{
121b046a 630 return server->ops->send_cancel ?
fb2036d8 631 server->ops->send_cancel(server, rqst, mid) : 0;
76dcc26f
JL
632}
633
2c8f981d
JL
634int
635cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
636 bool log_error)
637{
792af7b0 638 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
826a95e4
JL
639
640 dump_smb(mid->resp_buf, min_t(u32, 92, len));
2c8f981d
JL
641
642 /* convert the length into a more usable form */
38d77c50 643 if (server->sign) {
738f9de5 644 struct kvec iov[2];
985e4ff0 645 int rc = 0;
738f9de5
PS
646 struct smb_rqst rqst = { .rq_iov = iov,
647 .rq_nvec = 2 };
826a95e4 648
738f9de5
PS
649 iov[0].iov_base = mid->resp_buf;
650 iov[0].iov_len = 4;
651 iov[1].iov_base = (char *)mid->resp_buf + 4;
652 iov[1].iov_len = len - 4;
2c8f981d 653 /* FIXME: add code to kill session */
bf5ea0e2 654 rc = cifs_verify_signature(&rqst, server,
0124cc45 655 mid->sequence_number);
985e4ff0 656 if (rc)
f96637be
JP
657 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
658 rc);
2c8f981d
JL
659 }
660
661 /* BB special case reconnect tid and uid here? */
662 return map_smb_to_linux_error(mid->resp_buf, log_error);
663}
664
fec344e3
JL
665struct mid_q_entry *
666cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
792af7b0
PS
667{
668 int rc;
fec344e3 669 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
792af7b0
PS
670 struct mid_q_entry *mid;
671
738f9de5
PS
672 if (rqst->rq_iov[0].iov_len != 4 ||
673 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
674 return ERR_PTR(-EIO);
675
792af7b0
PS
676 rc = allocate_mid(ses, hdr, &mid);
677 if (rc)
fec344e3
JL
678 return ERR_PTR(rc);
679 rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
680 if (rc) {
3c1bf7e4 681 cifs_delete_mid(mid);
fec344e3
JL
682 return ERR_PTR(rc);
683 }
684 return mid;
792af7b0
PS
685}
686
b8f57ee8 687int
738f9de5
PS
688cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
689 struct smb_rqst *rqst, int *resp_buf_type, const int flags,
690 struct kvec *resp_iov)
7ee1af76
JA
691{
692 int rc = 0;
a891f0f8 693 int timeout, optype;
7ee1af76 694 struct mid_q_entry *midQ;
a891f0f8 695 unsigned int credits = 1;
738f9de5 696 char *buf;
50c2f753 697
a891f0f8
PS
698 timeout = flags & CIFS_TIMEOUT_MASK;
699 optype = flags & CIFS_OP_MASK;
133672ef 700
a891f0f8 701 *resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */
7ee1af76
JA
702
703 if ((ses == NULL) || (ses->server == NULL)) {
f96637be 704 cifs_dbg(VFS, "Null session\n");
7ee1af76
JA
705 return -EIO;
706 }
707
da502f7d 708 if (ses->server->tcpStatus == CifsExiting)
7ee1af76 709 return -ENOENT;
7ee1af76 710
792af7b0
PS
711 /*
712 * Ensure that we do not send more than 50 overlapping requests
713 * to the same server. We may make this configurable later or
714 * use ses->maxReq.
715 */
7ee1af76 716
a891f0f8 717 rc = wait_for_free_request(ses->server, timeout, optype);
da502f7d 718 if (rc)
7ee1af76 719 return rc;
7ee1af76 720
792af7b0
PS
721 /*
722 * Make sure that we sign in the same order that we send on this socket
723 * and avoid races inside tcp sendmsg code that could cause corruption
724 * of smb data.
725 */
7ee1af76 726
72ca545b 727 mutex_lock(&ses->server->srv_mutex);
7ee1af76 728
738f9de5 729 midQ = ses->server->ops->setup_request(ses, rqst);
fec344e3 730 if (IS_ERR(midQ)) {
72ca545b 731 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 732 /* Update # of requests on wire to server */
a891f0f8 733 add_credits(ses->server, 1, optype);
fec344e3 734 return PTR_ERR(midQ);
1da177e4 735 }
1da177e4 736
7c9421e1 737 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661 738 cifs_in_send_inc(ses->server);
7fb8986e 739 rc = smb_send_rqst(ses->server, rqst, flags);
789e6661
SF
740 cifs_in_send_dec(ses->server);
741 cifs_save_when_sent(midQ);
7ee1af76 742
ad313cb8
JL
743 if (rc < 0)
744 ses->server->sequence_number -= 2;
72ca545b 745 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 746
da502f7d 747 if (rc < 0)
7ee1af76 748 goto out;
4b8f930f 749
da502f7d 750 if (timeout == CIFS_ASYNC_OP)
133672ef 751 goto out;
d6e04ae6 752
0ade640e 753 rc = wait_for_response(ses->server, midQ);
1be912dd 754 if (rc != 0) {
38bd4906 755 cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
738f9de5 756 send_cancel(ses->server, rqst, midQ);
1be912dd 757 spin_lock(&GlobalMid_Lock);
7c9421e1 758 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
38bd4906 759 midQ->mid_flags |= MID_WAIT_CANCELLED;
1be912dd
JL
760 midQ->callback = DeleteMidQEntry;
761 spin_unlock(&GlobalMid_Lock);
a891f0f8 762 add_credits(ses->server, 1, optype);
1be912dd
JL
763 return rc;
764 }
765 spin_unlock(&GlobalMid_Lock);
766 }
d6e04ae6 767
3c1105df 768 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 769 if (rc != 0) {
a891f0f8 770 add_credits(ses->server, 1, optype);
d6e04ae6
SF
771 return rc;
772 }
50c2f753 773
7c9421e1 774 if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
d6e04ae6 775 rc = -EIO;
f96637be 776 cifs_dbg(FYI, "Bad MID state?\n");
2b2bdfba
SF
777 goto out;
778 }
779
792af7b0 780 buf = (char *)midQ->resp_buf;
da502f7d
PS
781 resp_iov->iov_base = buf;
782 resp_iov->iov_len = get_rfc1002_length(buf) + 4;
7c9421e1 783 if (midQ->large_buf)
a891f0f8 784 *resp_buf_type = CIFS_LARGE_BUFFER;
2c8f981d 785 else
a891f0f8
PS
786 *resp_buf_type = CIFS_SMALL_BUFFER;
787
788 credits = ses->server->ops->get_credits(midQ);
2b2bdfba 789
082d0642
PS
790 rc = ses->server->ops->check_receive(midQ, ses->server,
791 flags & CIFS_LOG_ERROR);
1da177e4 792
3c1bf7e4 793 /* mark it so buf will not be freed by cifs_delete_mid */
2c8f981d
JL
794 if ((flags & CIFS_NO_RESP) == 0)
795 midQ->resp_buf = NULL;
7ee1af76 796out:
3c1bf7e4 797 cifs_delete_mid(midQ);
a891f0f8 798 add_credits(ses->server, credits, optype);
1da177e4 799
d6e04ae6
SF
800 return rc;
801}
1da177e4 802
738f9de5
PS
803int
804SendReceive2(const unsigned int xid, struct cifs_ses *ses,
805 struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
806 const int flags, struct kvec *resp_iov)
807{
808 struct smb_rqst rqst;
3cecf486 809 struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
738f9de5
PS
810 int rc;
811
3cecf486
RS
812 if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
813 new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
814 GFP_KERNEL);
815 if (!new_iov)
816 return -ENOMEM;
817 } else
818 new_iov = s_iov;
738f9de5
PS
819
820 /* 1st iov is a RFC1001 length followed by the rest of the packet */
821 memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
822
823 new_iov[0].iov_base = new_iov[1].iov_base;
824 new_iov[0].iov_len = 4;
825 new_iov[1].iov_base += 4;
826 new_iov[1].iov_len -= 4;
827
828 memset(&rqst, 0, sizeof(struct smb_rqst));
829 rqst.rq_iov = new_iov;
830 rqst.rq_nvec = n_vec + 1;
831
832 rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
3cecf486
RS
833 if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
834 kfree(new_iov);
738f9de5
PS
835 return rc;
836}
837
83b77391
RS
838/* Like SendReceive2 but iov[0] does not contain an rfc1002 header */
839int
840smb2_send_recv(const unsigned int xid, struct cifs_ses *ses,
841 struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
842 const int flags, struct kvec *resp_iov)
843{
844 struct smb_rqst rqst;
3cecf486 845 struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
83b77391
RS
846 int rc;
847 int i;
848 __u32 count;
849 __be32 rfc1002_marker;
850
3cecf486
RS
851 if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
852 new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
853 GFP_KERNEL);
854 if (!new_iov)
855 return -ENOMEM;
856 } else
857 new_iov = s_iov;
83b77391
RS
858
859 /* 1st iov is an RFC1002 Session Message length */
860 memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
861
862 count = 0;
863 for (i = 1; i < n_vec + 1; i++)
864 count += new_iov[i].iov_len;
865
866 rfc1002_marker = cpu_to_be32(count);
867
868 new_iov[0].iov_base = &rfc1002_marker;
869 new_iov[0].iov_len = 4;
870
871 memset(&rqst, 0, sizeof(struct smb_rqst));
872 rqst.rq_iov = new_iov;
873 rqst.rq_nvec = n_vec + 1;
874
875 rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
3cecf486
RS
876 if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
877 kfree(new_iov);
83b77391
RS
878 return rc;
879}
880
1da177e4 881int
96daf2b0 882SendReceive(const unsigned int xid, struct cifs_ses *ses,
1da177e4 883 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
a891f0f8 884 int *pbytes_returned, const int timeout)
1da177e4
LT
885{
886 int rc = 0;
1da177e4 887 struct mid_q_entry *midQ;
fb2036d8
PS
888 unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
889 struct kvec iov = { .iov_base = in_buf, .iov_len = len };
890 struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
1da177e4
LT
891
892 if (ses == NULL) {
f96637be 893 cifs_dbg(VFS, "Null smb session\n");
1da177e4
LT
894 return -EIO;
895 }
79a58d1f 896 if (ses->server == NULL) {
f96637be 897 cifs_dbg(VFS, "Null tcp session\n");
1da177e4
LT
898 return -EIO;
899 }
900
79a58d1f 901 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
902 return -ENOENT;
903
79a58d1f 904 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
905 to the same server. We may make this configurable later or
906 use ses->maxReq */
1da177e4 907
fb2036d8 908 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
f96637be 909 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
fb2036d8 910 len);
6d9c6d54
VL
911 return -EIO;
912 }
913
a891f0f8 914 rc = wait_for_free_request(ses->server, timeout, 0);
7ee1af76
JA
915 if (rc)
916 return rc;
917
79a58d1f 918 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
919 and avoid races inside tcp sendmsg code that could cause corruption
920 of smb data */
921
72ca545b 922 mutex_lock(&ses->server->srv_mutex);
1da177e4 923
7ee1af76
JA
924 rc = allocate_mid(ses, in_buf, &midQ);
925 if (rc) {
72ca545b 926 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 927 /* Update # of requests on wire to server */
a891f0f8 928 add_credits(ses->server, 1, 0);
7ee1af76 929 return rc;
1da177e4
LT
930 }
931
ad009ac9 932 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb
VL
933 if (rc) {
934 mutex_unlock(&ses->server->srv_mutex);
935 goto out;
936 }
1da177e4 937
7c9421e1 938 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661
SF
939
940 cifs_in_send_inc(ses->server);
fb2036d8 941 rc = smb_send(ses->server, in_buf, len);
789e6661
SF
942 cifs_in_send_dec(ses->server);
943 cifs_save_when_sent(midQ);
ad313cb8
JL
944
945 if (rc < 0)
946 ses->server->sequence_number -= 2;
947
72ca545b 948 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 949
79a58d1f 950 if (rc < 0)
7ee1af76
JA
951 goto out;
952
a891f0f8 953 if (timeout == CIFS_ASYNC_OP)
7ee1af76 954 goto out;
1da177e4 955
0ade640e 956 rc = wait_for_response(ses->server, midQ);
1be912dd 957 if (rc != 0) {
fb2036d8 958 send_cancel(ses->server, &rqst, midQ);
1be912dd 959 spin_lock(&GlobalMid_Lock);
7c9421e1 960 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1be912dd
JL
961 /* no longer considered to be "in-flight" */
962 midQ->callback = DeleteMidQEntry;
963 spin_unlock(&GlobalMid_Lock);
a891f0f8 964 add_credits(ses->server, 1, 0);
1be912dd
JL
965 return rc;
966 }
967 spin_unlock(&GlobalMid_Lock);
968 }
1da177e4 969
3c1105df 970 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 971 if (rc != 0) {
a891f0f8 972 add_credits(ses->server, 1, 0);
1da177e4
LT
973 return rc;
974 }
50c2f753 975
2c8f981d 976 if (!midQ->resp_buf || !out_buf ||
7c9421e1 977 midQ->mid_state != MID_RESPONSE_RECEIVED) {
2b2bdfba 978 rc = -EIO;
f96637be 979 cifs_dbg(VFS, "Bad MID state?\n");
2c8f981d 980 goto out;
1da177e4 981 }
7ee1af76 982
d4e4854f 983 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
2c8f981d
JL
984 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
985 rc = cifs_check_receive(midQ, ses->server, 0);
7ee1af76 986out:
3c1bf7e4 987 cifs_delete_mid(midQ);
a891f0f8 988 add_credits(ses->server, 1, 0);
1da177e4 989
7ee1af76
JA
990 return rc;
991}
1da177e4 992
7ee1af76
JA
993/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
994 blocking lock to return. */
995
996static int
96daf2b0 997send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
998 struct smb_hdr *in_buf,
999 struct smb_hdr *out_buf)
1000{
1001 int bytes_returned;
96daf2b0 1002 struct cifs_ses *ses = tcon->ses;
7ee1af76
JA
1003 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
1004
1005 /* We just modify the current in_buf to change
1006 the type of lock from LOCKING_ANDX_SHARED_LOCK
1007 or LOCKING_ANDX_EXCLUSIVE_LOCK to
1008 LOCKING_ANDX_CANCEL_LOCK. */
1009
1010 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
1011 pSMB->Timeout = 0;
88257360 1012 pSMB->hdr.Mid = get_next_mid(ses->server);
7ee1af76
JA
1013
1014 return SendReceive(xid, ses, in_buf, out_buf,
7749981e 1015 &bytes_returned, 0);
7ee1af76
JA
1016}
1017
1018int
96daf2b0 1019SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
1020 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
1021 int *pbytes_returned)
1022{
1023 int rc = 0;
1024 int rstart = 0;
7ee1af76 1025 struct mid_q_entry *midQ;
96daf2b0 1026 struct cifs_ses *ses;
fb2036d8
PS
1027 unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
1028 struct kvec iov = { .iov_base = in_buf, .iov_len = len };
1029 struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
7ee1af76
JA
1030
1031 if (tcon == NULL || tcon->ses == NULL) {
f96637be 1032 cifs_dbg(VFS, "Null smb session\n");
7ee1af76
JA
1033 return -EIO;
1034 }
1035 ses = tcon->ses;
1036
79a58d1f 1037 if (ses->server == NULL) {
f96637be 1038 cifs_dbg(VFS, "Null tcp session\n");
7ee1af76
JA
1039 return -EIO;
1040 }
1041
79a58d1f 1042 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
1043 return -ENOENT;
1044
79a58d1f 1045 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
1046 to the same server. We may make this configurable later or
1047 use ses->maxReq */
1048
fb2036d8 1049 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
f96637be 1050 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
fb2036d8 1051 len);
6d9c6d54
VL
1052 return -EIO;
1053 }
1054
a891f0f8 1055 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
7ee1af76
JA
1056 if (rc)
1057 return rc;
1058
79a58d1f 1059 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
1060 and avoid races inside tcp sendmsg code that could cause corruption
1061 of smb data */
1062
72ca545b 1063 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
1064
1065 rc = allocate_mid(ses, in_buf, &midQ);
1066 if (rc) {
72ca545b 1067 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
1068 return rc;
1069 }
1070
7ee1af76 1071 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb 1072 if (rc) {
3c1bf7e4 1073 cifs_delete_mid(midQ);
829049cb
VL
1074 mutex_unlock(&ses->server->srv_mutex);
1075 return rc;
1076 }
1da177e4 1077
7c9421e1 1078 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661 1079 cifs_in_send_inc(ses->server);
fb2036d8 1080 rc = smb_send(ses->server, in_buf, len);
789e6661
SF
1081 cifs_in_send_dec(ses->server);
1082 cifs_save_when_sent(midQ);
ad313cb8
JL
1083
1084 if (rc < 0)
1085 ses->server->sequence_number -= 2;
1086
72ca545b 1087 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 1088
79a58d1f 1089 if (rc < 0) {
3c1bf7e4 1090 cifs_delete_mid(midQ);
7ee1af76
JA
1091 return rc;
1092 }
1093
1094 /* Wait for a reply - allow signals to interrupt. */
1095 rc = wait_event_interruptible(ses->server->response_q,
7c9421e1 1096 (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
1097 ((ses->server->tcpStatus != CifsGood) &&
1098 (ses->server->tcpStatus != CifsNew)));
1099
1100 /* Were we interrupted by a signal ? */
1101 if ((rc == -ERESTARTSYS) &&
7c9421e1 1102 (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
7ee1af76
JA
1103 ((ses->server->tcpStatus == CifsGood) ||
1104 (ses->server->tcpStatus == CifsNew))) {
1105
1106 if (in_buf->Command == SMB_COM_TRANSACTION2) {
1107 /* POSIX lock. We send a NT_CANCEL SMB to cause the
1108 blocking lock to return. */
fb2036d8 1109 rc = send_cancel(ses->server, &rqst, midQ);
7ee1af76 1110 if (rc) {
3c1bf7e4 1111 cifs_delete_mid(midQ);
7ee1af76
JA
1112 return rc;
1113 }
1114 } else {
1115 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
1116 to cause the blocking lock to return. */
1117
1118 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1119
1120 /* If we get -ENOLCK back the lock may have
1121 already been removed. Don't exit in this case. */
1122 if (rc && rc != -ENOLCK) {
3c1bf7e4 1123 cifs_delete_mid(midQ);
7ee1af76
JA
1124 return rc;
1125 }
1126 }
1127
1be912dd
JL
1128 rc = wait_for_response(ses->server, midQ);
1129 if (rc) {
fb2036d8 1130 send_cancel(ses->server, &rqst, midQ);
1be912dd 1131 spin_lock(&GlobalMid_Lock);
7c9421e1 1132 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1be912dd
JL
1133 /* no longer considered to be "in-flight" */
1134 midQ->callback = DeleteMidQEntry;
1135 spin_unlock(&GlobalMid_Lock);
1136 return rc;
1137 }
1138 spin_unlock(&GlobalMid_Lock);
7ee1af76 1139 }
1be912dd
JL
1140
1141 /* We got the response - restart system call. */
1142 rstart = 1;
7ee1af76
JA
1143 }
1144
3c1105df 1145 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 1146 if (rc != 0)
7ee1af76 1147 return rc;
50c2f753 1148
17c8bfed 1149 /* rcvd frame is ok */
7c9421e1 1150 if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
698e96a8 1151 rc = -EIO;
f96637be 1152 cifs_dbg(VFS, "Bad MID state?\n");
698e96a8
VL
1153 goto out;
1154 }
1da177e4 1155
d4e4854f 1156 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
2c8f981d
JL
1157 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
1158 rc = cifs_check_receive(midQ, ses->server, 0);
17c8bfed 1159out:
3c1bf7e4 1160 cifs_delete_mid(midQ);
7ee1af76
JA
1161 if (rstart && rc == -EACCES)
1162 return -ERESTARTSYS;
1da177e4
LT
1163 return rc;
1164}