CIFS: Separate protocol-specific code from transport routines
[deliverable/linux.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;
63 temp->command = smb_buffer->Command;
b6b38f70 64 cFYI(1, "For smb_command %d", temp->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
LT
77 atomic_inc(&midCount);
78 temp->midState = 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
1da177e4 88 midEntry->midState = MID_FREE;
8097531a 89 atomic_dec(&midCount);
79a58d1f 90 if (midEntry->largeBuf)
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) &&
1047abc1
SF
100 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
101 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
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{
307 return wait_for_free_credits(server, optype, get_credits_field(server));
308}
309
96daf2b0 310static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
7ee1af76
JA
311 struct mid_q_entry **ppmidQ)
312{
1da177e4 313 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 314 return -ENOENT;
8fbbd365
VL
315 }
316
317 if (ses->server->tcpStatus == CifsNeedReconnect) {
b6b38f70 318 cFYI(1, "tcp session dead - return to caller to retry");
7ee1af76 319 return -EAGAIN;
8fbbd365
VL
320 }
321
322 if (ses->status != CifsGood) {
1da177e4 323 /* check if SMB session is bad because we are setting it up */
79a58d1f 324 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926 325 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 326 return -EAGAIN;
ad7a2926 327 /* else ok - we are setting up session */
1da177e4 328 }
24b9b06b 329 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364 330 if (*ppmidQ == NULL)
7ee1af76 331 return -ENOMEM;
ddc8cf8f
JL
332 spin_lock(&GlobalMid_Lock);
333 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
334 spin_unlock(&GlobalMid_Lock);
7ee1af76
JA
335 return 0;
336}
337
0ade640e
JL
338static int
339wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
7ee1af76 340{
0ade640e 341 int error;
7ee1af76 342
f06ac72e 343 error = wait_event_freezekillable(server->response_q,
0ade640e
JL
344 midQ->midState != MID_REQUEST_SUBMITTED);
345 if (error < 0)
346 return -ERESTARTSYS;
7ee1af76 347
0ade640e 348 return 0;
7ee1af76
JA
349}
350
792af7b0
PS
351static int
352cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov,
353 unsigned int nvec, struct mid_q_entry **ret_mid)
354{
355 int rc;
356 struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
357 struct mid_q_entry *mid;
358
359 /* enable signing if server requires it */
360 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
361 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
362
363 mid = AllocMidQEntry(hdr, server);
364 if (mid == NULL)
365 return -ENOMEM;
366
367 /* put it on the pending_mid_q */
368 spin_lock(&GlobalMid_Lock);
369 list_add_tail(&mid->qhead, &server->pending_mid_q);
370 spin_unlock(&GlobalMid_Lock);
371
372 rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number);
373 if (rc)
374 delete_mid(mid);
375 *ret_mid = mid;
376 return rc;
377}
133672ef 378
a6827c18
JL
379/*
380 * Send a SMB request and set the callback function in the mid to handle
381 * the result. Caller is responsible for dealing with timeouts.
382 */
383int
fcc31cb6 384cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov,
44d22d84
JL
385 unsigned int nvec, mid_receive_t *receive,
386 mid_callback_t *callback, void *cbdata, bool ignore_pend)
a6827c18
JL
387{
388 int rc;
389 struct mid_q_entry *mid;
390
59ffd841 391 rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0);
a6827c18
JL
392 if (rc)
393 return rc;
394
395 mutex_lock(&server->srv_mutex);
792af7b0
PS
396 rc = cifs_setup_async_request(server, iov, nvec, &mid);
397 if (rc) {
a6827c18 398 mutex_unlock(&server->srv_mutex);
2d86dbc9 399 cifs_add_credits(server, 1);
0193e072 400 wake_up(&server->request_q);
792af7b0 401 return rc;
a6827c18
JL
402 }
403
44d22d84 404 mid->receive = receive;
a6827c18
JL
405 mid->callback = callback;
406 mid->callback_data = cbdata;
407 mid->midState = MID_REQUEST_SUBMITTED;
789e6661
SF
408
409 cifs_in_send_inc(server);
fcc31cb6 410 rc = smb_sendv(server, iov, nvec);
789e6661
SF
411 cifs_in_send_dec(server);
412 cifs_save_when_sent(mid);
a6827c18 413 mutex_unlock(&server->srv_mutex);
789e6661 414
a6827c18
JL
415 if (rc)
416 goto out_err;
417
418 return rc;
419out_err:
420 delete_mid(mid);
2d86dbc9 421 cifs_add_credits(server, 1);
a6827c18
JL
422 wake_up(&server->request_q);
423 return rc;
424}
425
133672ef
SF
426/*
427 *
428 * Send an SMB Request. No response info (other than return code)
429 * needs to be parsed.
430 *
431 * flags indicate the type of request buffer and how long to wait
432 * and whether to log NT STATUS code (error) before mapping it to POSIX error
433 *
434 */
435int
96daf2b0 436SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
792af7b0 437 char *in_buf, int flags)
133672ef
SF
438{
439 int rc;
440 struct kvec iov[1];
441 int resp_buf_type;
442
792af7b0
PS
443 iov[0].iov_base = in_buf;
444 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
133672ef
SF
445 flags |= CIFS_NO_RESP;
446 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
b6b38f70 447 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
90c81e0b 448
133672ef
SF
449 return rc;
450}
451
053d5034 452static int
3c1105df 453cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
053d5034
JL
454{
455 int rc = 0;
456
74dd92a8
JL
457 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
458 mid->mid, mid->midState);
053d5034 459
74dd92a8
JL
460 spin_lock(&GlobalMid_Lock);
461 switch (mid->midState) {
462 case MID_RESPONSE_RECEIVED:
053d5034
JL
463 spin_unlock(&GlobalMid_Lock);
464 return rc;
74dd92a8
JL
465 case MID_RETRY_NEEDED:
466 rc = -EAGAIN;
467 break;
71823baf
JL
468 case MID_RESPONSE_MALFORMED:
469 rc = -EIO;
470 break;
3c1105df
JL
471 case MID_SHUTDOWN:
472 rc = -EHOSTDOWN;
473 break;
74dd92a8 474 default:
3c1105df 475 list_del_init(&mid->qhead);
74dd92a8
JL
476 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
477 mid->mid, mid->midState);
478 rc = -EIO;
053d5034
JL
479 }
480 spin_unlock(&GlobalMid_Lock);
481
2b84a36c 482 DeleteMidQEntry(mid);
053d5034
JL
483 return rc;
484}
485
76dcc26f
JL
486/*
487 * An NT cancel request header looks just like the original request except:
488 *
489 * The Command is SMB_COM_NT_CANCEL
490 * The WordCount is zeroed out
491 * The ByteCount is zeroed out
492 *
493 * This function mangles an existing request buffer into a
494 * SMB_COM_NT_CANCEL request and then sends it.
495 */
496static int
497send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
498 struct mid_q_entry *mid)
499{
500 int rc = 0;
501
502 /* -4 for RFC1001 length and +2 for BCC field */
be8e3b00 503 in_buf->smb_buf_length = cpu_to_be32(sizeof(struct smb_hdr) - 4 + 2);
76dcc26f
JL
504 in_buf->Command = SMB_COM_NT_CANCEL;
505 in_buf->WordCount = 0;
820a803f 506 put_bcc(0, in_buf);
76dcc26f
JL
507
508 mutex_lock(&server->srv_mutex);
509 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
510 if (rc) {
511 mutex_unlock(&server->srv_mutex);
512 return rc;
513 }
be8e3b00 514 rc = smb_send(server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
76dcc26f
JL
515 mutex_unlock(&server->srv_mutex);
516
517 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
518 in_buf->Mid, rc);
519
520 return rc;
521}
522
2c8f981d
JL
523int
524cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
525 bool log_error)
526{
792af7b0 527 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
826a95e4
JL
528
529 dump_smb(mid->resp_buf, min_t(u32, 92, len));
2c8f981d
JL
530
531 /* convert the length into a more usable form */
96daf2b0 532 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
826a95e4
JL
533 struct kvec iov;
534
535 iov.iov_base = mid->resp_buf;
536 iov.iov_len = len;
2c8f981d 537 /* FIXME: add code to kill session */
826a95e4 538 if (cifs_verify_signature(&iov, 1, server,
2c8f981d
JL
539 mid->sequence_number + 1) != 0)
540 cERROR(1, "Unexpected SMB signature");
541 }
542
543 /* BB special case reconnect tid and uid here? */
544 return map_smb_to_linux_error(mid->resp_buf, log_error);
545}
546
792af7b0
PS
547static int
548cifs_setup_request(struct cifs_ses *ses, struct kvec *iov,
549 unsigned int nvec, struct mid_q_entry **ret_mid)
550{
551 int rc;
552 struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base;
553 struct mid_q_entry *mid;
554
555 rc = allocate_mid(ses, hdr, &mid);
556 if (rc)
557 return rc;
558 rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number);
559 if (rc)
560 delete_mid(mid);
561 *ret_mid = mid;
562 return rc;
563}
564
7ee1af76 565int
96daf2b0 566SendReceive2(const unsigned int xid, struct cifs_ses *ses,
79a58d1f 567 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 568 const int flags)
7ee1af76
JA
569{
570 int rc = 0;
133672ef 571 int long_op;
7ee1af76 572 struct mid_q_entry *midQ;
792af7b0 573 char *buf = iov[0].iov_base;
50c2f753 574
133672ef
SF
575 long_op = flags & CIFS_TIMEOUT_MASK;
576
7ee1af76
JA
577 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
578
579 if ((ses == NULL) || (ses->server == NULL)) {
792af7b0 580 cifs_small_buf_release(buf);
b6b38f70 581 cERROR(1, "Null session");
7ee1af76
JA
582 return -EIO;
583 }
584
79a58d1f 585 if (ses->server->tcpStatus == CifsExiting) {
792af7b0 586 cifs_small_buf_release(buf);
7ee1af76
JA
587 return -ENOENT;
588 }
589
792af7b0
PS
590 /*
591 * Ensure that we do not send more than 50 overlapping requests
592 * to the same server. We may make this configurable later or
593 * use ses->maxReq.
594 */
7ee1af76 595
c5797a94 596 rc = wait_for_free_request(ses->server, long_op);
7ee1af76 597 if (rc) {
792af7b0 598 cifs_small_buf_release(buf);
7ee1af76
JA
599 return rc;
600 }
601
792af7b0
PS
602 /*
603 * Make sure that we sign in the same order that we send on this socket
604 * and avoid races inside tcp sendmsg code that could cause corruption
605 * of smb data.
606 */
7ee1af76 607
72ca545b 608 mutex_lock(&ses->server->srv_mutex);
7ee1af76 609
792af7b0 610 rc = cifs_setup_request(ses, iov, n_vec, &midQ);
7ee1af76 611 if (rc) {
72ca545b 612 mutex_unlock(&ses->server->srv_mutex);
792af7b0 613 cifs_small_buf_release(buf);
7ee1af76 614 /* Update # of requests on wire to server */
2d86dbc9 615 cifs_add_credits(ses->server, 1);
7ee1af76 616 return rc;
1da177e4 617 }
1da177e4
LT
618
619 midQ->midState = MID_REQUEST_SUBMITTED;
789e6661 620 cifs_in_send_inc(ses->server);
0496e02d 621 rc = smb_sendv(ses->server, iov, n_vec);
789e6661
SF
622 cifs_in_send_dec(ses->server);
623 cifs_save_when_sent(midQ);
7ee1af76 624
72ca545b 625 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 626
2db7c581 627 if (rc < 0) {
792af7b0 628 cifs_small_buf_release(buf);
7ee1af76 629 goto out;
2db7c581 630 }
4b8f930f 631
2db7c581 632 if (long_op == CIFS_ASYNC_OP) {
792af7b0 633 cifs_small_buf_release(buf);
133672ef 634 goto out;
2db7c581 635 }
d6e04ae6 636
0ade640e 637 rc = wait_for_response(ses->server, midQ);
1be912dd 638 if (rc != 0) {
792af7b0 639 send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ);
1be912dd
JL
640 spin_lock(&GlobalMid_Lock);
641 if (midQ->midState == MID_REQUEST_SUBMITTED) {
642 midQ->callback = DeleteMidQEntry;
643 spin_unlock(&GlobalMid_Lock);
792af7b0 644 cifs_small_buf_release(buf);
2d86dbc9 645 cifs_add_credits(ses->server, 1);
1be912dd
JL
646 return rc;
647 }
648 spin_unlock(&GlobalMid_Lock);
649 }
d6e04ae6 650
792af7b0 651 cifs_small_buf_release(buf);
2db7c581 652
3c1105df 653 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 654 if (rc != 0) {
2d86dbc9 655 cifs_add_credits(ses->server, 1);
d6e04ae6
SF
656 return rc;
657 }
50c2f753 658
2c8f981d 659 if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) {
d6e04ae6 660 rc = -EIO;
2c8f981d 661 cFYI(1, "Bad MID state?");
2b2bdfba
SF
662 goto out;
663 }
664
792af7b0
PS
665 buf = (char *)midQ->resp_buf;
666 iov[0].iov_base = buf;
667 iov[0].iov_len = get_rfc1002_length(buf) + 4;
2c8f981d
JL
668 if (midQ->largeBuf)
669 *pRespBufType = CIFS_LARGE_BUFFER;
670 else
671 *pRespBufType = CIFS_SMALL_BUFFER;
2b2bdfba 672
2c8f981d 673 rc = cifs_check_receive(midQ, ses->server, flags & CIFS_LOG_ERROR);
1da177e4 674
2c8f981d
JL
675 /* mark it so buf will not be freed by delete_mid */
676 if ((flags & CIFS_NO_RESP) == 0)
677 midQ->resp_buf = NULL;
7ee1af76 678out:
ddc8cf8f 679 delete_mid(midQ);
2d86dbc9 680 cifs_add_credits(ses->server, 1);
1da177e4 681
d6e04ae6
SF
682 return rc;
683}
1da177e4
LT
684
685int
96daf2b0 686SendReceive(const unsigned int xid, struct cifs_ses *ses,
1da177e4
LT
687 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
688 int *pbytes_returned, const int long_op)
689{
690 int rc = 0;
1da177e4
LT
691 struct mid_q_entry *midQ;
692
693 if (ses == NULL) {
b6b38f70 694 cERROR(1, "Null smb session");
1da177e4
LT
695 return -EIO;
696 }
79a58d1f 697 if (ses->server == NULL) {
b6b38f70 698 cERROR(1, "Null tcp session");
1da177e4
LT
699 return -EIO;
700 }
701
79a58d1f 702 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
703 return -ENOENT;
704
79a58d1f 705 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
706 to the same server. We may make this configurable later or
707 use ses->maxReq */
1da177e4 708
be8e3b00
SF
709 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
710 MAX_CIFS_HDR_SIZE - 4) {
b6b38f70 711 cERROR(1, "Illegal length, greater than maximum frame, %d",
be8e3b00 712 be32_to_cpu(in_buf->smb_buf_length));
6d9c6d54
VL
713 return -EIO;
714 }
715
c5797a94 716 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
717 if (rc)
718 return rc;
719
79a58d1f 720 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
721 and avoid races inside tcp sendmsg code that could cause corruption
722 of smb data */
723
72ca545b 724 mutex_lock(&ses->server->srv_mutex);
1da177e4 725
7ee1af76
JA
726 rc = allocate_mid(ses, in_buf, &midQ);
727 if (rc) {
72ca545b 728 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 729 /* Update # of requests on wire to server */
2d86dbc9 730 cifs_add_credits(ses->server, 1);
7ee1af76 731 return rc;
1da177e4
LT
732 }
733
ad009ac9 734 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb
VL
735 if (rc) {
736 mutex_unlock(&ses->server->srv_mutex);
737 goto out;
738 }
1da177e4
LT
739
740 midQ->midState = MID_REQUEST_SUBMITTED;
789e6661
SF
741
742 cifs_in_send_inc(ses->server);
be8e3b00 743 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
789e6661
SF
744 cifs_in_send_dec(ses->server);
745 cifs_save_when_sent(midQ);
72ca545b 746 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 747
79a58d1f 748 if (rc < 0)
7ee1af76
JA
749 goto out;
750
0ade640e 751 if (long_op == CIFS_ASYNC_OP)
7ee1af76 752 goto out;
1da177e4 753
0ade640e 754 rc = wait_for_response(ses->server, midQ);
1be912dd 755 if (rc != 0) {
2db7c581 756 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
757 spin_lock(&GlobalMid_Lock);
758 if (midQ->midState == MID_REQUEST_SUBMITTED) {
759 /* no longer considered to be "in-flight" */
760 midQ->callback = DeleteMidQEntry;
761 spin_unlock(&GlobalMid_Lock);
2d86dbc9 762 cifs_add_credits(ses->server, 1);
1be912dd
JL
763 return rc;
764 }
765 spin_unlock(&GlobalMid_Lock);
766 }
1da177e4 767
3c1105df 768 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 769 if (rc != 0) {
2d86dbc9 770 cifs_add_credits(ses->server, 1);
1da177e4
LT
771 return rc;
772 }
50c2f753 773
2c8f981d
JL
774 if (!midQ->resp_buf || !out_buf ||
775 midQ->midState != MID_RESPONSE_RECEIVED) {
2b2bdfba 776 rc = -EIO;
b6b38f70 777 cERROR(1, "Bad MID state?");
2c8f981d 778 goto out;
1da177e4 779 }
7ee1af76 780
2c8f981d
JL
781 *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
782 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
783 rc = cifs_check_receive(midQ, ses->server, 0);
7ee1af76 784out:
ddc8cf8f 785 delete_mid(midQ);
2d86dbc9 786 cifs_add_credits(ses->server, 1);
1da177e4 787
7ee1af76
JA
788 return rc;
789}
1da177e4 790
7ee1af76
JA
791/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
792 blocking lock to return. */
793
794static int
96daf2b0 795send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
796 struct smb_hdr *in_buf,
797 struct smb_hdr *out_buf)
798{
799 int bytes_returned;
96daf2b0 800 struct cifs_ses *ses = tcon->ses;
7ee1af76
JA
801 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
802
803 /* We just modify the current in_buf to change
804 the type of lock from LOCKING_ANDX_SHARED_LOCK
805 or LOCKING_ANDX_EXCLUSIVE_LOCK to
806 LOCKING_ANDX_CANCEL_LOCK. */
807
808 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
809 pSMB->Timeout = 0;
810 pSMB->hdr.Mid = GetNextMid(ses->server);
811
812 return SendReceive(xid, ses, in_buf, out_buf,
7749981e 813 &bytes_returned, 0);
7ee1af76
JA
814}
815
816int
96daf2b0 817SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
7ee1af76
JA
818 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
819 int *pbytes_returned)
820{
821 int rc = 0;
822 int rstart = 0;
7ee1af76 823 struct mid_q_entry *midQ;
96daf2b0 824 struct cifs_ses *ses;
7ee1af76
JA
825
826 if (tcon == NULL || tcon->ses == NULL) {
b6b38f70 827 cERROR(1, "Null smb session");
7ee1af76
JA
828 return -EIO;
829 }
830 ses = tcon->ses;
831
79a58d1f 832 if (ses->server == NULL) {
b6b38f70 833 cERROR(1, "Null tcp session");
7ee1af76
JA
834 return -EIO;
835 }
836
79a58d1f 837 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
838 return -ENOENT;
839
79a58d1f 840 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
841 to the same server. We may make this configurable later or
842 use ses->maxReq */
843
be8e3b00
SF
844 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
845 MAX_CIFS_HDR_SIZE - 4) {
b6b38f70 846 cERROR(1, "Illegal length, greater than maximum frame, %d",
be8e3b00 847 be32_to_cpu(in_buf->smb_buf_length));
6d9c6d54
VL
848 return -EIO;
849 }
850
c5797a94 851 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
7ee1af76
JA
852 if (rc)
853 return rc;
854
79a58d1f 855 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
856 and avoid races inside tcp sendmsg code that could cause corruption
857 of smb data */
858
72ca545b 859 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
860
861 rc = allocate_mid(ses, in_buf, &midQ);
862 if (rc) {
72ca545b 863 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
864 return rc;
865 }
866
7ee1af76 867 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb 868 if (rc) {
ddc8cf8f 869 delete_mid(midQ);
829049cb
VL
870 mutex_unlock(&ses->server->srv_mutex);
871 return rc;
872 }
1da177e4 873
7ee1af76 874 midQ->midState = MID_REQUEST_SUBMITTED;
789e6661 875 cifs_in_send_inc(ses->server);
be8e3b00 876 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
789e6661
SF
877 cifs_in_send_dec(ses->server);
878 cifs_save_when_sent(midQ);
72ca545b 879 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 880
79a58d1f 881 if (rc < 0) {
ddc8cf8f 882 delete_mid(midQ);
7ee1af76
JA
883 return rc;
884 }
885
886 /* Wait for a reply - allow signals to interrupt. */
887 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 888 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
889 ((ses->server->tcpStatus != CifsGood) &&
890 (ses->server->tcpStatus != CifsNew)));
891
892 /* Were we interrupted by a signal ? */
893 if ((rc == -ERESTARTSYS) &&
894 (midQ->midState == MID_REQUEST_SUBMITTED) &&
895 ((ses->server->tcpStatus == CifsGood) ||
896 (ses->server->tcpStatus == CifsNew))) {
897
898 if (in_buf->Command == SMB_COM_TRANSACTION2) {
899 /* POSIX lock. We send a NT_CANCEL SMB to cause the
900 blocking lock to return. */
76dcc26f 901 rc = send_nt_cancel(ses->server, in_buf, midQ);
7ee1af76 902 if (rc) {
ddc8cf8f 903 delete_mid(midQ);
7ee1af76
JA
904 return rc;
905 }
906 } else {
907 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
908 to cause the blocking lock to return. */
909
910 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
911
912 /* If we get -ENOLCK back the lock may have
913 already been removed. Don't exit in this case. */
914 if (rc && rc != -ENOLCK) {
ddc8cf8f 915 delete_mid(midQ);
7ee1af76
JA
916 return rc;
917 }
918 }
919
1be912dd
JL
920 rc = wait_for_response(ses->server, midQ);
921 if (rc) {
2db7c581 922 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
923 spin_lock(&GlobalMid_Lock);
924 if (midQ->midState == MID_REQUEST_SUBMITTED) {
925 /* no longer considered to be "in-flight" */
926 midQ->callback = DeleteMidQEntry;
927 spin_unlock(&GlobalMid_Lock);
928 return rc;
929 }
930 spin_unlock(&GlobalMid_Lock);
7ee1af76 931 }
1be912dd
JL
932
933 /* We got the response - restart system call. */
934 rstart = 1;
7ee1af76
JA
935 }
936
3c1105df 937 rc = cifs_sync_mid_result(midQ, ses->server);
053d5034 938 if (rc != 0)
7ee1af76 939 return rc;
50c2f753 940
17c8bfed 941 /* rcvd frame is ok */
2c8f981d 942 if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) {
698e96a8 943 rc = -EIO;
b6b38f70 944 cERROR(1, "Bad MID state?");
698e96a8
VL
945 goto out;
946 }
1da177e4 947
2c8f981d
JL
948 *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length);
949 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
950 rc = cifs_check_receive(midQ, ses->server, 0);
17c8bfed 951out:
ddc8cf8f 952 delete_mid(midQ);
7ee1af76
JA
953 if (rstart && rc == -EACCES)
954 return -ERESTARTSYS;
1da177e4
LT
955 return rc;
956}
This page took 0.454892 seconds and 5 git commands to generate.