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