]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/cifs/transport.c
Merge branch 'slab/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/penberg...
[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>
29#include <asm/uaccess.h>
30#include <asm/processor.h>
31#include <linux/mempool.h>
32#include "cifspdu.h"
33#include "cifsglob.h"
34#include "cifsproto.h"
35#include "cifs_debug.h"
50c2f753 36
1da177e4 37extern mempool_t *cifs_mid_poolp;
1da177e4 38
2b84a36c
JL
39static void
40wake_up_task(struct mid_q_entry *mid)
41{
42 wake_up_process(mid->callback_data);
43}
44
a6827c18 45struct mid_q_entry *
24b9b06b 46AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
1da177e4
LT
47{
48 struct mid_q_entry *temp;
49
24b9b06b 50 if (server == NULL) {
b6b38f70 51 cERROR(1, "Null TCP session in AllocMidQEntry");
1da177e4
LT
52 return NULL;
53 }
50c2f753 54
232087cb 55 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
1da177e4
LT
56 if (temp == NULL)
57 return temp;
58 else {
26f57364 59 memset(temp, 0, sizeof(struct mid_q_entry));
1da177e4
LT
60 temp->mid = smb_buffer->Mid; /* always LE */
61 temp->pid = current->pid;
62 temp->command = smb_buffer->Command;
b6b38f70 63 cFYI(1, "For smb_command %d", temp->command);
1047abc1
SF
64 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
65 /* when mid allocated can be before when sent */
66 temp->when_alloc = jiffies;
2b84a36c
JL
67
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 = wake_up_task;
73 temp->callback_data = current;
1da177e4
LT
74 }
75
1da177e4
LT
76 atomic_inc(&midCount);
77 temp->midState = MID_REQUEST_ALLOCATED;
1da177e4
LT
78 return temp;
79}
80
766fdbb5 81void
1da177e4
LT
82DeleteMidQEntry(struct mid_q_entry *midEntry)
83{
1047abc1
SF
84#ifdef CONFIG_CIFS_STATS2
85 unsigned long now;
86#endif
1da177e4 87 midEntry->midState = MID_FREE;
8097531a 88 atomic_dec(&midCount);
79a58d1f 89 if (midEntry->largeBuf)
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 */
79a58d1f
SF
97 if ((now - midEntry->when_alloc) > HZ) {
98 if ((cifsFYI & CIFS_TIMER) &&
1047abc1
SF
99 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
100 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
101 midEntry->command, midEntry->mid);
102 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
103 now - midEntry->when_alloc,
104 now - midEntry->when_sent,
105 now - midEntry->when_received);
106 }
107 }
108#endif
1da177e4
LT
109 mempool_free(midEntry, cifs_mid_poolp);
110}
111
ddc8cf8f
JL
112static void
113delete_mid(struct mid_q_entry *mid)
114{
115 spin_lock(&GlobalMid_Lock);
116 list_del(&mid->qhead);
117 spin_unlock(&GlobalMid_Lock);
118
119 DeleteMidQEntry(mid);
120}
121
d6e04ae6 122static int
0496e02d 123smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
1da177e4
LT
124{
125 int rc = 0;
126 int i = 0;
127 struct msghdr smb_msg;
3e84469d
SF
128 struct smb_hdr *smb_buffer = iov[0].iov_base;
129 unsigned int len = iov[0].iov_len;
130 unsigned int total_len;
131 int first_vec = 0;
be8e3b00 132 unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length);
edf1ae40 133 struct socket *ssocket = server->ssocket;
50c2f753 134
79a58d1f 135 if (ssocket == NULL)
1da177e4 136 return -ENOTSOCK; /* BB eventually add reconnect code here */
3e84469d 137
a9f1b85e 138 smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
26f57364 139 smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4
LT
140 smb_msg.msg_control = NULL;
141 smb_msg.msg_controllen = 0;
0496e02d 142 if (server->noblocksnd)
edf1ae40
SF
143 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
144 else
145 smb_msg.msg_flags = MSG_NOSIGNAL;
1da177e4 146
3e84469d
SF
147 total_len = 0;
148 for (i = 0; i < n_vec; i++)
149 total_len += iov[i].iov_len;
150
b6b38f70 151 cFYI(1, "Sending smb: total_len %d", total_len);
1da177e4
LT
152 dump_smb(smb_buffer, len);
153
17680356 154 i = 0;
3e84469d
SF
155 while (total_len) {
156 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
157 n_vec - first_vec, total_len);
1da177e4
LT
158 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
159 i++;
da505c38
SF
160 /* if blocking send we try 3 times, since each can block
161 for 5 seconds. For nonblocking we have to try more
162 but wait increasing amounts of time allowing time for
163 socket to clear. The overall time we wait in either
164 case to send on the socket is about 15 seconds.
165 Similarly we wait for 15 seconds for
166 a response from the server in SendReceive[2]
167 for the server to send a response back for
168 most types of requests (except SMB Write
169 past end of file which can be slow, and
170 blocking lock operations). NFS waits slightly longer
171 than CIFS, but this can make it take longer for
172 nonresponsive servers to be detected and 15 seconds
173 is more than enough time for modern networks to
174 send a packet. In most cases if we fail to send
175 after the retries we will kill the socket and
176 reconnect which may clear the network problem.
177 */
178 if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
b6b38f70
JP
179 cERROR(1, "sends on sock %p stuck for 15 seconds",
180 ssocket);
1da177e4
LT
181 rc = -EAGAIN;
182 break;
183 }
68058e75 184 msleep(1 << i);
1da177e4
LT
185 continue;
186 }
79a58d1f 187 if (rc < 0)
1da177e4 188 break;
3e84469d 189
61de800d
SF
190 if (rc == total_len) {
191 total_len = 0;
192 break;
193 } else if (rc > total_len) {
b6b38f70 194 cERROR(1, "sent %d requested %d", rc, total_len);
3e84469d
SF
195 break;
196 }
79a58d1f 197 if (rc == 0) {
3e84469d
SF
198 /* should never happen, letting socket clear before
199 retrying is our only obvious option here */
b6b38f70 200 cERROR(1, "tcp sent no data");
3e84469d
SF
201 msleep(500);
202 continue;
d6e04ae6 203 }
3e84469d 204 total_len -= rc;
68058e75 205 /* the line below resets i */
3e84469d
SF
206 for (i = first_vec; i < n_vec; i++) {
207 if (iov[i].iov_len) {
208 if (rc > iov[i].iov_len) {
209 rc -= iov[i].iov_len;
210 iov[i].iov_len = 0;
211 } else {
212 iov[i].iov_base += rc;
213 iov[i].iov_len -= rc;
214 first_vec = i;
215 break;
216 }
217 }
d6e04ae6 218 }
5e1253b5 219 i = 0; /* in case we get ENOSPC on the next send */
1da177e4
LT
220 }
221
edf1ae40 222 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
b6b38f70
JP
223 cFYI(1, "partial send (%d remaining), terminating session",
224 total_len);
edf1ae40
SF
225 /* If we have only sent part of an SMB then the next SMB
226 could be taken as the remainder of this one. We need
227 to kill the socket so the server throws away the partial
228 SMB */
229 server->tcpStatus = CifsNeedReconnect;
230 }
231
d804d41d 232 if (rc < 0 && rc != -EINTR)
b6b38f70 233 cERROR(1, "Error %d sending data on socket to server", rc);
d804d41d 234 else
1da177e4 235 rc = 0;
1da177e4 236
7ee1af76
JA
237 /* Don't want to modify the buffer as a
238 side effect of this call. */
be8e3b00 239 smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length);
7ee1af76 240
1da177e4
LT
241 return rc;
242}
243
0496e02d
JL
244int
245smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
246 unsigned int smb_buf_length)
247{
248 struct kvec iov;
249
250 iov.iov_base = smb_buffer;
251 iov.iov_len = smb_buf_length + 4;
252
253 return smb_sendv(server, &iov, 1);
254}
255
c5797a94
JL
256static int wait_for_free_request(struct TCP_Server_Info *server,
257 const int long_op)
1da177e4 258{
133672ef 259 if (long_op == CIFS_ASYNC_OP) {
1da177e4 260 /* oplock breaks must not be held up */
c5797a94 261 atomic_inc(&server->inFlight);
27a97a61
VL
262 return 0;
263 }
264
265 spin_lock(&GlobalMid_Lock);
266 while (1) {
c5797a94 267 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
27a97a61 268 spin_unlock(&GlobalMid_Lock);
131afd0b 269#ifdef CONFIG_CIFS_STATS2
c5797a94 270 atomic_inc(&server->num_waiters);
131afd0b 271#endif
c5797a94
JL
272 wait_event(server->request_q,
273 atomic_read(&server->inFlight)
27a97a61 274 < cifs_max_pending);
131afd0b 275#ifdef CONFIG_CIFS_STATS2
c5797a94 276 atomic_dec(&server->num_waiters);
131afd0b 277#endif
27a97a61
VL
278 spin_lock(&GlobalMid_Lock);
279 } else {
c5797a94 280 if (server->tcpStatus == CifsExiting) {
1da177e4 281 spin_unlock(&GlobalMid_Lock);
27a97a61 282 return -ENOENT;
1da177e4 283 }
27a97a61
VL
284
285 /* can not count locking commands against total
286 as they are allowed to block on server */
287
288 /* update # of requests on the wire to server */
289 if (long_op != CIFS_BLOCKING_OP)
c5797a94 290 atomic_inc(&server->inFlight);
27a97a61
VL
291 spin_unlock(&GlobalMid_Lock);
292 break;
1da177e4
LT
293 }
294 }
7ee1af76
JA
295 return 0;
296}
1da177e4 297
96daf2b0 298static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
7ee1af76
JA
299 struct mid_q_entry **ppmidQ)
300{
1da177e4 301 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 302 return -ENOENT;
8fbbd365
VL
303 }
304
305 if (ses->server->tcpStatus == CifsNeedReconnect) {
b6b38f70 306 cFYI(1, "tcp session dead - return to caller to retry");
7ee1af76 307 return -EAGAIN;
8fbbd365
VL
308 }
309
310 if (ses->status != CifsGood) {
1da177e4 311 /* check if SMB session is bad because we are setting it up */
79a58d1f 312 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926 313 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 314 return -EAGAIN;
ad7a2926 315 /* else ok - we are setting up session */
1da177e4 316 }
24b9b06b 317 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364 318 if (*ppmidQ == NULL)
7ee1af76 319 return -ENOMEM;
ddc8cf8f
JL
320 spin_lock(&GlobalMid_Lock);
321 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
322 spin_unlock(&GlobalMid_Lock);
7ee1af76
JA
323 return 0;
324}
325
0ade640e
JL
326static int
327wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
7ee1af76 328{
0ade640e 329 int error;
7ee1af76 330
0ade640e
JL
331 error = wait_event_killable(server->response_q,
332 midQ->midState != MID_REQUEST_SUBMITTED);
333 if (error < 0)
334 return -ERESTARTSYS;
7ee1af76 335
0ade640e 336 return 0;
7ee1af76
JA
337}
338
133672ef 339
a6827c18
JL
340/*
341 * Send a SMB request and set the callback function in the mid to handle
342 * the result. Caller is responsible for dealing with timeouts.
343 */
344int
fcc31cb6 345cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
59ffd841
JL
346 unsigned int nvec, mid_callback_t *callback, void *cbdata,
347 bool ignore_pend)
a6827c18
JL
348{
349 int rc;
350 struct mid_q_entry *mid;
fcc31cb6 351 struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
a6827c18 352
59ffd841 353 rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0);
a6827c18
JL
354 if (rc)
355 return rc;
356
e3f0dadb 357 /* enable signing if server requires it */
96daf2b0 358 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
fcc31cb6 359 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
e3f0dadb 360
a6827c18 361 mutex_lock(&server->srv_mutex);
fcc31cb6 362 mid = AllocMidQEntry(hdr, server);
a6827c18
JL
363 if (mid == NULL) {
364 mutex_unlock(&server->srv_mutex);
0193e072
PS
365 atomic_dec(&server->inFlight);
366 wake_up(&server->request_q);
a6827c18
JL
367 return -ENOMEM;
368 }
369
370 /* put it on the pending_mid_q */
371 spin_lock(&GlobalMid_Lock);
372 list_add_tail(&mid->qhead, &server->pending_mid_q);
373 spin_unlock(&GlobalMid_Lock);
374
fcc31cb6 375 rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
a6827c18
JL
376 if (rc) {
377 mutex_unlock(&server->srv_mutex);
378 goto out_err;
379 }
380
381 mid->callback = callback;
382 mid->callback_data = cbdata;
383 mid->midState = MID_REQUEST_SUBMITTED;
384#ifdef CONFIG_CIFS_STATS2
385 atomic_inc(&server->inSend);
386#endif
fcc31cb6 387 rc = smb_sendv(server, iov, nvec);
a6827c18
JL
388#ifdef CONFIG_CIFS_STATS2
389 atomic_dec(&server->inSend);
390 mid->when_sent = jiffies;
391#endif
392 mutex_unlock(&server->srv_mutex);
393 if (rc)
394 goto out_err;
395
396 return rc;
397out_err:
398 delete_mid(mid);
399 atomic_dec(&server->inFlight);
400 wake_up(&server->request_q);
401 return rc;
402}
403
133672ef
SF
404/*
405 *
406 * Send an SMB Request. No response info (other than return code)
407 * needs to be parsed.
408 *
409 * flags indicate the type of request buffer and how long to wait
410 * and whether to log NT STATUS code (error) before mapping it to POSIX error
411 *
412 */
413int
96daf2b0 414SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
133672ef
SF
415 struct smb_hdr *in_buf, int flags)
416{
417 int rc;
418 struct kvec iov[1];
419 int resp_buf_type;
420
421 iov[0].iov_base = (char *)in_buf;
be8e3b00 422 iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4;
133672ef
SF
423 flags |= CIFS_NO_RESP;
424 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
b6b38f70 425 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
90c81e0b 426
133672ef
SF
427 return rc;
428}
429
053d5034 430static int
3c1105df 431cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
053d5034
JL
432{
433 int rc = 0;
434
74dd92a8
JL
435 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
436 mid->mid, mid->midState);
053d5034 437
74dd92a8
JL
438 spin_lock(&GlobalMid_Lock);
439 switch (mid->midState) {
440 case MID_RESPONSE_RECEIVED:
053d5034
JL
441 spin_unlock(&GlobalMid_Lock);
442 return rc;
74dd92a8
JL
443 case MID_RETRY_NEEDED:
444 rc = -EAGAIN;
445 break;
71823baf
JL
446 case MID_RESPONSE_MALFORMED:
447 rc = -EIO;
448 break;
3c1105df
JL
449 case MID_SHUTDOWN:
450 rc = -EHOSTDOWN;
451 break;
74dd92a8 452 default:
3c1105df 453 list_del_init(&mid->qhead);
74dd92a8
JL
454 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
455 mid->mid, mid->midState);
456 rc = -EIO;
053d5034
JL
457 }
458 spin_unlock(&GlobalMid_Lock);
459
2b84a36c 460 DeleteMidQEntry(mid);
053d5034
JL
461 return rc;
462}
463
76dcc26f
JL
464/*
465 * An NT cancel request header looks just like the original request except:
466 *
467 * The Command is SMB_COM_NT_CANCEL
468 * The WordCount is zeroed out
469 * The ByteCount is zeroed out
470 *
471 * This function mangles an existing request buffer into a
472 * SMB_COM_NT_CANCEL request and then sends it.
473 */
474static int
475send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
476 struct mid_q_entry *mid)
477{
478 int rc = 0;
479
480 /* -4 for RFC1001 length and +2 for BCC field */
be8e3b00 481 in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
76dcc26f
JL
482 in_buf->Command = SMB_COM_NT_CANCEL;
483 in_buf->WordCount = 0;
820a803f 484 put_bcc(0, in_buf);
76dcc26f
JL
485
486 mutex_lock(&server->srv_mutex);
487 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
488 if (rc) {
489 mutex_unlock(&server->srv_mutex);
490 return rc;
491 }
be8e3b00 492 rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
76dcc26f
JL
493 mutex_unlock(&server->srv_mutex);
494
495 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
496 in_buf->Mid, rc);
497
498 return rc;
499}
500
2c8f981d
JL
501int
502cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
503 bool log_error)
504{
505 dump_smb(mid->resp_buf,
506 min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length)));
507
508 /* convert the length into a more usable form */
96daf2b0 509 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
2c8f981d
JL
510 /* FIXME: add code to kill session */
511 if (cifs_verify_signature(mid->resp_buf, server,
512 mid->sequence_number + 1) != 0)
513 cERROR(1, "Unexpected SMB signature");
514 }
515
516 /* BB special case reconnect tid and uid here? */
517 return map_smb_to_linux_error(mid->resp_buf, log_error);
518}
519
7ee1af76 520int
96daf2b0 521SendReceive2(const unsigned int xid, struct cifs_ses *ses,
79a58d1f 522 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 523 const int flags)
7ee1af76
JA
524{
525 int rc = 0;
133672ef 526 int long_op;
7ee1af76
JA
527 struct mid_q_entry *midQ;
528 struct smb_hdr *in_buf = iov[0].iov_base;
50c2f753 529
133672ef
SF
530 long_op = flags & CIFS_TIMEOUT_MASK;
531
7ee1af76
JA
532 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
533
534 if ((ses == NULL) || (ses->server == NULL)) {
535 cifs_small_buf_release(in_buf);
b6b38f70 536 cERROR(1, "Null session");
7ee1af76
JA
537 return -EIO;
538 }
539
79a58d1f 540 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76
JA
541 cifs_small_buf_release(in_buf);
542 return -ENOENT;
543 }
544
79a58d1f 545 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
546 to the same server. We may make this configurable later or
547 use ses->maxReq */
548
c5797a94 549 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
550 if (rc) {
551 cifs_small_buf_release(in_buf);
552 return rc;
553 }
554
79a58d1f 555 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
556 and avoid races inside tcp sendmsg code that could cause corruption
557 of smb data */
558
72ca545b 559 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
560
561 rc = allocate_mid(ses, in_buf, &midQ);
562 if (rc) {
72ca545b 563 mutex_unlock(&ses->server->srv_mutex);
4b8f930f 564 cifs_small_buf_release(in_buf);
7ee1af76 565 /* Update # of requests on wire to server */
79a58d1f 566 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
567 wake_up(&ses->server->request_q);
568 return rc;
1da177e4 569 }
79a58d1f 570 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
829049cb
VL
571 if (rc) {
572 mutex_unlock(&ses->server->srv_mutex);
573 cifs_small_buf_release(in_buf);
574 goto out;
575 }
1da177e4
LT
576
577 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
578#ifdef CONFIG_CIFS_STATS2
579 atomic_inc(&ses->server->inSend);
580#endif
0496e02d 581 rc = smb_sendv(ses->server, iov, n_vec);
131afd0b
SF
582#ifdef CONFIG_CIFS_STATS2
583 atomic_dec(&ses->server->inSend);
1047abc1 584 midQ->when_sent = jiffies;
131afd0b 585#endif
7ee1af76 586
72ca545b 587 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 588
2db7c581
JL
589 if (rc < 0) {
590 cifs_small_buf_release(in_buf);
7ee1af76 591 goto out;
2db7c581 592 }
4b8f930f 593
2db7c581
JL
594 if (long_op == CIFS_ASYNC_OP) {
595 cifs_small_buf_release(in_buf);
133672ef 596 goto out;
2db7c581 597 }
d6e04ae6 598
0ade640e 599 rc = wait_for_response(ses->server, midQ);
1be912dd 600 if (rc != 0) {
2db7c581 601 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
602 spin_lock(&GlobalMid_Lock);
603 if (midQ->midState == MID_REQUEST_SUBMITTED) {
604 midQ->callback = DeleteMidQEntry;
605 spin_unlock(&GlobalMid_Lock);
2db7c581 606 cifs_small_buf_release(in_buf);
1be912dd
JL
607 atomic_dec(&ses->server->inFlight);
608 wake_up(&ses->server->request_q);
609 return rc;
610 }
611 spin_unlock(&GlobalMid_Lock);
612 }
d6e04ae6 613
2db7c581
JL
614 cifs_small_buf_release(in_buf);
615
3c1105df 616 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 617 if (rc != 0) {
79a58d1f 618 atomic_dec(&ses->server->inFlight);
7ee1af76 619 wake_up(&ses->server->request_q);
d6e04ae6
SF
620 return rc;
621 }
50c2f753 622
2c8f981d 623 if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) {
d6e04ae6 624 rc = -EIO;
2c8f981d 625 cFYI(1, "Bad MID state?");
2b2bdfba
SF
626 goto out;
627 }
628
2c8f981d
JL
629 iov[0].iov_base = (char *)midQ->resp_buf;
630 iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4;
631 if (midQ->largeBuf)
632 *pRespBufType = CIFS_LARGE_BUFFER;
633 else
634 *pRespBufType = CIFS_SMALL_BUFFER;
2b2bdfba 635
2c8f981d 636 rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR);
1da177e4 637
2c8f981d
JL
638 /* mark it so buf will not be freed by delete_mid */
639 if ((flags & CIFS_NO_RESP) == 0)
640 midQ->resp_buf = NULL;
7ee1af76 641out:
ddc8cf8f 642 delete_mid(midQ);
79a58d1f 643 atomic_dec(&ses->server->inFlight);
7ee1af76 644 wake_up(&ses->server->request_q);
1da177e4 645
d6e04ae6
SF
646 return rc;
647}
1da177e4
LT
648
649int
96daf2b0 650SendReceive(const unsigned int xid, struct cifs_ses *ses,
1da177e4
LT
651 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
652 int *pbytes_returned, const int long_op)
653{
654 int rc = 0;
1da177e4
LT
655 struct mid_q_entry *midQ;
656
657 if (ses == NULL) {
b6b38f70 658 cERROR(1, "Null smb session");
1da177e4
LT
659 return -EIO;
660 }
79a58d1f 661 if (ses->server == NULL) {
b6b38f70 662 cERROR(1, "Null tcp session");
1da177e4
LT
663 return -EIO;
664 }
665
79a58d1f 666 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
667 return -ENOENT;
668
79a58d1f 669 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
670 to the same server. We may make this configurable later or
671 use ses->maxReq */
1da177e4 672
be8e3b00
SF
673 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
674 MAX_CIFS_HDR_SIZE - 4) {
b6b38f70 675 cERROR(1, "Illegal length, greater than maximum frame, %d",
be8e3b00 676 be32_to_cpu(in_buf->smb_buf_length));
6d9c6d54
VL
677 return -EIO;
678 }
679
c5797a94 680 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
681 if (rc)
682 return rc;
683
79a58d1f 684 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
685 and avoid races inside tcp sendmsg code that could cause corruption
686 of smb data */
687
72ca545b 688 mutex_lock(&ses->server->srv_mutex);
1da177e4 689
7ee1af76
JA
690 rc = allocate_mid(ses, in_buf, &midQ);
691 if (rc) {
72ca545b 692 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 693 /* Update # of requests on wire to server */
79a58d1f 694 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
695 wake_up(&ses->server->request_q);
696 return rc;
1da177e4
LT
697 }
698
ad009ac9 699 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb
VL
700 if (rc) {
701 mutex_unlock(&ses->server->srv_mutex);
702 goto out;
703 }
1da177e4
LT
704
705 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
706#ifdef CONFIG_CIFS_STATS2
707 atomic_inc(&ses->server->inSend);
708#endif
be8e3b00 709 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
131afd0b
SF
710#ifdef CONFIG_CIFS_STATS2
711 atomic_dec(&ses->server->inSend);
1047abc1 712 midQ->when_sent = jiffies;
131afd0b 713#endif
72ca545b 714 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 715
79a58d1f 716 if (rc < 0)
7ee1af76
JA
717 goto out;
718
0ade640e 719 if (long_op == CIFS_ASYNC_OP)
7ee1af76 720 goto out;
1da177e4 721
0ade640e 722 rc = wait_for_response(ses->server, midQ);
1be912dd 723 if (rc != 0) {
2db7c581 724 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
725 spin_lock(&GlobalMid_Lock);
726 if (midQ->midState == MID_REQUEST_SUBMITTED) {
727 /* no longer considered to be "in-flight" */
728 midQ->callback = DeleteMidQEntry;
729 spin_unlock(&GlobalMid_Lock);
730 atomic_dec(&ses->server->inFlight);
731 wake_up(&ses->server->request_q);
732 return rc;
733 }
734 spin_unlock(&GlobalMid_Lock);
735 }
1da177e4 736
3c1105df 737 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 738 if (rc != 0) {
79a58d1f 739 atomic_dec(&ses->server->inFlight);
7ee1af76 740 wake_up(&ses->server->request_q);
1da177e4
LT
741 return rc;
742 }
50c2f753 743
2c8f981d
JL
744 if (!midQ->resp_buf || !out_buf ||
745 midQ->midState != MID_RESPONSE_RECEIVED) {
2b2bdfba 746 rc = -EIO;
b6b38f70 747 cERROR(1, "Bad MID state?");
2c8f981d 748 goto out;
1da177e4 749 }
7ee1af76 750
2c8f981d
JL
751 *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
752 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
753 rc = cifs_check_receive(midQ, ses->server, 0);
7ee1af76 754out:
ddc8cf8f 755 delete_mid(midQ);
79a58d1f 756 atomic_dec(&ses->server->inFlight);
7ee1af76 757 wake_up(&ses->server->request_q);
1da177e4 758
7ee1af76
JA
759 return rc;
760}
1da177e4 761
7ee1af76
JA
762/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
763 blocking lock to return. */
764
765static int
96daf2b0 766send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
767 struct smb_hdr *in_buf,
768 struct smb_hdr *out_buf)
769{
770 int bytes_returned;
96daf2b0 771 struct cifs_ses *ses = tcon->ses;
7ee1af76
JA
772 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
773
774 /* We just modify the current in_buf to change
775 the type of lock from LOCKING_ANDX_SHARED_LOCK
776 or LOCKING_ANDX_EXCLUSIVE_LOCK to
777 LOCKING_ANDX_CANCEL_LOCK. */
778
779 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
780 pSMB->Timeout = 0;
781 pSMB->hdr.Mid = GetNextMid(ses->server);
782
783 return SendReceive(xid, ses, in_buf, out_buf,
7749981e 784 &bytes_returned, 0);
7ee1af76
JA
785}
786
787int
96daf2b0 788SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
789 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
790 int *pbytes_returned)
791{
792 int rc = 0;
793 int rstart = 0;
7ee1af76 794 struct mid_q_entry *midQ;
96daf2b0 795 struct cifs_ses *ses;
7ee1af76
JA
796
797 if (tcon == NULL || tcon->ses == NULL) {
b6b38f70 798 cERROR(1, "Null smb session");
7ee1af76
JA
799 return -EIO;
800 }
801 ses = tcon->ses;
802
79a58d1f 803 if (ses->server == NULL) {
b6b38f70 804 cERROR(1, "Null tcp session");
7ee1af76
JA
805 return -EIO;
806 }
807
79a58d1f 808 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
809 return -ENOENT;
810
79a58d1f 811 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
812 to the same server. We may make this configurable later or
813 use ses->maxReq */
814
be8e3b00
SF
815 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
816 MAX_CIFS_HDR_SIZE - 4) {
b6b38f70 817 cERROR(1, "Illegal length, greater than maximum frame, %d",
be8e3b00 818 be32_to_cpu(in_buf->smb_buf_length));
6d9c6d54
VL
819 return -EIO;
820 }
821
c5797a94 822 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
7ee1af76
JA
823 if (rc)
824 return rc;
825
79a58d1f 826 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
827 and avoid races inside tcp sendmsg code that could cause corruption
828 of smb data */
829
72ca545b 830 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
831
832 rc = allocate_mid(ses, in_buf, &midQ);
833 if (rc) {
72ca545b 834 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
835 return rc;
836 }
837
7ee1af76 838 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb 839 if (rc) {
ddc8cf8f 840 delete_mid(midQ);
829049cb
VL
841 mutex_unlock(&ses->server->srv_mutex);
842 return rc;
843 }
1da177e4 844
7ee1af76
JA
845 midQ->midState = MID_REQUEST_SUBMITTED;
846#ifdef CONFIG_CIFS_STATS2
847 atomic_inc(&ses->server->inSend);
848#endif
be8e3b00 849 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
7ee1af76
JA
850#ifdef CONFIG_CIFS_STATS2
851 atomic_dec(&ses->server->inSend);
852 midQ->when_sent = jiffies;
853#endif
72ca545b 854 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 855
79a58d1f 856 if (rc < 0) {
ddc8cf8f 857 delete_mid(midQ);
7ee1af76
JA
858 return rc;
859 }
860
861 /* Wait for a reply - allow signals to interrupt. */
862 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 863 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
864 ((ses->server->tcpStatus != CifsGood) &&
865 (ses->server->tcpStatus != CifsNew)));
866
867 /* Were we interrupted by a signal ? */
868 if ((rc == -ERESTARTSYS) &&
869 (midQ->midState == MID_REQUEST_SUBMITTED) &&
870 ((ses->server->tcpStatus == CifsGood) ||
871 (ses->server->tcpStatus == CifsNew))) {
872
873 if (in_buf->Command == SMB_COM_TRANSACTION2) {
874 /* POSIX lock. We send a NT_CANCEL SMB to cause the
875 blocking lock to return. */
76dcc26f 876 rc = send_nt_cancel(ses->server, in_buf, midQ);
7ee1af76 877 if (rc) {
ddc8cf8f 878 delete_mid(midQ);
7ee1af76
JA
879 return rc;
880 }
881 } else {
882 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
883 to cause the blocking lock to return. */
884
885 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
886
887 /* If we get -ENOLCK back the lock may have
888 already been removed. Don't exit in this case. */
889 if (rc && rc != -ENOLCK) {
ddc8cf8f 890 delete_mid(midQ);
7ee1af76
JA
891 return rc;
892 }
893 }
894
1be912dd
JL
895 rc = wait_for_response(ses->server, midQ);
896 if (rc) {
2db7c581 897 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
898 spin_lock(&GlobalMid_Lock);
899 if (midQ->midState == MID_REQUEST_SUBMITTED) {
900 /* no longer considered to be "in-flight" */
901 midQ->callback = DeleteMidQEntry;
902 spin_unlock(&GlobalMid_Lock);
903 return rc;
904 }
905 spin_unlock(&GlobalMid_Lock);
7ee1af76 906 }
1be912dd
JL
907
908 /* We got the response - restart system call. */
909 rstart = 1;
7ee1af76
JA
910 }
911
3c1105df 912 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 913 if (rc != 0)
7ee1af76 914 return rc;
50c2f753 915
17c8bfed 916 /* rcvd frame is ok */
2c8f981d 917 if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) {
698e96a8 918 rc = -EIO;
b6b38f70 919 cERROR(1, "Bad MID state?");
698e96a8
VL
920 goto out;
921 }
1da177e4 922
2c8f981d
JL
923 *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
924 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
925 rc = cifs_check_receive(midQ, ses->server, 0);
17c8bfed 926out:
ddc8cf8f 927 delete_mid(midQ);
7ee1af76
JA
928 if (rstart && rc == -EACCES)
929 return -ERESTARTSYS;
1da177e4
LT
930 return rc;
931}