]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/cifs/transport.c
CIFS: set *resp_buf_type to NO_BUFFER on error
[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
N
58 memset(temp, 0, sizeof(struct mid_q_entry));
59 temp->mid = get_mid(smb_buffer);
60 temp->pid = current->pid;
61 temp->command = cpu_to_le16(smb_buffer->Command);
62 cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
1047abc1 63 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
a6f74e80
N
64 /* when mid allocated can be before when sent */
65 temp->when_alloc = jiffies;
66 temp->server = server;
2b84a36c 67
a6f74e80
N
68 /*
69 * The default is for the mid to be synchronous, so the
70 * default callback just wakes up the current task.
71 */
72 temp->callback = cifs_wake_up_task;
73 temp->callback_data = current;
1da177e4 74
1da177e4 75 atomic_inc(&midCount);
7c9421e1 76 temp->mid_state = MID_REQUEST_ALLOCATED;
1da177e4
LT
77 return temp;
78}
79
766fdbb5 80void
1da177e4
LT
81DeleteMidQEntry(struct mid_q_entry *midEntry)
82{
1047abc1 83#ifdef CONFIG_CIFS_STATS2
2dc7e1c0 84 __le16 command = midEntry->server->vals->lock_cmd;
1047abc1
SF
85 unsigned long now;
86#endif
7c9421e1 87 midEntry->mid_state = MID_FREE;
8097531a 88 atomic_dec(&midCount);
7c9421e1 89 if (midEntry->large_buf)
b8643e1b
SF
90 cifs_buf_release(midEntry->resp_buf);
91 else
92 cifs_small_buf_release(midEntry->resp_buf);
1047abc1
SF
93#ifdef CONFIG_CIFS_STATS2
94 now = jiffies;
95 /* commands taking longer than one second are indications that
96 something is wrong, unless it is quite a slow link or server */
4328fea7 97 if (time_after(now, midEntry->when_alloc + HZ)) {
2dc7e1c0 98 if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
0b456f04 99 pr_debug(" CIFS slow rsp: cmd %d mid %llu",
1047abc1 100 midEntry->command, midEntry->mid);
0b456f04 101 pr_info(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
1047abc1
SF
102 now - midEntry->when_alloc,
103 now - midEntry->when_sent,
104 now - midEntry->when_received);
105 }
106 }
107#endif
1da177e4
LT
108 mempool_free(midEntry, cifs_mid_poolp);
109}
110
3c1bf7e4
PS
111void
112cifs_delete_mid(struct mid_q_entry *mid)
ddc8cf8f
JL
113{
114 spin_lock(&GlobalMid_Lock);
115 list_del(&mid->qhead);
116 spin_unlock(&GlobalMid_Lock);
117
118 DeleteMidQEntry(mid);
119}
120
6f49f46b
JL
121/*
122 * smb_send_kvec - send an array of kvecs to the server
123 * @server: Server to send the data to
3ab3f2a1 124 * @smb_msg: Message to send
6f49f46b
JL
125 * @sent: amount of data sent on socket is stored here
126 *
127 * Our basic "send data to server" function. Should be called with srv_mutex
128 * held. The caller is responsible for handling the results.
129 */
d6e04ae6 130static int
3ab3f2a1
AV
131smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
132 size_t *sent)
1da177e4
LT
133{
134 int rc = 0;
3ab3f2a1 135 int retries = 0;
edf1ae40 136 struct socket *ssocket = server->ssocket;
50c2f753 137
6f49f46b
JL
138 *sent = 0;
139
3ab3f2a1
AV
140 smb_msg->msg_name = (struct sockaddr *) &server->dstaddr;
141 smb_msg->msg_namelen = sizeof(struct sockaddr);
142 smb_msg->msg_control = NULL;
143 smb_msg->msg_controllen = 0;
0496e02d 144 if (server->noblocksnd)
3ab3f2a1 145 smb_msg->msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
edf1ae40 146 else
3ab3f2a1 147 smb_msg->msg_flags = MSG_NOSIGNAL;
1da177e4 148
3ab3f2a1 149 while (msg_data_left(smb_msg)) {
6f49f46b
JL
150 /*
151 * If blocking send, we try 3 times, since each can block
152 * for 5 seconds. For nonblocking we have to try more
153 * but wait increasing amounts of time allowing time for
154 * socket to clear. The overall time we wait in either
155 * case to send on the socket is about 15 seconds.
156 * Similarly we wait for 15 seconds for a response from
157 * the server in SendReceive[2] for the server to send
158 * a response back for most types of requests (except
159 * SMB Write past end of file which can be slow, and
160 * blocking lock operations). NFS waits slightly longer
161 * than CIFS, but this can make it take longer for
162 * nonresponsive servers to be detected and 15 seconds
163 * is more than enough time for modern networks to
164 * send a packet. In most cases if we fail to send
165 * after the retries we will kill the socket and
166 * reconnect which may clear the network problem.
167 */
3ab3f2a1 168 rc = sock_sendmsg(ssocket, smb_msg);
ce6c44e4 169 if (rc == -EAGAIN) {
3ab3f2a1
AV
170 retries++;
171 if (retries >= 14 ||
172 (!server->noblocksnd && (retries > 2))) {
f96637be
JP
173 cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
174 ssocket);
3ab3f2a1 175 return -EAGAIN;
1da177e4 176 }
3ab3f2a1 177 msleep(1 << retries);
1da177e4
LT
178 continue;
179 }
6f49f46b 180
79a58d1f 181 if (rc < 0)
3ab3f2a1 182 return rc;
6f49f46b 183
79a58d1f 184 if (rc == 0) {
3e84469d
SF
185 /* should never happen, letting socket clear before
186 retrying is our only obvious option here */
f96637be 187 cifs_dbg(VFS, "tcp sent no data\n");
3e84469d
SF
188 msleep(500);
189 continue;
d6e04ae6 190 }
6f49f46b 191
3ab3f2a1
AV
192 /* send was at least partially successful */
193 *sent += rc;
194 retries = 0; /* in case we get ENOSPC on the next send */
1da177e4 195 }
3ab3f2a1 196 return 0;
97bc00b3
JL
197}
198
a26054d1
JL
199static unsigned long
200rqst_len(struct smb_rqst *rqst)
201{
202 unsigned int i;
203 struct kvec *iov = rqst->rq_iov;
204 unsigned long buflen = 0;
205
206 /* total up iov array first */
207 for (i = 0; i < rqst->rq_nvec; i++)
208 buflen += iov[i].iov_len;
209
210 /* add in the page array if there is one */
211 if (rqst->rq_npages) {
212 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
213 buflen += rqst->rq_tailsz;
214 }
215
216 return buflen;
217}
218
6f49f46b 219static int
7fb8986e 220__smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
6f49f46b
JL
221{
222 int rc;
223 struct kvec *iov = rqst->rq_iov;
224 int n_vec = rqst->rq_nvec;
225 unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
a26054d1 226 unsigned long send_length;
97bc00b3 227 unsigned int i;
3ab3f2a1 228 size_t total_len = 0, sent, size;
b8eed283 229 struct socket *ssocket = server->ssocket;
3ab3f2a1 230 struct msghdr smb_msg;
b8eed283 231 int val = 1;
6f49f46b 232
ea702b80
JL
233 if (ssocket == NULL)
234 return -ENOTSOCK;
235
a26054d1
JL
236 /* sanity check send length */
237 send_length = rqst_len(rqst);
238 if (send_length != smb_buf_length + 4) {
239 WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
240 send_length, smb_buf_length);
241 return -EIO;
242 }
243
738f9de5
PS
244 if (n_vec < 2)
245 return -EIO;
246
f96637be 247 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
6f49f46b 248 dump_smb(iov[0].iov_base, iov[0].iov_len);
738f9de5 249 dump_smb(iov[1].iov_base, iov[1].iov_len);
6f49f46b 250
b8eed283
JL
251 /* cork the socket */
252 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
253 (char *)&val, sizeof(val));
254
3ab3f2a1
AV
255 size = 0;
256 for (i = 0; i < n_vec; i++)
257 size += iov[i].iov_len;
258
259 iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size);
260
261 rc = smb_send_kvec(server, &smb_msg, &sent);
97bc00b3
JL
262 if (rc < 0)
263 goto uncork;
264
265 total_len += sent;
266
267 /* now walk the page array and send each page in it */
268 for (i = 0; i < rqst->rq_npages; i++) {
3ab3f2a1
AV
269 size_t len = i == rqst->rq_npages - 1
270 ? rqst->rq_tailsz
271 : rqst->rq_pagesz;
272 struct bio_vec bvec = {
273 .bv_page = rqst->rq_pages[i],
274 .bv_len = len
275 };
276 iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
277 &bvec, 1, len);
278 rc = smb_send_kvec(server, &smb_msg, &sent);
97bc00b3
JL
279 if (rc < 0)
280 break;
281
282 total_len += sent;
283 }
1da177e4 284
97bc00b3 285uncork:
b8eed283
JL
286 /* uncork it */
287 val = 0;
288 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
289 (char *)&val, sizeof(val));
290
edf1ae40 291 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
f96637be
JP
292 cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
293 smb_buf_length + 4, total_len);
6f49f46b
JL
294 /*
295 * If we have only sent part of an SMB then the next SMB could
296 * be taken as the remainder of this one. We need to kill the
297 * socket so the server throws away the partial SMB
298 */
edf1ae40
SF
299 server->tcpStatus = CifsNeedReconnect;
300 }
301
d804d41d 302 if (rc < 0 && rc != -EINTR)
f96637be
JP
303 cifs_dbg(VFS, "Error %d sending data on socket to server\n",
304 rc);
d804d41d 305 else
1da177e4 306 rc = 0;
1da177e4
LT
307
308 return rc;
309}
310
6f49f46b 311static int
7fb8986e 312smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst, int flags)
6f49f46b 313{
7fb8986e
PS
314 struct smb_rqst cur_rqst;
315 int rc;
316
317 if (!(flags & CIFS_TRANSFORM_REQ))
318 return __smb_send_rqst(server, rqst);
319
320 if (!server->ops->init_transform_rq ||
321 !server->ops->free_transform_rq) {
322 cifs_dbg(VFS, "Encryption requested but transform callbacks are missed\n");
323 return -EIO;
324 }
6f49f46b 325
7fb8986e
PS
326 rc = server->ops->init_transform_rq(server, &cur_rqst, rqst);
327 if (rc)
328 return rc;
329
330 rc = __smb_send_rqst(server, &cur_rqst);
331 server->ops->free_transform_rq(&cur_rqst);
332 return rc;
6f49f46b
JL
333}
334
0496e02d
JL
335int
336smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
337 unsigned int smb_buf_length)
338{
738f9de5 339 struct kvec iov[2];
7fb8986e
PS
340 struct smb_rqst rqst = { .rq_iov = iov,
341 .rq_nvec = 2 };
0496e02d 342
738f9de5
PS
343 iov[0].iov_base = smb_buffer;
344 iov[0].iov_len = 4;
345 iov[1].iov_base = (char *)smb_buffer + 4;
346 iov[1].iov_len = smb_buf_length;
0496e02d 347
7fb8986e 348 return __smb_send_rqst(server, &rqst);
0496e02d
JL
349}
350
fc40f9cf 351static int
a891f0f8 352wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
bc205ed1 353 int *credits)
1da177e4 354{
5bc59498
PS
355 int rc;
356
fc40f9cf 357 spin_lock(&server->req_lock);
a891f0f8 358 if (timeout == CIFS_ASYNC_OP) {
1da177e4 359 /* oplock breaks must not be held up */
fc40f9cf 360 server->in_flight++;
bc205ed1 361 *credits -= 1;
fc40f9cf 362 spin_unlock(&server->req_lock);
27a97a61
VL
363 return 0;
364 }
365
27a97a61 366 while (1) {
bc205ed1 367 if (*credits <= 0) {
fc40f9cf 368 spin_unlock(&server->req_lock);
789e6661 369 cifs_num_waiters_inc(server);
5bc59498 370 rc = wait_event_killable(server->request_q,
bc205ed1 371 has_credits(server, credits));
789e6661 372 cifs_num_waiters_dec(server);
5bc59498
PS
373 if (rc)
374 return rc;
fc40f9cf 375 spin_lock(&server->req_lock);
27a97a61 376 } else {
c5797a94 377 if (server->tcpStatus == CifsExiting) {
fc40f9cf 378 spin_unlock(&server->req_lock);
27a97a61 379 return -ENOENT;
1da177e4 380 }
27a97a61 381
2d86dbc9
PS
382 /*
383 * Can not count locking commands against total
384 * as they are allowed to block on server.
385 */
27a97a61
VL
386
387 /* update # of requests on the wire to server */
a891f0f8 388 if (timeout != CIFS_BLOCKING_OP) {
bc205ed1 389 *credits -= 1;
fc40f9cf 390 server->in_flight++;
2d86dbc9 391 }
fc40f9cf 392 spin_unlock(&server->req_lock);
27a97a61 393 break;
1da177e4
LT
394 }
395 }
7ee1af76
JA
396 return 0;
397}
1da177e4 398
bc205ed1 399static int
a891f0f8
PS
400wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
401 const int optype)
bc205ed1 402{
eb4c7df6
SP
403 int *val;
404
405 val = server->ops->get_credits_field(server, optype);
406 /* Since an echo is already inflight, no need to wait to send another */
407 if (*val <= 0 && optype == CIFS_ECHO_OP)
408 return -EAGAIN;
409 return wait_for_free_credits(server, timeout, val);
bc205ed1
PS
410}
411
cb7e9eab
PS
412int
413cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
414 unsigned int *num, unsigned int *credits)
415{
416 *num = size;
417 *credits = 0;
418 return 0;
419}
420
96daf2b0 421static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
7ee1af76
JA
422 struct mid_q_entry **ppmidQ)
423{
1da177e4 424 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 425 return -ENOENT;
8fbbd365
VL
426 }
427
428 if (ses->server->tcpStatus == CifsNeedReconnect) {
f96637be 429 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
7ee1af76 430 return -EAGAIN;
8fbbd365
VL
431 }
432
7f48558e 433 if (ses->status == CifsNew) {
79a58d1f 434 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926 435 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 436 return -EAGAIN;
ad7a2926 437 /* else ok - we are setting up session */
1da177e4 438 }
7f48558e
SP
439
440 if (ses->status == CifsExiting) {
441 /* check if SMB session is bad because we are setting it up */
442 if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
443 return -EAGAIN;
444 /* else ok - we are shutting down session */
445 }
446
24b9b06b 447 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364 448 if (*ppmidQ == NULL)
7ee1af76 449 return -ENOMEM;
ddc8cf8f
JL
450 spin_lock(&GlobalMid_Lock);
451 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
452 spin_unlock(&GlobalMid_Lock);
7ee1af76
JA
453 return 0;
454}
455
0ade640e
JL
456static int
457wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
7ee1af76 458{
0ade640e 459 int error;
7ee1af76 460
5853cc2a 461 error = wait_event_freezekillable_unsafe(server->response_q,
7c9421e1 462 midQ->mid_state != MID_REQUEST_SUBMITTED);
0ade640e
JL
463 if (error < 0)
464 return -ERESTARTSYS;
7ee1af76 465
0ade640e 466 return 0;
7ee1af76
JA
467}
468
fec344e3
JL
469struct mid_q_entry *
470cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
792af7b0
PS
471{
472 int rc;
fec344e3 473 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
792af7b0
PS
474 struct mid_q_entry *mid;
475
738f9de5
PS
476 if (rqst->rq_iov[0].iov_len != 4 ||
477 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
478 return ERR_PTR(-EIO);
479
792af7b0 480 /* enable signing if server requires it */
38d77c50 481 if (server->sign)
792af7b0
PS
482 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
483
484 mid = AllocMidQEntry(hdr, server);
485 if (mid == NULL)
fec344e3 486 return ERR_PTR(-ENOMEM);
792af7b0 487
fec344e3 488 rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
ffc61ccb
SP
489 if (rc) {
490 DeleteMidQEntry(mid);
fec344e3 491 return ERR_PTR(rc);
ffc61ccb
SP
492 }
493
fec344e3 494 return mid;
792af7b0 495}
133672ef 496
a6827c18
JL
497/*
498 * Send a SMB request and set the callback function in the mid to handle
499 * the result. Caller is responsible for dealing with timeouts.
500 */
501int
fec344e3 502cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
9b7c18a2
PS
503 mid_receive_t *receive, mid_callback_t *callback,
504 mid_handle_t *handle, void *cbdata, const int flags)
a6827c18 505{
a891f0f8 506 int rc, timeout, optype;
a6827c18 507 struct mid_q_entry *mid;
cb7e9eab 508 unsigned int credits = 0;
a6827c18 509
a891f0f8
PS
510 timeout = flags & CIFS_TIMEOUT_MASK;
511 optype = flags & CIFS_OP_MASK;
512
cb7e9eab
PS
513 if ((flags & CIFS_HAS_CREDITS) == 0) {
514 rc = wait_for_free_request(server, timeout, optype);
515 if (rc)
516 return rc;
517 credits = 1;
518 }
a6827c18
JL
519
520 mutex_lock(&server->srv_mutex);
fec344e3
JL
521 mid = server->ops->setup_async_request(server, rqst);
522 if (IS_ERR(mid)) {
a6827c18 523 mutex_unlock(&server->srv_mutex);
cb7e9eab 524 add_credits_and_wake_if(server, credits, optype);
fec344e3 525 return PTR_ERR(mid);
a6827c18
JL
526 }
527
44d22d84 528 mid->receive = receive;
a6827c18
JL
529 mid->callback = callback;
530 mid->callback_data = cbdata;
9b7c18a2 531 mid->handle = handle;
7c9421e1 532 mid->mid_state = MID_REQUEST_SUBMITTED;
789e6661 533
ffc61ccb
SP
534 /* put it on the pending_mid_q */
535 spin_lock(&GlobalMid_Lock);
536 list_add_tail(&mid->qhead, &server->pending_mid_q);
537 spin_unlock(&GlobalMid_Lock);
538
93d2cb6c
LL
539 /*
540 * Need to store the time in mid before calling I/O. For call_async,
541 * I/O response may come back and free the mid entry on another thread.
542 */
543 cifs_save_when_sent(mid);
789e6661 544 cifs_in_send_inc(server);
7fb8986e 545 rc = smb_send_rqst(server, rqst, flags);
789e6661 546 cifs_in_send_dec(server);
ad313cb8 547
820962dc 548 if (rc < 0) {
ad313cb8 549 server->sequence_number -= 2;
820962dc
RV
550 cifs_delete_mid(mid);
551 }
552
a6827c18 553 mutex_unlock(&server->srv_mutex);
789e6661 554
ffc61ccb
SP
555 if (rc == 0)
556 return 0;
a6827c18 557
cb7e9eab 558 add_credits_and_wake_if(server, credits, optype);
a6827c18
JL
559 return rc;
560}
561
133672ef
SF
562/*
563 *
564 * Send an SMB Request. No response info (other than return code)
565 * needs to be parsed.
566 *
567 * flags indicate the type of request buffer and how long to wait
568 * and whether to log NT STATUS code (error) before mapping it to POSIX error
569 *
570 */
571int
96daf2b0 572SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
792af7b0 573 char *in_buf, int flags)
133672ef
SF
574{
575 int rc;
576 struct kvec iov[1];
da502f7d 577 struct kvec rsp_iov;
133672ef
SF
578 int resp_buf_type;
579
792af7b0
PS
580 iov[0].iov_base = in_buf;
581 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
133672ef 582 flags |= CIFS_NO_RESP;
da502f7d 583 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
f96637be 584 cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
90c81e0b 585
133672ef
SF
586 return rc;
587}
588
053d5034 589static int
3c1105df 590cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
053d5034
JL
591{
592 int rc = 0;
593
f96637be
JP
594 cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
595 __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
053d5034 596
74dd92a8 597 spin_lock(&GlobalMid_Lock);
7c9421e1 598 switch (mid->mid_state) {
74dd92a8 599 case MID_RESPONSE_RECEIVED:
053d5034
JL
600 spin_unlock(&GlobalMid_Lock);
601 return rc;
74dd92a8
JL
602 case MID_RETRY_NEEDED:
603 rc = -EAGAIN;
604 break;
71823baf
JL
605 case MID_RESPONSE_MALFORMED:
606 rc = -EIO;
607 break;
3c1105df
JL
608 case MID_SHUTDOWN:
609 rc = -EHOSTDOWN;
610 break;
74dd92a8 611 default:
3c1105df 612 list_del_init(&mid->qhead);
f96637be
JP
613 cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
614 __func__, mid->mid, mid->mid_state);
74dd92a8 615 rc = -EIO;
053d5034
JL
616 }
617 spin_unlock(&GlobalMid_Lock);
618
2b84a36c 619 DeleteMidQEntry(mid);
053d5034
JL
620 return rc;
621}
622
121b046a 623static inline int
fb2036d8
PS
624send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
625 struct mid_q_entry *mid)
76dcc26f 626{
121b046a 627 return server->ops->send_cancel ?
fb2036d8 628 server->ops->send_cancel(server, rqst, mid) : 0;
76dcc26f
JL
629}
630
2c8f981d
JL
631int
632cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
633 bool log_error)
634{
792af7b0 635 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
826a95e4
JL
636
637 dump_smb(mid->resp_buf, min_t(u32, 92, len));
2c8f981d
JL
638
639 /* convert the length into a more usable form */
38d77c50 640 if (server->sign) {
738f9de5 641 struct kvec iov[2];
985e4ff0 642 int rc = 0;
738f9de5
PS
643 struct smb_rqst rqst = { .rq_iov = iov,
644 .rq_nvec = 2 };
826a95e4 645
738f9de5
PS
646 iov[0].iov_base = mid->resp_buf;
647 iov[0].iov_len = 4;
648 iov[1].iov_base = (char *)mid->resp_buf + 4;
649 iov[1].iov_len = len - 4;
2c8f981d 650 /* FIXME: add code to kill session */
bf5ea0e2 651 rc = cifs_verify_signature(&rqst, server,
0124cc45 652 mid->sequence_number);
985e4ff0 653 if (rc)
f96637be
JP
654 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
655 rc);
2c8f981d
JL
656 }
657
658 /* BB special case reconnect tid and uid here? */
659 return map_smb_to_linux_error(mid->resp_buf, log_error);
660}
661
fec344e3
JL
662struct mid_q_entry *
663cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
792af7b0
PS
664{
665 int rc;
fec344e3 666 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
792af7b0
PS
667 struct mid_q_entry *mid;
668
738f9de5
PS
669 if (rqst->rq_iov[0].iov_len != 4 ||
670 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
671 return ERR_PTR(-EIO);
672
792af7b0
PS
673 rc = allocate_mid(ses, hdr, &mid);
674 if (rc)
fec344e3
JL
675 return ERR_PTR(rc);
676 rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
677 if (rc) {
3c1bf7e4 678 cifs_delete_mid(mid);
fec344e3
JL
679 return ERR_PTR(rc);
680 }
681 return mid;
792af7b0
PS
682}
683
b8f57ee8 684int
738f9de5
PS
685cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
686 struct smb_rqst *rqst, int *resp_buf_type, const int flags,
687 struct kvec *resp_iov)
7ee1af76
JA
688{
689 int rc = 0;
a891f0f8 690 int timeout, optype;
7ee1af76 691 struct mid_q_entry *midQ;
a891f0f8 692 unsigned int credits = 1;
738f9de5 693 char *buf;
50c2f753 694
a891f0f8
PS
695 timeout = flags & CIFS_TIMEOUT_MASK;
696 optype = flags & CIFS_OP_MASK;
133672ef 697
a891f0f8 698 *resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */
7ee1af76
JA
699
700 if ((ses == NULL) || (ses->server == NULL)) {
f96637be 701 cifs_dbg(VFS, "Null session\n");
7ee1af76
JA
702 return -EIO;
703 }
704
da502f7d 705 if (ses->server->tcpStatus == CifsExiting)
7ee1af76 706 return -ENOENT;
7ee1af76 707
792af7b0
PS
708 /*
709 * Ensure that we do not send more than 50 overlapping requests
710 * to the same server. We may make this configurable later or
711 * use ses->maxReq.
712 */
7ee1af76 713
a891f0f8 714 rc = wait_for_free_request(ses->server, timeout, optype);
da502f7d 715 if (rc)
7ee1af76 716 return rc;
7ee1af76 717
792af7b0
PS
718 /*
719 * Make sure that we sign in the same order that we send on this socket
720 * and avoid races inside tcp sendmsg code that could cause corruption
721 * of smb data.
722 */
7ee1af76 723
72ca545b 724 mutex_lock(&ses->server->srv_mutex);
7ee1af76 725
738f9de5 726 midQ = ses->server->ops->setup_request(ses, rqst);
fec344e3 727 if (IS_ERR(midQ)) {
72ca545b 728 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 729 /* Update # of requests on wire to server */
a891f0f8 730 add_credits(ses->server, 1, optype);
fec344e3 731 return PTR_ERR(midQ);
1da177e4 732 }
1da177e4 733
7c9421e1 734 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661 735 cifs_in_send_inc(ses->server);
7fb8986e 736 rc = smb_send_rqst(ses->server, rqst, flags);
789e6661
SF
737 cifs_in_send_dec(ses->server);
738 cifs_save_when_sent(midQ);
7ee1af76 739
ad313cb8
JL
740 if (rc < 0)
741 ses->server->sequence_number -= 2;
72ca545b 742 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 743
da502f7d 744 if (rc < 0)
7ee1af76 745 goto out;
4b8f930f 746
da502f7d 747 if (timeout == CIFS_ASYNC_OP)
133672ef 748 goto out;
d6e04ae6 749
0ade640e 750 rc = wait_for_response(ses->server, midQ);
1be912dd 751 if (rc != 0) {
38bd4906 752 cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
738f9de5 753 send_cancel(ses->server, rqst, midQ);
1be912dd 754 spin_lock(&GlobalMid_Lock);
7c9421e1 755 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
38bd4906 756 midQ->mid_flags |= MID_WAIT_CANCELLED;
1be912dd
JL
757 midQ->callback = DeleteMidQEntry;
758 spin_unlock(&GlobalMid_Lock);
a891f0f8 759 add_credits(ses->server, 1, optype);
1be912dd
JL
760 return rc;
761 }
762 spin_unlock(&GlobalMid_Lock);
763 }
d6e04ae6 764
3c1105df 765 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 766 if (rc != 0) {
a891f0f8 767 add_credits(ses->server, 1, optype);
d6e04ae6
SF
768 return rc;
769 }
50c2f753 770
7c9421e1 771 if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
d6e04ae6 772 rc = -EIO;
f96637be 773 cifs_dbg(FYI, "Bad MID state?\n");
2b2bdfba
SF
774 goto out;
775 }
776
792af7b0 777 buf = (char *)midQ->resp_buf;
da502f7d
PS
778 resp_iov->iov_base = buf;
779 resp_iov->iov_len = get_rfc1002_length(buf) + 4;
7c9421e1 780 if (midQ->large_buf)
a891f0f8 781 *resp_buf_type = CIFS_LARGE_BUFFER;
2c8f981d 782 else
a891f0f8
PS
783 *resp_buf_type = CIFS_SMALL_BUFFER;
784
785 credits = ses->server->ops->get_credits(midQ);
2b2bdfba 786
082d0642
PS
787 rc = ses->server->ops->check_receive(midQ, ses->server,
788 flags & CIFS_LOG_ERROR);
1da177e4 789
3c1bf7e4 790 /* mark it so buf will not be freed by cifs_delete_mid */
2c8f981d
JL
791 if ((flags & CIFS_NO_RESP) == 0)
792 midQ->resp_buf = NULL;
7ee1af76 793out:
3c1bf7e4 794 cifs_delete_mid(midQ);
a891f0f8 795 add_credits(ses->server, credits, optype);
1da177e4 796
d6e04ae6
SF
797 return rc;
798}
1da177e4 799
738f9de5
PS
800int
801SendReceive2(const unsigned int xid, struct cifs_ses *ses,
802 struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
803 const int flags, struct kvec *resp_iov)
804{
805 struct smb_rqst rqst;
806 struct kvec *new_iov;
807 int rc;
808
809 new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1), GFP_KERNEL);
5a6a3031
SF
810 if (!new_iov) {
811 /* otherwise cifs_send_recv below sets resp_buf_type */
812 *resp_buf_type = CIFS_NO_BUFFER;
738f9de5 813 return -ENOMEM;
5a6a3031 814 }
738f9de5
PS
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}