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