]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/cifs/transport.c
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
[mirror_ubuntu-artful-kernel.git] / fs / cifs / transport.c
CommitLineData
1da177e4
LT
1/*
2 * fs/cifs/transport.c
3 *
79a58d1f 4 * Copyright (C) International Business Machines Corp., 2002,2007
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>
25#include <linux/wait.h>
26#include <linux/net.h>
27#include <linux/delay.h>
28#include <asm/uaccess.h>
29#include <asm/processor.h>
30#include <linux/mempool.h>
31#include "cifspdu.h"
32#include "cifsglob.h"
33#include "cifsproto.h"
34#include "cifs_debug.h"
50c2f753 35
1da177e4 36extern mempool_t *cifs_mid_poolp;
e18b890b 37extern struct kmem_cache *cifs_oplock_cachep;
1da177e4
LT
38
39static struct mid_q_entry *
7ee1af76 40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
1da177e4
LT
41{
42 struct mid_q_entry *temp;
43
44 if (ses == NULL) {
275cde1a 45 cERROR(1, ("Null session passed in to AllocMidQEntry"));
1da177e4
LT
46 return NULL;
47 }
48 if (ses->server == NULL) {
49 cERROR(1, ("Null TCP session in AllocMidQEntry"));
50 return NULL;
51 }
50c2f753 52
d6e04ae6 53 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
e94b1766 54 GFP_KERNEL | 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;
61 temp->command = smb_buffer->Command;
62 cFYI(1, ("For smb_command %d", temp->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;
1da177e4
LT
66 temp->ses = ses;
67 temp->tsk = current;
68 }
69
70 spin_lock(&GlobalMid_Lock);
71 list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
72 atomic_inc(&midCount);
73 temp->midState = MID_REQUEST_ALLOCATED;
74 spin_unlock(&GlobalMid_Lock);
75 return temp;
76}
77
78static void
79DeleteMidQEntry(struct mid_q_entry *midEntry)
80{
1047abc1
SF
81#ifdef CONFIG_CIFS_STATS2
82 unsigned long now;
83#endif
1da177e4
LT
84 spin_lock(&GlobalMid_Lock);
85 midEntry->midState = MID_FREE;
86 list_del(&midEntry->qhead);
87 atomic_dec(&midCount);
88 spin_unlock(&GlobalMid_Lock);
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
112struct oplock_q_entry *
79a58d1f 113AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
1da177e4
LT
114{
115 struct oplock_q_entry *temp;
79a58d1f 116 if ((pinode == NULL) || (tcon == NULL)) {
1da177e4
LT
117 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
118 return NULL;
119 }
120 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
e94b1766 121 GFP_KERNEL);
1da177e4
LT
122 if (temp == NULL)
123 return temp;
124 else {
125 temp->pinode = pinode;
126 temp->tcon = tcon;
127 temp->netfid = fid;
128 spin_lock(&GlobalMid_Lock);
129 list_add_tail(&temp->qhead, &GlobalOplock_Q);
130 spin_unlock(&GlobalMid_Lock);
131 }
132 return temp;
133
134}
135
79a58d1f 136void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
1da177e4 137{
79a58d1f 138 spin_lock(&GlobalMid_Lock);
1da177e4
LT
139 /* should we check if list empty first? */
140 list_del(&oplockEntry->qhead);
141 spin_unlock(&GlobalMid_Lock);
142 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
143}
144
145int
146smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
147 unsigned int smb_buf_length, struct sockaddr *sin)
148{
149 int rc = 0;
150 int i = 0;
151 struct msghdr smb_msg;
152 struct kvec iov;
153 unsigned len = smb_buf_length + 4;
154
79a58d1f 155 if (ssocket == NULL)
1da177e4
LT
156 return -ENOTSOCK; /* BB eventually add reconnect code here */
157 iov.iov_base = smb_buffer;
158 iov.iov_len = len;
159
160 smb_msg.msg_name = sin;
26f57364 161 smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4
LT
162 smb_msg.msg_control = NULL;
163 smb_msg.msg_controllen = 0;
164 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
165
166 /* smb header is converted in header_assemble. bcc and rest of SMB word
79a58d1f
SF
167 area, and byte area if necessary, is converted to littleendian in
168 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
1da177e4
LT
169 Flags2 is converted in SendReceive */
170
171 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
3e84469d 172 cFYI(1, ("Sending smb of length %d", smb_buf_length));
1da177e4
LT
173 dump_smb(smb_buffer, len);
174
175 while (len > 0) {
176 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
177 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
178 i++;
3e84469d 179 /* smaller timeout here than send2 since smaller size */
79a58d1f
SF
180 /* Although it may not be required, this also is smaller
181 oplock break time */
182 if (i > 12) {
1da177e4 183 cERROR(1,
68058e75 184 ("sends on sock %p stuck for 7 seconds",
1da177e4
LT
185 ssocket));
186 rc = -EAGAIN;
187 break;
188 }
68058e75 189 msleep(1 << i);
1da177e4
LT
190 continue;
191 }
79a58d1f 192 if (rc < 0)
1da177e4 193 break;
5e1253b5
SF
194 else
195 i = 0; /* reset i after each successful send */
1da177e4
LT
196 iov.iov_base += rc;
197 iov.iov_len -= rc;
198 len -= rc;
199 }
200
201 if (rc < 0) {
79a58d1f 202 cERROR(1, ("Error %d sending data on socket to server", rc));
1da177e4
LT
203 } else {
204 rc = 0;
205 }
206
7ee1af76
JA
207 /* Don't want to modify the buffer as a
208 side effect of this call. */
209 smb_buffer->smb_buf_length = smb_buf_length;
210
1da177e4
LT
211 return rc;
212}
213
d6e04ae6 214static int
3e84469d
SF
215smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
216 struct sockaddr *sin)
1da177e4
LT
217{
218 int rc = 0;
219 int i = 0;
220 struct msghdr smb_msg;
3e84469d
SF
221 struct smb_hdr *smb_buffer = iov[0].iov_base;
222 unsigned int len = iov[0].iov_len;
223 unsigned int total_len;
224 int first_vec = 0;
7ee1af76 225 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
50c2f753 226
79a58d1f 227 if (ssocket == NULL)
1da177e4 228 return -ENOTSOCK; /* BB eventually add reconnect code here */
3e84469d 229
1da177e4 230 smb_msg.msg_name = sin;
26f57364 231 smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4
LT
232 smb_msg.msg_control = NULL;
233 smb_msg.msg_controllen = 0;
234 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
235
236 /* smb header is converted in header_assemble. bcc and rest of SMB word
79a58d1f
SF
237 area, and byte area if necessary, is converted to littleendian in
238 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
1da177e4
LT
239 Flags2 is converted in SendReceive */
240
3e84469d
SF
241
242 total_len = 0;
243 for (i = 0; i < n_vec; i++)
244 total_len += iov[i].iov_len;
245
1da177e4 246 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
3e84469d 247 cFYI(1, ("Sending smb: total_len %d", total_len));
1da177e4
LT
248 dump_smb(smb_buffer, len);
249
3e84469d
SF
250 while (total_len) {
251 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
252 n_vec - first_vec, total_len);
1da177e4
LT
253 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
254 i++;
79a58d1f 255 if (i >= 14) {
1da177e4 256 cERROR(1,
68058e75 257 ("sends on sock %p stuck for 15 seconds",
1da177e4
LT
258 ssocket));
259 rc = -EAGAIN;
260 break;
261 }
68058e75 262 msleep(1 << i);
1da177e4
LT
263 continue;
264 }
79a58d1f 265 if (rc < 0)
1da177e4 266 break;
3e84469d
SF
267
268 if (rc >= total_len) {
269 WARN_ON(rc > total_len);
270 break;
271 }
79a58d1f 272 if (rc == 0) {
3e84469d
SF
273 /* should never happen, letting socket clear before
274 retrying is our only obvious option here */
79a58d1f 275 cERROR(1, ("tcp sent no data"));
3e84469d
SF
276 msleep(500);
277 continue;
d6e04ae6 278 }
3e84469d 279 total_len -= rc;
68058e75 280 /* the line below resets i */
3e84469d
SF
281 for (i = first_vec; i < n_vec; i++) {
282 if (iov[i].iov_len) {
283 if (rc > iov[i].iov_len) {
284 rc -= iov[i].iov_len;
285 iov[i].iov_len = 0;
286 } else {
287 iov[i].iov_base += rc;
288 iov[i].iov_len -= rc;
289 first_vec = i;
290 break;
291 }
292 }
d6e04ae6 293 }
5e1253b5 294 i = 0; /* in case we get ENOSPC on the next send */
1da177e4
LT
295 }
296
297 if (rc < 0) {
79a58d1f 298 cERROR(1, ("Error %d sending data on socket to server", rc));
3e84469d 299 } else
1da177e4 300 rc = 0;
1da177e4 301
7ee1af76
JA
302 /* Don't want to modify the buffer as a
303 side effect of this call. */
304 smb_buffer->smb_buf_length = smb_buf_length;
305
1da177e4
LT
306 return rc;
307}
308
7ee1af76 309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
1da177e4 310{
133672ef 311 if (long_op == CIFS_ASYNC_OP) {
1da177e4
LT
312 /* oplock breaks must not be held up */
313 atomic_inc(&ses->server->inFlight);
314 } else {
79a58d1f
SF
315 spin_lock(&GlobalMid_Lock);
316 while (1) {
317 if (atomic_read(&ses->server->inFlight) >=
d6e04ae6 318 cifs_max_pending){
1da177e4 319 spin_unlock(&GlobalMid_Lock);
131afd0b
SF
320#ifdef CONFIG_CIFS_STATS2
321 atomic_inc(&ses->server->num_waiters);
322#endif
1da177e4
LT
323 wait_event(ses->server->request_q,
324 atomic_read(&ses->server->inFlight)
325 < cifs_max_pending);
131afd0b
SF
326#ifdef CONFIG_CIFS_STATS2
327 atomic_dec(&ses->server->num_waiters);
328#endif
1da177e4
LT
329 spin_lock(&GlobalMid_Lock);
330 } else {
79a58d1f 331 if (ses->server->tcpStatus == CifsExiting) {
1da177e4
LT
332 spin_unlock(&GlobalMid_Lock);
333 return -ENOENT;
334 }
335
79a58d1f
SF
336 /* can not count locking commands against total
337 as they are allowed to block on server */
50c2f753 338
1da177e4 339 /* update # of requests on the wire to server */
133672ef 340 if (long_op != CIFS_BLOCKING_OP)
1da177e4 341 atomic_inc(&ses->server->inFlight);
1da177e4
LT
342 spin_unlock(&GlobalMid_Lock);
343 break;
344 }
345 }
346 }
7ee1af76
JA
347 return 0;
348}
1da177e4 349
7ee1af76
JA
350static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
351 struct mid_q_entry **ppmidQ)
352{
1da177e4 353 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 354 return -ENOENT;
1da177e4 355 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
79a58d1f 356 cFYI(1, ("tcp session dead - return to caller to retry"));
7ee1af76 357 return -EAGAIN;
1da177e4
LT
358 } else if (ses->status != CifsGood) {
359 /* check if SMB session is bad because we are setting it up */
79a58d1f 360 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
1da177e4 361 (in_buf->Command != SMB_COM_NEGOTIATE)) {
7ee1af76 362 return -EAGAIN;
1da177e4
LT
363 } /* else ok - we are setting up session */
364 }
7ee1af76 365 *ppmidQ = AllocMidQEntry(in_buf, ses);
26f57364 366 if (*ppmidQ == NULL)
7ee1af76 367 return -ENOMEM;
7ee1af76
JA
368 return 0;
369}
370
79a58d1f 371static int wait_for_response(struct cifsSesInfo *ses,
7ee1af76
JA
372 struct mid_q_entry *midQ,
373 unsigned long timeout,
374 unsigned long time_to_wait)
375{
376 unsigned long curr_timeout;
377
378 for (;;) {
379 curr_timeout = timeout + jiffies;
380 wait_event(ses->server->response_q,
79a58d1f
SF
381 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
382 time_after(jiffies, curr_timeout) ||
7ee1af76
JA
383 ((ses->server->tcpStatus != CifsGood) &&
384 (ses->server->tcpStatus != CifsNew)));
385
386 if (time_after(jiffies, curr_timeout) &&
387 (midQ->midState == MID_REQUEST_SUBMITTED) &&
388 ((ses->server->tcpStatus == CifsGood) ||
389 (ses->server->tcpStatus == CifsNew))) {
390
391 unsigned long lrt;
392
393 /* We timed out. Is the server still
394 sending replies ? */
395 spin_lock(&GlobalMid_Lock);
396 lrt = ses->server->lstrp;
397 spin_unlock(&GlobalMid_Lock);
398
399 /* Calculate time_to_wait past last receive time.
79a58d1f 400 Although we prefer not to time out if the
7ee1af76 401 server is still responding - we will time
79a58d1f 402 out if the server takes more than 15 (or 45
7ee1af76 403 or 180) seconds to respond to this request
79a58d1f 404 and has not responded to any request from
7ee1af76
JA
405 other threads on the client within 10 seconds */
406 lrt += time_to_wait;
407 if (time_after(jiffies, lrt)) {
408 /* No replies for time_to_wait. */
79a58d1f 409 cERROR(1, ("server not responding"));
7ee1af76
JA
410 return -1;
411 }
412 } else {
413 return 0;
414 }
415 }
416}
417
133672ef
SF
418
419/*
420 *
421 * Send an SMB Request. No response info (other than return code)
422 * needs to be parsed.
423 *
424 * flags indicate the type of request buffer and how long to wait
425 * and whether to log NT STATUS code (error) before mapping it to POSIX error
426 *
427 */
428int
429SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
430 struct smb_hdr *in_buf, int flags)
431{
432 int rc;
433 struct kvec iov[1];
434 int resp_buf_type;
435
436 iov[0].iov_base = (char *)in_buf;
437 iov[0].iov_len = in_buf->smb_buf_length + 4;
438 flags |= CIFS_NO_RESP;
439 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
440#ifdef CONFIG_CIFS_DEBUG2
441 cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc));
442#endif
443 return rc;
444}
445
7ee1af76 446int
79a58d1f
SF
447SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
448 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 449 const int flags)
7ee1af76
JA
450{
451 int rc = 0;
133672ef 452 int long_op;
7ee1af76
JA
453 unsigned int receive_len;
454 unsigned long timeout;
455 struct mid_q_entry *midQ;
456 struct smb_hdr *in_buf = iov[0].iov_base;
50c2f753 457
133672ef
SF
458 long_op = flags & CIFS_TIMEOUT_MASK;
459
7ee1af76
JA
460 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
461
462 if ((ses == NULL) || (ses->server == NULL)) {
463 cifs_small_buf_release(in_buf);
79a58d1f 464 cERROR(1, ("Null session"));
7ee1af76
JA
465 return -EIO;
466 }
467
79a58d1f 468 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76
JA
469 cifs_small_buf_release(in_buf);
470 return -ENOENT;
471 }
472
79a58d1f 473 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
474 to the same server. We may make this configurable later or
475 use ses->maxReq */
476
477 rc = wait_for_free_request(ses, long_op);
478 if (rc) {
479 cifs_small_buf_release(in_buf);
480 return rc;
481 }
482
79a58d1f 483 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
484 and avoid races inside tcp sendmsg code that could cause corruption
485 of smb data */
486
79a58d1f 487 down(&ses->server->tcpSem);
7ee1af76
JA
488
489 rc = allocate_mid(ses, in_buf, &midQ);
490 if (rc) {
1da177e4 491 up(&ses->server->tcpSem);
4b8f930f 492 cifs_small_buf_release(in_buf);
7ee1af76 493 /* Update # of requests on wire to server */
79a58d1f 494 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
495 wake_up(&ses->server->request_q);
496 return rc;
1da177e4 497 }
79a58d1f 498 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
1da177e4
LT
499
500 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
501#ifdef CONFIG_CIFS_STATS2
502 atomic_inc(&ses->server->inSend);
503#endif
3e84469d 504 rc = smb_send2(ses->server->ssocket, iov, n_vec,
d6e04ae6 505 (struct sockaddr *) &(ses->server->addr.sockAddr));
131afd0b
SF
506#ifdef CONFIG_CIFS_STATS2
507 atomic_dec(&ses->server->inSend);
1047abc1 508 midQ->when_sent = jiffies;
131afd0b 509#endif
7ee1af76
JA
510
511 up(&ses->server->tcpSem);
512 cifs_small_buf_release(in_buf);
513
79a58d1f 514 if (rc < 0)
7ee1af76 515 goto out;
4b8f930f 516
133672ef
SF
517 if (long_op == CIFS_STD_OP)
518 timeout = 15 * HZ;
519 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
37c0eb46 520 timeout = 180 * HZ;
133672ef 521 else if (long_op == CIFS_LONG_OP)
79a58d1f 522 timeout = 45 * HZ; /* should be greater than
d6e04ae6 523 servers oplock break timeout (about 43 seconds) */
133672ef
SF
524 else if (long_op == CIFS_ASYNC_OP)
525 goto out;
526 else if (long_op == CIFS_BLOCKING_OP)
527 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
528 else {
529 cERROR(1, ("unknown timeout flag %d", long_op));
530 rc = -EIO;
531 goto out;
532 }
7ee1af76 533
79a58d1f 534 /* wait for 15 seconds or until woken up due to response arriving or
d6e04ae6
SF
535 due to last connection to this server being unmounted */
536 if (signal_pending(current)) {
537 /* if signal pending do not hold up user for full smb timeout
8a236264 538 but we still give response a chance to complete */
d6e04ae6 539 timeout = 2 * HZ;
79a58d1f 540 }
d6e04ae6
SF
541
542 /* No user interrupts in wait - wreaks havoc with performance */
7ee1af76 543 wait_for_response(ses, midQ, timeout, 10 * HZ);
d6e04ae6
SF
544
545 spin_lock(&GlobalMid_Lock);
546 if (midQ->resp_buf) {
547 spin_unlock(&GlobalMid_Lock);
70ca734a 548 receive_len = midQ->resp_buf->smb_buf_length;
d6e04ae6 549 } else {
79a58d1f 550 cERROR(1, ("No response to cmd %d mid %d",
37c0eb46 551 midQ->command, midQ->mid));
79a58d1f
SF
552 if (midQ->midState == MID_REQUEST_SUBMITTED) {
553 if (ses->server->tcpStatus == CifsExiting)
d6e04ae6
SF
554 rc = -EHOSTDOWN;
555 else {
556 ses->server->tcpStatus = CifsNeedReconnect;
557 midQ->midState = MID_RETRY_NEEDED;
558 }
559 }
560
561 if (rc != -EHOSTDOWN) {
79a58d1f 562 if (midQ->midState == MID_RETRY_NEEDED) {
d6e04ae6 563 rc = -EAGAIN;
79a58d1f 564 cFYI(1, ("marking request for retry"));
d6e04ae6
SF
565 } else {
566 rc = -EIO;
567 }
568 }
569 spin_unlock(&GlobalMid_Lock);
570 DeleteMidQEntry(midQ);
7ee1af76 571 /* Update # of requests on wire to server */
79a58d1f 572 atomic_dec(&ses->server->inFlight);
7ee1af76 573 wake_up(&ses->server->request_q);
d6e04ae6
SF
574 return rc;
575 }
50c2f753 576
d6e04ae6
SF
577 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
578 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
579 receive_len, xid));
580 rc = -EIO;
581 } else { /* rcvd frame is ok */
79a58d1f 582 if (midQ->resp_buf &&
d6e04ae6 583 (midQ->midState == MID_RESPONSE_RECEIVED)) {
84afc29b 584
ec637e3f 585 iov[0].iov_base = (char *)midQ->resp_buf;
79a58d1f 586 if (midQ->largeBuf)
ec637e3f
SF
587 *pRespBufType = CIFS_LARGE_BUFFER;
588 else
589 *pRespBufType = CIFS_SMALL_BUFFER;
590 iov[0].iov_len = receive_len + 4;
d6e04ae6 591
ec637e3f 592 dump_smb(midQ->resp_buf, 80);
d6e04ae6 593 /* convert the length into a more usable form */
79a58d1f 594 if ((receive_len > 24) &&
d6e04ae6
SF
595 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
596 SECMODE_SIGN_ENABLED))) {
ec637e3f 597 rc = cifs_verify_signature(midQ->resp_buf,
b609f06a 598 &ses->server->mac_signing_key,
d6e04ae6 599 midQ->sequence_number+1);
79a58d1f
SF
600 if (rc) {
601 cERROR(1, ("Unexpected SMB signature"));
d6e04ae6
SF
602 /* BB FIXME add code to kill session */
603 }
604 }
605
d6e04ae6 606 /* BB special case reconnect tid and uid here? */
133672ef
SF
607 rc = map_smb_to_linux_error(midQ->resp_buf,
608 flags & CIFS_LOG_ERROR);
d6e04ae6
SF
609
610 /* convert ByteCount if necessary */
26f57364
SF
611 if (receive_len >= sizeof(struct smb_hdr) - 4
612 /* do not count RFC1001 header */ +
ec637e3f 613 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
79a58d1f 614 BCC(midQ->resp_buf) =
ec637e3f 615 le16_to_cpu(BCC_LE(midQ->resp_buf));
133672ef
SF
616 if ((flags & CIFS_NO_RESP) == 0)
617 midQ->resp_buf = NULL; /* mark it so buf will
618 not be freed by
619 DeleteMidQEntry */
d6e04ae6
SF
620 } else {
621 rc = -EIO;
79a58d1f 622 cFYI(1, ("Bad MID state?"));
d6e04ae6
SF
623 }
624 }
1da177e4 625
7ee1af76 626out:
7ee1af76 627 DeleteMidQEntry(midQ);
79a58d1f 628 atomic_dec(&ses->server->inFlight);
7ee1af76 629 wake_up(&ses->server->request_q);
1da177e4 630
d6e04ae6
SF
631 return rc;
632}
1da177e4
LT
633
634int
635SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
636 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
637 int *pbytes_returned, const int long_op)
638{
639 int rc = 0;
640 unsigned int receive_len;
641 unsigned long timeout;
642 struct mid_q_entry *midQ;
643
644 if (ses == NULL) {
79a58d1f 645 cERROR(1, ("Null smb session"));
1da177e4
LT
646 return -EIO;
647 }
79a58d1f
SF
648 if (ses->server == NULL) {
649 cERROR(1, ("Null tcp session"));
1da177e4
LT
650 return -EIO;
651 }
652
79a58d1f 653 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
654 return -ENOENT;
655
79a58d1f 656 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
657 to the same server. We may make this configurable later or
658 use ses->maxReq */
1da177e4 659
7ee1af76
JA
660 rc = wait_for_free_request(ses, long_op);
661 if (rc)
662 return rc;
663
79a58d1f 664 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
665 and avoid races inside tcp sendmsg code that could cause corruption
666 of smb data */
667
79a58d1f 668 down(&ses->server->tcpSem);
1da177e4 669
7ee1af76
JA
670 rc = allocate_mid(ses, in_buf, &midQ);
671 if (rc) {
1da177e4 672 up(&ses->server->tcpSem);
7ee1af76 673 /* Update # of requests on wire to server */
79a58d1f 674 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
675 wake_up(&ses->server->request_q);
676 return rc;
1da177e4
LT
677 }
678
679 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
26a21b98 680 cERROR(1, ("Illegal length, greater than maximum frame, %d",
1da177e4
LT
681 in_buf->smb_buf_length));
682 DeleteMidQEntry(midQ);
7ee1af76
JA
683 up(&ses->server->tcpSem);
684 /* Update # of requests on wire to server */
79a58d1f 685 atomic_dec(&ses->server->inFlight);
7ee1af76 686 wake_up(&ses->server->request_q);
1da177e4
LT
687 return -EIO;
688 }
689
ad009ac9 690 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4
LT
691
692 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
693#ifdef CONFIG_CIFS_STATS2
694 atomic_inc(&ses->server->inSend);
695#endif
1da177e4
LT
696 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
697 (struct sockaddr *) &(ses->server->addr.sockAddr));
131afd0b
SF
698#ifdef CONFIG_CIFS_STATS2
699 atomic_dec(&ses->server->inSend);
1047abc1 700 midQ->when_sent = jiffies;
131afd0b 701#endif
7ee1af76
JA
702 up(&ses->server->tcpSem);
703
79a58d1f 704 if (rc < 0)
7ee1af76
JA
705 goto out;
706
133672ef
SF
707 if (long_op == CIFS_STD_OP)
708 timeout = 15 * HZ;
709 /* wait for 15 seconds or until woken up due to response arriving or
710 due to last connection to this server being unmounted */
711 else if (long_op == CIFS_ASYNC_OP)
7ee1af76 712 goto out;
133672ef 713 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
37c0eb46 714 timeout = 180 * HZ;
133672ef 715 else if (long_op == CIFS_LONG_OP)
79a58d1f 716 timeout = 45 * HZ; /* should be greater than
1da177e4 717 servers oplock break timeout (about 43 seconds) */
133672ef
SF
718 else if (long_op == CIFS_BLOCKING_OP)
719 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
720 else {
721 cERROR(1, ("unknown timeout flag %d", long_op));
722 rc = -EIO;
723 goto out;
724 }
725
1da177e4
LT
726 if (signal_pending(current)) {
727 /* if signal pending do not hold up user for full smb timeout
8a236264 728 but we still give response a chance to complete */
1da177e4 729 timeout = 2 * HZ;
79a58d1f 730 }
1da177e4
LT
731
732 /* No user interrupts in wait - wreaks havoc with performance */
7ee1af76 733 wait_for_response(ses, midQ, timeout, 10 * HZ);
1da177e4
LT
734
735 spin_lock(&GlobalMid_Lock);
736 if (midQ->resp_buf) {
737 spin_unlock(&GlobalMid_Lock);
70ca734a 738 receive_len = midQ->resp_buf->smb_buf_length;
1da177e4 739 } else {
79a58d1f 740 cERROR(1, ("No response for cmd %d mid %d",
37c0eb46 741 midQ->command, midQ->mid));
79a58d1f
SF
742 if (midQ->midState == MID_REQUEST_SUBMITTED) {
743 if (ses->server->tcpStatus == CifsExiting)
1da177e4
LT
744 rc = -EHOSTDOWN;
745 else {
746 ses->server->tcpStatus = CifsNeedReconnect;
747 midQ->midState = MID_RETRY_NEEDED;
748 }
749 }
750
751 if (rc != -EHOSTDOWN) {
79a58d1f 752 if (midQ->midState == MID_RETRY_NEEDED) {
1da177e4 753 rc = -EAGAIN;
79a58d1f 754 cFYI(1, ("marking request for retry"));
1da177e4
LT
755 } else {
756 rc = -EIO;
757 }
758 }
759 spin_unlock(&GlobalMid_Lock);
760 DeleteMidQEntry(midQ);
7ee1af76 761 /* Update # of requests on wire to server */
79a58d1f 762 atomic_dec(&ses->server->inFlight);
7ee1af76 763 wake_up(&ses->server->request_q);
1da177e4
LT
764 return rc;
765 }
50c2f753 766
1da177e4 767 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
ad009ac9 768 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1da177e4
LT
769 receive_len, xid));
770 rc = -EIO;
771 } else { /* rcvd frame is ok */
772
773 if (midQ->resp_buf && out_buf
774 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
775 out_buf->smb_buf_length = receive_len;
776 memcpy((char *)out_buf + 4,
777 (char *)midQ->resp_buf + 4,
778 receive_len);
779
780 dump_smb(out_buf, 92);
781 /* convert the length into a more usable form */
79a58d1f 782 if ((receive_len > 24) &&
ad009ac9
SF
783 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
784 SECMODE_SIGN_ENABLED))) {
785 rc = cifs_verify_signature(out_buf,
b609f06a 786 &ses->server->mac_signing_key,
ad009ac9 787 midQ->sequence_number+1);
79a58d1f
SF
788 if (rc) {
789 cERROR(1, ("Unexpected SMB signature"));
275cde1a 790 /* BB FIXME add code to kill session */
ad009ac9 791 }
1da177e4
LT
792 }
793
794 *pbytes_returned = out_buf->smb_buf_length;
795
ad009ac9 796 /* BB special case reconnect tid and uid here? */
a761ac57 797 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4
LT
798
799 /* convert ByteCount if necessary */
26f57364
SF
800 if (receive_len >= sizeof(struct smb_hdr) - 4
801 /* do not count RFC1001 header */ +
1da177e4 802 (2 * out_buf->WordCount) + 2 /* bcc */ )
0f2b27c4 803 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1da177e4
LT
804 } else {
805 rc = -EIO;
79a58d1f 806 cERROR(1, ("Bad MID state?"));
1da177e4
LT
807 }
808 }
7ee1af76
JA
809
810out:
1da177e4 811 DeleteMidQEntry(midQ);
79a58d1f 812 atomic_dec(&ses->server->inFlight);
7ee1af76 813 wake_up(&ses->server->request_q);
1da177e4 814
7ee1af76
JA
815 return rc;
816}
1da177e4 817
7ee1af76
JA
818/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
819
820static int
821send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
822 struct mid_q_entry *midQ)
823{
824 int rc = 0;
825 struct cifsSesInfo *ses = tcon->ses;
826 __u16 mid = in_buf->Mid;
827
828 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
829 in_buf->Mid = mid;
79a58d1f 830 down(&ses->server->tcpSem);
7ee1af76
JA
831 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
832 if (rc) {
833 up(&ses->server->tcpSem);
834 return rc;
835 }
836 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
837 (struct sockaddr *) &(ses->server->addr.sockAddr));
838 up(&ses->server->tcpSem);
1da177e4 839 return rc;
7ee1af76
JA
840}
841
842/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
843 blocking lock to return. */
844
845static int
846send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
847 struct smb_hdr *in_buf,
848 struct smb_hdr *out_buf)
849{
850 int bytes_returned;
851 struct cifsSesInfo *ses = tcon->ses;
852 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
853
854 /* We just modify the current in_buf to change
855 the type of lock from LOCKING_ANDX_SHARED_LOCK
856 or LOCKING_ANDX_EXCLUSIVE_LOCK to
857 LOCKING_ANDX_CANCEL_LOCK. */
858
859 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
860 pSMB->Timeout = 0;
861 pSMB->hdr.Mid = GetNextMid(ses->server);
862
863 return SendReceive(xid, ses, in_buf, out_buf,
133672ef 864 &bytes_returned, CIFS_STD_OP);
7ee1af76
JA
865}
866
867int
868SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
869 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
870 int *pbytes_returned)
871{
872 int rc = 0;
873 int rstart = 0;
874 unsigned int receive_len;
875 struct mid_q_entry *midQ;
876 struct cifsSesInfo *ses;
877
878 if (tcon == NULL || tcon->ses == NULL) {
79a58d1f 879 cERROR(1, ("Null smb session"));
7ee1af76
JA
880 return -EIO;
881 }
882 ses = tcon->ses;
883
79a58d1f
SF
884 if (ses->server == NULL) {
885 cERROR(1, ("Null tcp session"));
7ee1af76
JA
886 return -EIO;
887 }
888
79a58d1f 889 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
890 return -ENOENT;
891
79a58d1f 892 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
893 to the same server. We may make this configurable later or
894 use ses->maxReq */
895
133672ef 896 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
7ee1af76
JA
897 if (rc)
898 return rc;
899
79a58d1f 900 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
901 and avoid races inside tcp sendmsg code that could cause corruption
902 of smb data */
903
79a58d1f 904 down(&ses->server->tcpSem);
7ee1af76
JA
905
906 rc = allocate_mid(ses, in_buf, &midQ);
907 if (rc) {
908 up(&ses->server->tcpSem);
909 return rc;
910 }
911
912 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
913 up(&ses->server->tcpSem);
914 cERROR(1, ("Illegal length, greater than maximum frame, %d",
915 in_buf->smb_buf_length));
916 DeleteMidQEntry(midQ);
917 return -EIO;
918 }
919
920 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4 921
7ee1af76
JA
922 midQ->midState = MID_REQUEST_SUBMITTED;
923#ifdef CONFIG_CIFS_STATS2
924 atomic_inc(&ses->server->inSend);
925#endif
926 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
927 (struct sockaddr *) &(ses->server->addr.sockAddr));
928#ifdef CONFIG_CIFS_STATS2
929 atomic_dec(&ses->server->inSend);
930 midQ->when_sent = jiffies;
931#endif
1da177e4 932 up(&ses->server->tcpSem);
7ee1af76 933
79a58d1f 934 if (rc < 0) {
7ee1af76
JA
935 DeleteMidQEntry(midQ);
936 return rc;
937 }
938
939 /* Wait for a reply - allow signals to interrupt. */
940 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 941 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
942 ((ses->server->tcpStatus != CifsGood) &&
943 (ses->server->tcpStatus != CifsNew)));
944
945 /* Were we interrupted by a signal ? */
946 if ((rc == -ERESTARTSYS) &&
947 (midQ->midState == MID_REQUEST_SUBMITTED) &&
948 ((ses->server->tcpStatus == CifsGood) ||
949 (ses->server->tcpStatus == CifsNew))) {
950
951 if (in_buf->Command == SMB_COM_TRANSACTION2) {
952 /* POSIX lock. We send a NT_CANCEL SMB to cause the
953 blocking lock to return. */
954
955 rc = send_nt_cancel(tcon, in_buf, midQ);
956 if (rc) {
957 DeleteMidQEntry(midQ);
958 return rc;
959 }
960 } else {
961 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
962 to cause the blocking lock to return. */
963
964 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
965
966 /* If we get -ENOLCK back the lock may have
967 already been removed. Don't exit in this case. */
968 if (rc && rc != -ENOLCK) {
969 DeleteMidQEntry(midQ);
970 return rc;
971 }
972 }
973
974 /* Wait 5 seconds for the response. */
79a58d1f 975 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
7ee1af76
JA
976 /* We got the response - restart system call. */
977 rstart = 1;
978 }
979 }
980
981 spin_lock(&GlobalMid_Lock);
982 if (midQ->resp_buf) {
983 spin_unlock(&GlobalMid_Lock);
984 receive_len = midQ->resp_buf->smb_buf_length;
985 } else {
79a58d1f 986 cERROR(1, ("No response for cmd %d mid %d",
7ee1af76 987 midQ->command, midQ->mid));
79a58d1f
SF
988 if (midQ->midState == MID_REQUEST_SUBMITTED) {
989 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
990 rc = -EHOSTDOWN;
991 else {
992 ses->server->tcpStatus = CifsNeedReconnect;
993 midQ->midState = MID_RETRY_NEEDED;
994 }
995 }
996
997 if (rc != -EHOSTDOWN) {
79a58d1f 998 if (midQ->midState == MID_RETRY_NEEDED) {
7ee1af76 999 rc = -EAGAIN;
79a58d1f 1000 cFYI(1, ("marking request for retry"));
7ee1af76
JA
1001 } else {
1002 rc = -EIO;
1003 }
1004 }
1005 spin_unlock(&GlobalMid_Lock);
1006 DeleteMidQEntry(midQ);
1007 return rc;
1da177e4 1008 }
50c2f753 1009
7ee1af76
JA
1010 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1011 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1012 receive_len, xid));
1013 rc = -EIO;
1014 } else { /* rcvd frame is ok */
1015
1016 if (midQ->resp_buf && out_buf
1017 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1018 out_buf->smb_buf_length = receive_len;
1019 memcpy((char *)out_buf + 4,
1020 (char *)midQ->resp_buf + 4,
1021 receive_len);
1022
1023 dump_smb(out_buf, 92);
1024 /* convert the length into a more usable form */
79a58d1f 1025 if ((receive_len > 24) &&
7ee1af76
JA
1026 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1027 SECMODE_SIGN_ENABLED))) {
1028 rc = cifs_verify_signature(out_buf,
b609f06a 1029 &ses->server->mac_signing_key,
7ee1af76 1030 midQ->sequence_number+1);
79a58d1f
SF
1031 if (rc) {
1032 cERROR(1, ("Unexpected SMB signature"));
7ee1af76
JA
1033 /* BB FIXME add code to kill session */
1034 }
1035 }
1036
1037 *pbytes_returned = out_buf->smb_buf_length;
1038
1039 /* BB special case reconnect tid and uid here? */
a761ac57 1040 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4 1041
7ee1af76 1042 /* convert ByteCount if necessary */
26f57364
SF
1043 if (receive_len >= sizeof(struct smb_hdr) - 4
1044 /* do not count RFC1001 header */ +
7ee1af76
JA
1045 (2 * out_buf->WordCount) + 2 /* bcc */ )
1046 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1047 } else {
1048 rc = -EIO;
79a58d1f 1049 cERROR(1, ("Bad MID state?"));
7ee1af76
JA
1050 }
1051 }
1052 DeleteMidQEntry(midQ);
1053 if (rstart && rc == -EACCES)
1054 return -ERESTARTSYS;
1da177e4
LT
1055 return rc;
1056}