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