]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - fs/cifs/transport.c
CIFS: Add capability to transform requests before sending
[mirror_ubuntu-zesty-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
7dc5ef8b 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
27eefed6
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);
27eefed6 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
7dc5ef8b 316smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst, int flags)
6f49f46b 317{
7dc5ef8b
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
7dc5ef8b
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{
27eefed6 343 struct kvec iov[2];
7dc5ef8b
PS
344 struct smb_rqst rqst = { .rq_iov = iov,
345 .rq_nvec = 2 };
0496e02d 346
27eefed6
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
7dc5ef8b 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
27eefed6
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,
27eefed6
PS
507 mid_receive_t *receive, mid_callback_t *callback, void *cbdata,
508 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;
7c9421e1 535 mid->mid_state = MID_REQUEST_SUBMITTED;
789e6661 536
ffc61ccb
SP
537 /* put it on the pending_mid_q */
538 spin_lock(&GlobalMid_Lock);
539 list_add_tail(&mid->qhead, &server->pending_mid_q);
540 spin_unlock(&GlobalMid_Lock);
541
542
789e6661 543 cifs_in_send_inc(server);
7dc5ef8b 544 rc = smb_send_rqst(server, rqst, flags);
789e6661
SF
545 cifs_in_send_dec(server);
546 cifs_save_when_sent(mid);
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];
9a7baddf 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;
9a7baddf 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
5fb4e288 619 mutex_lock(&server->srv_mutex);
2b84a36c 620 DeleteMidQEntry(mid);
5fb4e288 621 mutex_unlock(&server->srv_mutex);
053d5034
JL
622 return rc;
623}
624
121b046a 625static inline int
df976e8b
PS
626send_cancel(struct TCP_Server_Info *server, struct smb_rqst *rqst,
627 struct mid_q_entry *mid)
76dcc26f 628{
121b046a 629 return server->ops->send_cancel ?
df976e8b 630 server->ops->send_cancel(server, rqst, mid) : 0;
76dcc26f
JL
631}
632
2c8f981d
JL
633int
634cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
635 bool log_error)
636{
792af7b0 637 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
826a95e4
JL
638
639 dump_smb(mid->resp_buf, min_t(u32, 92, len));
2c8f981d
JL
640
641 /* convert the length into a more usable form */
38d77c50 642 if (server->sign) {
27eefed6 643 struct kvec iov[2];
985e4ff0 644 int rc = 0;
27eefed6
PS
645 struct smb_rqst rqst = { .rq_iov = iov,
646 .rq_nvec = 2 };
826a95e4 647
27eefed6
PS
648 iov[0].iov_base = mid->resp_buf;
649 iov[0].iov_len = 4;
650 iov[1].iov_base = (char *)mid->resp_buf + 4;
651 iov[1].iov_len = len - 4;
2c8f981d 652 /* FIXME: add code to kill session */
bf5ea0e2 653 rc = cifs_verify_signature(&rqst, server,
0124cc45 654 mid->sequence_number);
985e4ff0 655 if (rc)
f96637be
JP
656 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
657 rc);
2c8f981d
JL
658 }
659
660 /* BB special case reconnect tid and uid here? */
661 return map_smb_to_linux_error(mid->resp_buf, log_error);
662}
663
fec344e3
JL
664struct mid_q_entry *
665cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
792af7b0
PS
666{
667 int rc;
fec344e3 668 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
792af7b0
PS
669 struct mid_q_entry *mid;
670
27eefed6
PS
671 if (rqst->rq_iov[0].iov_len != 4 ||
672 rqst->rq_iov[0].iov_base + 4 != rqst->rq_iov[1].iov_base)
673 return ERR_PTR(-EIO);
674
792af7b0
PS
675 rc = allocate_mid(ses, hdr, &mid);
676 if (rc)
fec344e3
JL
677 return ERR_PTR(rc);
678 rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
679 if (rc) {
3c1bf7e4 680 cifs_delete_mid(mid);
fec344e3
JL
681 return ERR_PTR(rc);
682 }
683 return mid;
792af7b0
PS
684}
685
78afce20 686int
27eefed6
PS
687cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
688 struct smb_rqst *rqst, int *resp_buf_type, const int flags,
689 struct kvec *resp_iov)
7ee1af76
JA
690{
691 int rc = 0;
a891f0f8 692 int timeout, optype;
7ee1af76 693 struct mid_q_entry *midQ;
a891f0f8 694 unsigned int credits = 1;
27eefed6 695 char *buf;
50c2f753 696
a891f0f8
PS
697 timeout = flags & CIFS_TIMEOUT_MASK;
698 optype = flags & CIFS_OP_MASK;
133672ef 699
a891f0f8 700 *resp_buf_type = CIFS_NO_BUFFER; /* no response buf yet */
7ee1af76
JA
701
702 if ((ses == NULL) || (ses->server == NULL)) {
f96637be 703 cifs_dbg(VFS, "Null session\n");
7ee1af76
JA
704 return -EIO;
705 }
706
9a7baddf 707 if (ses->server->tcpStatus == CifsExiting)
7ee1af76 708 return -ENOENT;
7ee1af76 709
792af7b0
PS
710 /*
711 * Ensure that we do not send more than 50 overlapping requests
712 * to the same server. We may make this configurable later or
713 * use ses->maxReq.
714 */
7ee1af76 715
a891f0f8 716 rc = wait_for_free_request(ses->server, timeout, optype);
9a7baddf 717 if (rc)
7ee1af76 718 return rc;
7ee1af76 719
792af7b0
PS
720 /*
721 * Make sure that we sign in the same order that we send on this socket
722 * and avoid races inside tcp sendmsg code that could cause corruption
723 * of smb data.
724 */
7ee1af76 725
72ca545b 726 mutex_lock(&ses->server->srv_mutex);
7ee1af76 727
27eefed6 728 midQ = ses->server->ops->setup_request(ses, rqst);
fec344e3 729 if (IS_ERR(midQ)) {
72ca545b 730 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 731 /* Update # of requests on wire to server */
a891f0f8 732 add_credits(ses->server, 1, optype);
fec344e3 733 return PTR_ERR(midQ);
1da177e4 734 }
1da177e4 735
7c9421e1 736 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661 737 cifs_in_send_inc(ses->server);
7dc5ef8b 738 rc = smb_send_rqst(ses->server, rqst, flags);
789e6661
SF
739 cifs_in_send_dec(ses->server);
740 cifs_save_when_sent(midQ);
7ee1af76 741
ad313cb8
JL
742 if (rc < 0)
743 ses->server->sequence_number -= 2;
72ca545b 744 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 745
9a7baddf 746 if (rc < 0)
7ee1af76 747 goto out;
4b8f930f 748
9a7baddf 749 if (timeout == CIFS_ASYNC_OP)
133672ef 750 goto out;
d6e04ae6 751
0ade640e 752 rc = wait_for_response(ses->server, midQ);
1be912dd 753 if (rc != 0) {
27eefed6 754 send_cancel(ses->server, rqst, midQ);
1be912dd 755 spin_lock(&GlobalMid_Lock);
7c9421e1 756 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
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;
9a7baddf
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
27eefed6
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);
810 if (!new_iov)
811 return -ENOMEM;
812
813 /* 1st iov is a RFC1001 length followed by the rest of the packet */
814 memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
815
816 new_iov[0].iov_base = new_iov[1].iov_base;
817 new_iov[0].iov_len = 4;
818 new_iov[1].iov_base += 4;
819 new_iov[1].iov_len -= 4;
820
821 memset(&rqst, 0, sizeof(struct smb_rqst));
822 rqst.rq_iov = new_iov;
823 rqst.rq_nvec = n_vec + 1;
824
825 rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
826 kfree(new_iov);
827 return rc;
828}
829
1da177e4 830int
96daf2b0 831SendReceive(const unsigned int xid, struct cifs_ses *ses,
1da177e4 832 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
a891f0f8 833 int *pbytes_returned, const int timeout)
1da177e4
LT
834{
835 int rc = 0;
1da177e4 836 struct mid_q_entry *midQ;
df976e8b
PS
837 unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
838 struct kvec iov = { .iov_base = in_buf, .iov_len = len };
839 struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
1da177e4
LT
840
841 if (ses == NULL) {
f96637be 842 cifs_dbg(VFS, "Null smb session\n");
1da177e4
LT
843 return -EIO;
844 }
79a58d1f 845 if (ses->server == NULL) {
f96637be 846 cifs_dbg(VFS, "Null tcp session\n");
1da177e4
LT
847 return -EIO;
848 }
849
79a58d1f 850 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
851 return -ENOENT;
852
79a58d1f 853 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
854 to the same server. We may make this configurable later or
855 use ses->maxReq */
1da177e4 856
df976e8b 857 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
f96637be 858 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
df976e8b 859 len);
6d9c6d54
VL
860 return -EIO;
861 }
862
a891f0f8 863 rc = wait_for_free_request(ses->server, timeout, 0);
7ee1af76
JA
864 if (rc)
865 return rc;
866
79a58d1f 867 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
868 and avoid races inside tcp sendmsg code that could cause corruption
869 of smb data */
870
72ca545b 871 mutex_lock(&ses->server->srv_mutex);
1da177e4 872
7ee1af76
JA
873 rc = allocate_mid(ses, in_buf, &midQ);
874 if (rc) {
72ca545b 875 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 876 /* Update # of requests on wire to server */
a891f0f8 877 add_credits(ses->server, 1, 0);
7ee1af76 878 return rc;
1da177e4
LT
879 }
880
ad009ac9 881 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb
VL
882 if (rc) {
883 mutex_unlock(&ses->server->srv_mutex);
884 goto out;
885 }
1da177e4 886
7c9421e1 887 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661
SF
888
889 cifs_in_send_inc(ses->server);
df976e8b 890 rc = smb_send(ses->server, in_buf, len);
789e6661
SF
891 cifs_in_send_dec(ses->server);
892 cifs_save_when_sent(midQ);
ad313cb8
JL
893
894 if (rc < 0)
895 ses->server->sequence_number -= 2;
896
72ca545b 897 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 898
79a58d1f 899 if (rc < 0)
7ee1af76
JA
900 goto out;
901
a891f0f8 902 if (timeout == CIFS_ASYNC_OP)
7ee1af76 903 goto out;
1da177e4 904
0ade640e 905 rc = wait_for_response(ses->server, midQ);
1be912dd 906 if (rc != 0) {
df976e8b 907 send_cancel(ses->server, &rqst, midQ);
1be912dd 908 spin_lock(&GlobalMid_Lock);
7c9421e1 909 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1be912dd
JL
910 /* no longer considered to be "in-flight" */
911 midQ->callback = DeleteMidQEntry;
912 spin_unlock(&GlobalMid_Lock);
a891f0f8 913 add_credits(ses->server, 1, 0);
1be912dd
JL
914 return rc;
915 }
916 spin_unlock(&GlobalMid_Lock);
917 }
1da177e4 918
3c1105df 919 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 920 if (rc != 0) {
a891f0f8 921 add_credits(ses->server, 1, 0);
1da177e4
LT
922 return rc;
923 }
50c2f753 924
2c8f981d 925 if (!midQ->resp_buf || !out_buf ||
7c9421e1 926 midQ->mid_state != MID_RESPONSE_RECEIVED) {
2b2bdfba 927 rc = -EIO;
f96637be 928 cifs_dbg(VFS, "Bad MID state?\n");
2c8f981d 929 goto out;
1da177e4 930 }
7ee1af76 931
d4e4854f 932 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
2c8f981d
JL
933 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
934 rc = cifs_check_receive(midQ, ses->server, 0);
7ee1af76 935out:
3c1bf7e4 936 cifs_delete_mid(midQ);
a891f0f8 937 add_credits(ses->server, 1, 0);
1da177e4 938
7ee1af76
JA
939 return rc;
940}
1da177e4 941
7ee1af76
JA
942/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
943 blocking lock to return. */
944
945static int
96daf2b0 946send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
947 struct smb_hdr *in_buf,
948 struct smb_hdr *out_buf)
949{
950 int bytes_returned;
96daf2b0 951 struct cifs_ses *ses = tcon->ses;
7ee1af76
JA
952 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
953
954 /* We just modify the current in_buf to change
955 the type of lock from LOCKING_ANDX_SHARED_LOCK
956 or LOCKING_ANDX_EXCLUSIVE_LOCK to
957 LOCKING_ANDX_CANCEL_LOCK. */
958
959 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
960 pSMB->Timeout = 0;
88257360 961 pSMB->hdr.Mid = get_next_mid(ses->server);
7ee1af76
JA
962
963 return SendReceive(xid, ses, in_buf, out_buf,
7749981e 964 &bytes_returned, 0);
7ee1af76
JA
965}
966
967int
96daf2b0 968SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
969 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
970 int *pbytes_returned)
971{
972 int rc = 0;
973 int rstart = 0;
7ee1af76 974 struct mid_q_entry *midQ;
96daf2b0 975 struct cifs_ses *ses;
df976e8b
PS
976 unsigned int len = be32_to_cpu(in_buf->smb_buf_length);
977 struct kvec iov = { .iov_base = in_buf, .iov_len = len };
978 struct smb_rqst rqst = { .rq_iov = &iov, .rq_nvec = 1 };
7ee1af76
JA
979
980 if (tcon == NULL || tcon->ses == NULL) {
f96637be 981 cifs_dbg(VFS, "Null smb session\n");
7ee1af76
JA
982 return -EIO;
983 }
984 ses = tcon->ses;
985
79a58d1f 986 if (ses->server == NULL) {
f96637be 987 cifs_dbg(VFS, "Null tcp session\n");
7ee1af76
JA
988 return -EIO;
989 }
990
79a58d1f 991 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
992 return -ENOENT;
993
79a58d1f 994 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
995 to the same server. We may make this configurable later or
996 use ses->maxReq */
997
df976e8b 998 if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
f96637be 999 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
df976e8b 1000 len);
6d9c6d54
VL
1001 return -EIO;
1002 }
1003
a891f0f8 1004 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
7ee1af76
JA
1005 if (rc)
1006 return rc;
1007
79a58d1f 1008 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
1009 and avoid races inside tcp sendmsg code that could cause corruption
1010 of smb data */
1011
72ca545b 1012 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
1013
1014 rc = allocate_mid(ses, in_buf, &midQ);
1015 if (rc) {
72ca545b 1016 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
1017 return rc;
1018 }
1019
7ee1af76 1020 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb 1021 if (rc) {
3c1bf7e4 1022 cifs_delete_mid(midQ);
829049cb
VL
1023 mutex_unlock(&ses->server->srv_mutex);
1024 return rc;
1025 }
1da177e4 1026
7c9421e1 1027 midQ->mid_state = MID_REQUEST_SUBMITTED;
789e6661 1028 cifs_in_send_inc(ses->server);
df976e8b 1029 rc = smb_send(ses->server, in_buf, len);
789e6661
SF
1030 cifs_in_send_dec(ses->server);
1031 cifs_save_when_sent(midQ);
ad313cb8
JL
1032
1033 if (rc < 0)
1034 ses->server->sequence_number -= 2;
1035
72ca545b 1036 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 1037
79a58d1f 1038 if (rc < 0) {
3c1bf7e4 1039 cifs_delete_mid(midQ);
7ee1af76
JA
1040 return rc;
1041 }
1042
1043 /* Wait for a reply - allow signals to interrupt. */
1044 rc = wait_event_interruptible(ses->server->response_q,
7c9421e1 1045 (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
1046 ((ses->server->tcpStatus != CifsGood) &&
1047 (ses->server->tcpStatus != CifsNew)));
1048
1049 /* Were we interrupted by a signal ? */
1050 if ((rc == -ERESTARTSYS) &&
7c9421e1 1051 (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
7ee1af76
JA
1052 ((ses->server->tcpStatus == CifsGood) ||
1053 (ses->server->tcpStatus == CifsNew))) {
1054
1055 if (in_buf->Command == SMB_COM_TRANSACTION2) {
1056 /* POSIX lock. We send a NT_CANCEL SMB to cause the
1057 blocking lock to return. */
df976e8b 1058 rc = send_cancel(ses->server, &rqst, midQ);
7ee1af76 1059 if (rc) {
3c1bf7e4 1060 cifs_delete_mid(midQ);
7ee1af76
JA
1061 return rc;
1062 }
1063 } else {
1064 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
1065 to cause the blocking lock to return. */
1066
1067 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1068
1069 /* If we get -ENOLCK back the lock may have
1070 already been removed. Don't exit in this case. */
1071 if (rc && rc != -ENOLCK) {
3c1bf7e4 1072 cifs_delete_mid(midQ);
7ee1af76
JA
1073 return rc;
1074 }
1075 }
1076
1be912dd
JL
1077 rc = wait_for_response(ses->server, midQ);
1078 if (rc) {
df976e8b 1079 send_cancel(ses->server, &rqst, midQ);
1be912dd 1080 spin_lock(&GlobalMid_Lock);
7c9421e1 1081 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1be912dd
JL
1082 /* no longer considered to be "in-flight" */
1083 midQ->callback = DeleteMidQEntry;
1084 spin_unlock(&GlobalMid_Lock);
1085 return rc;
1086 }
1087 spin_unlock(&GlobalMid_Lock);
7ee1af76 1088 }
1be912dd
JL
1089
1090 /* We got the response - restart system call. */
1091 rstart = 1;
7ee1af76
JA
1092 }
1093
3c1105df 1094 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 1095 if (rc != 0)
7ee1af76 1096 return rc;
50c2f753 1097
17c8bfed 1098 /* rcvd frame is ok */
7c9421e1 1099 if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
698e96a8 1100 rc = -EIO;
f96637be 1101 cifs_dbg(VFS, "Bad MID state?\n");
698e96a8
VL
1102 goto out;
1103 }
1da177e4 1104
d4e4854f 1105 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
2c8f981d
JL
1106 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
1107 rc = cifs_check_receive(midQ, ses->server, 0);
17c8bfed 1108out:
3c1bf7e4 1109 cifs_delete_mid(midQ);
7ee1af76
JA
1110 if (rstart && rc == -EACCES)
1111 return -ERESTARTSYS;
1da177e4
LT
1112 return rc;
1113}