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