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