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