Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux...
[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>
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) &&
ad7a2926 361 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 362 return -EAGAIN;
ad7a2926 363 /* else ok - we are setting up session */
1da177e4 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);
90c81e0b
SF
440 cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
441
133672ef
SF
442 return rc;
443}
444
7ee1af76 445int
79a58d1f
SF
446SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
447 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 448 const int flags)
7ee1af76
JA
449{
450 int rc = 0;
133672ef 451 int long_op;
7ee1af76
JA
452 unsigned int receive_len;
453 unsigned long timeout;
454 struct mid_q_entry *midQ;
455 struct smb_hdr *in_buf = iov[0].iov_base;
50c2f753 456
133672ef
SF
457 long_op = flags & CIFS_TIMEOUT_MASK;
458
7ee1af76
JA
459 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
460
461 if ((ses == NULL) || (ses->server == NULL)) {
462 cifs_small_buf_release(in_buf);
79a58d1f 463 cERROR(1, ("Null session"));
7ee1af76
JA
464 return -EIO;
465 }
466
79a58d1f 467 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76
JA
468 cifs_small_buf_release(in_buf);
469 return -ENOENT;
470 }
471
79a58d1f 472 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
473 to the same server. We may make this configurable later or
474 use ses->maxReq */
475
476 rc = wait_for_free_request(ses, long_op);
477 if (rc) {
478 cifs_small_buf_release(in_buf);
479 return rc;
480 }
481
79a58d1f 482 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
483 and avoid races inside tcp sendmsg code that could cause corruption
484 of smb data */
485
79a58d1f 486 down(&ses->server->tcpSem);
7ee1af76
JA
487
488 rc = allocate_mid(ses, in_buf, &midQ);
489 if (rc) {
1da177e4 490 up(&ses->server->tcpSem);
4b8f930f 491 cifs_small_buf_release(in_buf);
7ee1af76 492 /* Update # of requests on wire to server */
79a58d1f 493 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
494 wake_up(&ses->server->request_q);
495 return rc;
1da177e4 496 }
79a58d1f 497 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
1da177e4
LT
498
499 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
500#ifdef CONFIG_CIFS_STATS2
501 atomic_inc(&ses->server->inSend);
502#endif
3e84469d 503 rc = smb_send2(ses->server->ssocket, iov, n_vec,
d6e04ae6 504 (struct sockaddr *) &(ses->server->addr.sockAddr));
131afd0b
SF
505#ifdef CONFIG_CIFS_STATS2
506 atomic_dec(&ses->server->inSend);
1047abc1 507 midQ->when_sent = jiffies;
131afd0b 508#endif
7ee1af76
JA
509
510 up(&ses->server->tcpSem);
511 cifs_small_buf_release(in_buf);
512
79a58d1f 513 if (rc < 0)
7ee1af76 514 goto out;
4b8f930f 515
133672ef
SF
516 if (long_op == CIFS_STD_OP)
517 timeout = 15 * HZ;
518 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
37c0eb46 519 timeout = 180 * HZ;
133672ef 520 else if (long_op == CIFS_LONG_OP)
79a58d1f 521 timeout = 45 * HZ; /* should be greater than
d6e04ae6 522 servers oplock break timeout (about 43 seconds) */
133672ef
SF
523 else if (long_op == CIFS_ASYNC_OP)
524 goto out;
525 else if (long_op == CIFS_BLOCKING_OP)
526 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
527 else {
528 cERROR(1, ("unknown timeout flag %d", long_op));
529 rc = -EIO;
530 goto out;
531 }
7ee1af76 532
79a58d1f 533 /* wait for 15 seconds or until woken up due to response arriving or
d6e04ae6
SF
534 due to last connection to this server being unmounted */
535 if (signal_pending(current)) {
536 /* if signal pending do not hold up user for full smb timeout
8a236264 537 but we still give response a chance to complete */
d6e04ae6 538 timeout = 2 * HZ;
79a58d1f 539 }
d6e04ae6
SF
540
541 /* No user interrupts in wait - wreaks havoc with performance */
7ee1af76 542 wait_for_response(ses, midQ, timeout, 10 * HZ);
d6e04ae6
SF
543
544 spin_lock(&GlobalMid_Lock);
545 if (midQ->resp_buf) {
546 spin_unlock(&GlobalMid_Lock);
70ca734a 547 receive_len = midQ->resp_buf->smb_buf_length;
d6e04ae6 548 } else {
79a58d1f 549 cERROR(1, ("No response to cmd %d mid %d",
37c0eb46 550 midQ->command, midQ->mid));
79a58d1f
SF
551 if (midQ->midState == MID_REQUEST_SUBMITTED) {
552 if (ses->server->tcpStatus == CifsExiting)
d6e04ae6
SF
553 rc = -EHOSTDOWN;
554 else {
555 ses->server->tcpStatus = CifsNeedReconnect;
556 midQ->midState = MID_RETRY_NEEDED;
557 }
558 }
559
560 if (rc != -EHOSTDOWN) {
79a58d1f 561 if (midQ->midState == MID_RETRY_NEEDED) {
d6e04ae6 562 rc = -EAGAIN;
79a58d1f 563 cFYI(1, ("marking request for retry"));
d6e04ae6
SF
564 } else {
565 rc = -EIO;
566 }
567 }
568 spin_unlock(&GlobalMid_Lock);
569 DeleteMidQEntry(midQ);
7ee1af76 570 /* Update # of requests on wire to server */
79a58d1f 571 atomic_dec(&ses->server->inFlight);
7ee1af76 572 wake_up(&ses->server->request_q);
d6e04ae6
SF
573 return rc;
574 }
50c2f753 575
d6e04ae6
SF
576 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
577 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
578 receive_len, xid));
579 rc = -EIO;
580 } else { /* rcvd frame is ok */
79a58d1f 581 if (midQ->resp_buf &&
d6e04ae6 582 (midQ->midState == MID_RESPONSE_RECEIVED)) {
84afc29b 583
ec637e3f 584 iov[0].iov_base = (char *)midQ->resp_buf;
79a58d1f 585 if (midQ->largeBuf)
ec637e3f
SF
586 *pRespBufType = CIFS_LARGE_BUFFER;
587 else
588 *pRespBufType = CIFS_SMALL_BUFFER;
589 iov[0].iov_len = receive_len + 4;
d6e04ae6 590
ec637e3f 591 dump_smb(midQ->resp_buf, 80);
d6e04ae6 592 /* convert the length into a more usable form */
79a58d1f 593 if ((receive_len > 24) &&
d6e04ae6
SF
594 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
595 SECMODE_SIGN_ENABLED))) {
ec637e3f 596 rc = cifs_verify_signature(midQ->resp_buf,
b609f06a 597 &ses->server->mac_signing_key,
d6e04ae6 598 midQ->sequence_number+1);
79a58d1f
SF
599 if (rc) {
600 cERROR(1, ("Unexpected SMB signature"));
d6e04ae6
SF
601 /* BB FIXME add code to kill session */
602 }
603 }
604
d6e04ae6 605 /* BB special case reconnect tid and uid here? */
133672ef
SF
606 rc = map_smb_to_linux_error(midQ->resp_buf,
607 flags & CIFS_LOG_ERROR);
d6e04ae6
SF
608
609 /* convert ByteCount if necessary */
26f57364
SF
610 if (receive_len >= sizeof(struct smb_hdr) - 4
611 /* do not count RFC1001 header */ +
ec637e3f 612 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
79a58d1f 613 BCC(midQ->resp_buf) =
ec637e3f 614 le16_to_cpu(BCC_LE(midQ->resp_buf));
133672ef
SF
615 if ((flags & CIFS_NO_RESP) == 0)
616 midQ->resp_buf = NULL; /* mark it so buf will
617 not be freed by
618 DeleteMidQEntry */
d6e04ae6
SF
619 } else {
620 rc = -EIO;
79a58d1f 621 cFYI(1, ("Bad MID state?"));
d6e04ae6
SF
622 }
623 }
1da177e4 624
7ee1af76 625out:
7ee1af76 626 DeleteMidQEntry(midQ);
79a58d1f 627 atomic_dec(&ses->server->inFlight);
7ee1af76 628 wake_up(&ses->server->request_q);
1da177e4 629
d6e04ae6
SF
630 return rc;
631}
1da177e4
LT
632
633int
634SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
635 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
636 int *pbytes_returned, const int long_op)
637{
638 int rc = 0;
639 unsigned int receive_len;
640 unsigned long timeout;
641 struct mid_q_entry *midQ;
642
643 if (ses == NULL) {
79a58d1f 644 cERROR(1, ("Null smb session"));
1da177e4
LT
645 return -EIO;
646 }
79a58d1f
SF
647 if (ses->server == NULL) {
648 cERROR(1, ("Null tcp session"));
1da177e4
LT
649 return -EIO;
650 }
651
79a58d1f 652 if (ses->server->tcpStatus == CifsExiting)
31ca3bc3
SF
653 return -ENOENT;
654
79a58d1f 655 /* Ensure that we do not send more than 50 overlapping requests
1da177e4
LT
656 to the same server. We may make this configurable later or
657 use ses->maxReq */
1da177e4 658
7ee1af76
JA
659 rc = wait_for_free_request(ses, long_op);
660 if (rc)
661 return rc;
662
79a58d1f 663 /* make sure that we sign in the same order that we send on this socket
1da177e4
LT
664 and avoid races inside tcp sendmsg code that could cause corruption
665 of smb data */
666
79a58d1f 667 down(&ses->server->tcpSem);
1da177e4 668
7ee1af76
JA
669 rc = allocate_mid(ses, in_buf, &midQ);
670 if (rc) {
1da177e4 671 up(&ses->server->tcpSem);
7ee1af76 672 /* Update # of requests on wire to server */
79a58d1f 673 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
674 wake_up(&ses->server->request_q);
675 return rc;
1da177e4
LT
676 }
677
678 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
26a21b98 679 cERROR(1, ("Illegal length, greater than maximum frame, %d",
1da177e4
LT
680 in_buf->smb_buf_length));
681 DeleteMidQEntry(midQ);
7ee1af76
JA
682 up(&ses->server->tcpSem);
683 /* Update # of requests on wire to server */
79a58d1f 684 atomic_dec(&ses->server->inFlight);
7ee1af76 685 wake_up(&ses->server->request_q);
1da177e4
LT
686 return -EIO;
687 }
688
ad009ac9 689 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4
LT
690
691 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
692#ifdef CONFIG_CIFS_STATS2
693 atomic_inc(&ses->server->inSend);
694#endif
1da177e4
LT
695 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
696 (struct sockaddr *) &(ses->server->addr.sockAddr));
131afd0b
SF
697#ifdef CONFIG_CIFS_STATS2
698 atomic_dec(&ses->server->inSend);
1047abc1 699 midQ->when_sent = jiffies;
131afd0b 700#endif
7ee1af76
JA
701 up(&ses->server->tcpSem);
702
79a58d1f 703 if (rc < 0)
7ee1af76
JA
704 goto out;
705
133672ef
SF
706 if (long_op == CIFS_STD_OP)
707 timeout = 15 * HZ;
708 /* wait for 15 seconds or until woken up due to response arriving or
709 due to last connection to this server being unmounted */
710 else if (long_op == CIFS_ASYNC_OP)
7ee1af76 711 goto out;
133672ef 712 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
37c0eb46 713 timeout = 180 * HZ;
133672ef 714 else if (long_op == CIFS_LONG_OP)
79a58d1f 715 timeout = 45 * HZ; /* should be greater than
1da177e4 716 servers oplock break timeout (about 43 seconds) */
133672ef
SF
717 else if (long_op == CIFS_BLOCKING_OP)
718 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
719 else {
720 cERROR(1, ("unknown timeout flag %d", long_op));
721 rc = -EIO;
722 goto out;
723 }
724
1da177e4
LT
725 if (signal_pending(current)) {
726 /* if signal pending do not hold up user for full smb timeout
8a236264 727 but we still give response a chance to complete */
1da177e4 728 timeout = 2 * HZ;
79a58d1f 729 }
1da177e4
LT
730
731 /* No user interrupts in wait - wreaks havoc with performance */
7ee1af76 732 wait_for_response(ses, midQ, timeout, 10 * HZ);
1da177e4
LT
733
734 spin_lock(&GlobalMid_Lock);
735 if (midQ->resp_buf) {
736 spin_unlock(&GlobalMid_Lock);
70ca734a 737 receive_len = midQ->resp_buf->smb_buf_length;
1da177e4 738 } else {
79a58d1f 739 cERROR(1, ("No response for cmd %d mid %d",
37c0eb46 740 midQ->command, midQ->mid));
79a58d1f
SF
741 if (midQ->midState == MID_REQUEST_SUBMITTED) {
742 if (ses->server->tcpStatus == CifsExiting)
1da177e4
LT
743 rc = -EHOSTDOWN;
744 else {
745 ses->server->tcpStatus = CifsNeedReconnect;
746 midQ->midState = MID_RETRY_NEEDED;
747 }
748 }
749
750 if (rc != -EHOSTDOWN) {
79a58d1f 751 if (midQ->midState == MID_RETRY_NEEDED) {
1da177e4 752 rc = -EAGAIN;
79a58d1f 753 cFYI(1, ("marking request for retry"));
1da177e4
LT
754 } else {
755 rc = -EIO;
756 }
757 }
758 spin_unlock(&GlobalMid_Lock);
759 DeleteMidQEntry(midQ);
7ee1af76 760 /* Update # of requests on wire to server */
79a58d1f 761 atomic_dec(&ses->server->inFlight);
7ee1af76 762 wake_up(&ses->server->request_q);
1da177e4
LT
763 return rc;
764 }
50c2f753 765
1da177e4 766 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
ad009ac9 767 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1da177e4
LT
768 receive_len, xid));
769 rc = -EIO;
770 } else { /* rcvd frame is ok */
771
772 if (midQ->resp_buf && out_buf
773 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
774 out_buf->smb_buf_length = receive_len;
775 memcpy((char *)out_buf + 4,
776 (char *)midQ->resp_buf + 4,
777 receive_len);
778
779 dump_smb(out_buf, 92);
780 /* convert the length into a more usable form */
79a58d1f 781 if ((receive_len > 24) &&
ad009ac9
SF
782 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
783 SECMODE_SIGN_ENABLED))) {
784 rc = cifs_verify_signature(out_buf,
b609f06a 785 &ses->server->mac_signing_key,
ad009ac9 786 midQ->sequence_number+1);
79a58d1f
SF
787 if (rc) {
788 cERROR(1, ("Unexpected SMB signature"));
275cde1a 789 /* BB FIXME add code to kill session */
ad009ac9 790 }
1da177e4
LT
791 }
792
793 *pbytes_returned = out_buf->smb_buf_length;
794
ad009ac9 795 /* BB special case reconnect tid and uid here? */
a761ac57 796 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4
LT
797
798 /* convert ByteCount if necessary */
26f57364
SF
799 if (receive_len >= sizeof(struct smb_hdr) - 4
800 /* do not count RFC1001 header */ +
1da177e4 801 (2 * out_buf->WordCount) + 2 /* bcc */ )
0f2b27c4 802 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1da177e4
LT
803 } else {
804 rc = -EIO;
79a58d1f 805 cERROR(1, ("Bad MID state?"));
1da177e4
LT
806 }
807 }
7ee1af76
JA
808
809out:
1da177e4 810 DeleteMidQEntry(midQ);
79a58d1f 811 atomic_dec(&ses->server->inFlight);
7ee1af76 812 wake_up(&ses->server->request_q);
1da177e4 813
7ee1af76
JA
814 return rc;
815}
1da177e4 816
7ee1af76
JA
817/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
818
819static int
820send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
821 struct mid_q_entry *midQ)
822{
823 int rc = 0;
824 struct cifsSesInfo *ses = tcon->ses;
825 __u16 mid = in_buf->Mid;
826
827 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
828 in_buf->Mid = mid;
79a58d1f 829 down(&ses->server->tcpSem);
7ee1af76
JA
830 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
831 if (rc) {
832 up(&ses->server->tcpSem);
833 return rc;
834 }
835 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
836 (struct sockaddr *) &(ses->server->addr.sockAddr));
837 up(&ses->server->tcpSem);
1da177e4 838 return rc;
7ee1af76
JA
839}
840
841/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
842 blocking lock to return. */
843
844static int
845send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
846 struct smb_hdr *in_buf,
847 struct smb_hdr *out_buf)
848{
849 int bytes_returned;
850 struct cifsSesInfo *ses = tcon->ses;
851 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
852
853 /* We just modify the current in_buf to change
854 the type of lock from LOCKING_ANDX_SHARED_LOCK
855 or LOCKING_ANDX_EXCLUSIVE_LOCK to
856 LOCKING_ANDX_CANCEL_LOCK. */
857
858 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
859 pSMB->Timeout = 0;
860 pSMB->hdr.Mid = GetNextMid(ses->server);
861
862 return SendReceive(xid, ses, in_buf, out_buf,
133672ef 863 &bytes_returned, CIFS_STD_OP);
7ee1af76
JA
864}
865
866int
867SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
868 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
869 int *pbytes_returned)
870{
871 int rc = 0;
872 int rstart = 0;
873 unsigned int receive_len;
874 struct mid_q_entry *midQ;
875 struct cifsSesInfo *ses;
876
877 if (tcon == NULL || tcon->ses == NULL) {
79a58d1f 878 cERROR(1, ("Null smb session"));
7ee1af76
JA
879 return -EIO;
880 }
881 ses = tcon->ses;
882
79a58d1f
SF
883 if (ses->server == NULL) {
884 cERROR(1, ("Null tcp session"));
7ee1af76
JA
885 return -EIO;
886 }
887
79a58d1f 888 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
889 return -ENOENT;
890
79a58d1f 891 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
892 to the same server. We may make this configurable later or
893 use ses->maxReq */
894
133672ef 895 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
7ee1af76
JA
896 if (rc)
897 return rc;
898
79a58d1f 899 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
900 and avoid races inside tcp sendmsg code that could cause corruption
901 of smb data */
902
79a58d1f 903 down(&ses->server->tcpSem);
7ee1af76
JA
904
905 rc = allocate_mid(ses, in_buf, &midQ);
906 if (rc) {
907 up(&ses->server->tcpSem);
908 return rc;
909 }
910
911 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
912 up(&ses->server->tcpSem);
913 cERROR(1, ("Illegal length, greater than maximum frame, %d",
914 in_buf->smb_buf_length));
915 DeleteMidQEntry(midQ);
916 return -EIO;
917 }
918
919 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1da177e4 920
7ee1af76
JA
921 midQ->midState = MID_REQUEST_SUBMITTED;
922#ifdef CONFIG_CIFS_STATS2
923 atomic_inc(&ses->server->inSend);
924#endif
925 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
926 (struct sockaddr *) &(ses->server->addr.sockAddr));
927#ifdef CONFIG_CIFS_STATS2
928 atomic_dec(&ses->server->inSend);
929 midQ->when_sent = jiffies;
930#endif
1da177e4 931 up(&ses->server->tcpSem);
7ee1af76 932
79a58d1f 933 if (rc < 0) {
7ee1af76
JA
934 DeleteMidQEntry(midQ);
935 return rc;
936 }
937
938 /* Wait for a reply - allow signals to interrupt. */
939 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 940 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
941 ((ses->server->tcpStatus != CifsGood) &&
942 (ses->server->tcpStatus != CifsNew)));
943
944 /* Were we interrupted by a signal ? */
945 if ((rc == -ERESTARTSYS) &&
946 (midQ->midState == MID_REQUEST_SUBMITTED) &&
947 ((ses->server->tcpStatus == CifsGood) ||
948 (ses->server->tcpStatus == CifsNew))) {
949
950 if (in_buf->Command == SMB_COM_TRANSACTION2) {
951 /* POSIX lock. We send a NT_CANCEL SMB to cause the
952 blocking lock to return. */
953
954 rc = send_nt_cancel(tcon, in_buf, midQ);
955 if (rc) {
956 DeleteMidQEntry(midQ);
957 return rc;
958 }
959 } else {
960 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
961 to cause the blocking lock to return. */
962
963 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
964
965 /* If we get -ENOLCK back the lock may have
966 already been removed. Don't exit in this case. */
967 if (rc && rc != -ENOLCK) {
968 DeleteMidQEntry(midQ);
969 return rc;
970 }
971 }
972
973 /* Wait 5 seconds for the response. */
79a58d1f 974 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
7ee1af76
JA
975 /* We got the response - restart system call. */
976 rstart = 1;
977 }
978 }
979
980 spin_lock(&GlobalMid_Lock);
981 if (midQ->resp_buf) {
982 spin_unlock(&GlobalMid_Lock);
983 receive_len = midQ->resp_buf->smb_buf_length;
984 } else {
79a58d1f 985 cERROR(1, ("No response for cmd %d mid %d",
7ee1af76 986 midQ->command, midQ->mid));
79a58d1f
SF
987 if (midQ->midState == MID_REQUEST_SUBMITTED) {
988 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
989 rc = -EHOSTDOWN;
990 else {
991 ses->server->tcpStatus = CifsNeedReconnect;
992 midQ->midState = MID_RETRY_NEEDED;
993 }
994 }
995
996 if (rc != -EHOSTDOWN) {
79a58d1f 997 if (midQ->midState == MID_RETRY_NEEDED) {
7ee1af76 998 rc = -EAGAIN;
79a58d1f 999 cFYI(1, ("marking request for retry"));
7ee1af76
JA
1000 } else {
1001 rc = -EIO;
1002 }
1003 }
1004 spin_unlock(&GlobalMid_Lock);
1005 DeleteMidQEntry(midQ);
1006 return rc;
1da177e4 1007 }
50c2f753 1008
7ee1af76
JA
1009 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1010 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1011 receive_len, xid));
1012 rc = -EIO;
1013 } else { /* rcvd frame is ok */
1014
1015 if (midQ->resp_buf && out_buf
1016 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1017 out_buf->smb_buf_length = receive_len;
1018 memcpy((char *)out_buf + 4,
1019 (char *)midQ->resp_buf + 4,
1020 receive_len);
1021
1022 dump_smb(out_buf, 92);
1023 /* convert the length into a more usable form */
79a58d1f 1024 if ((receive_len > 24) &&
7ee1af76
JA
1025 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1026 SECMODE_SIGN_ENABLED))) {
1027 rc = cifs_verify_signature(out_buf,
b609f06a 1028 &ses->server->mac_signing_key,
7ee1af76 1029 midQ->sequence_number+1);
79a58d1f
SF
1030 if (rc) {
1031 cERROR(1, ("Unexpected SMB signature"));
7ee1af76
JA
1032 /* BB FIXME add code to kill session */
1033 }
1034 }
1035
1036 *pbytes_returned = out_buf->smb_buf_length;
1037
1038 /* BB special case reconnect tid and uid here? */
a761ac57 1039 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4 1040
7ee1af76 1041 /* convert ByteCount if necessary */
26f57364
SF
1042 if (receive_len >= sizeof(struct smb_hdr) - 4
1043 /* do not count RFC1001 header */ +
7ee1af76
JA
1044 (2 * out_buf->WordCount) + 2 /* bcc */ )
1045 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1046 } else {
1047 rc = -EIO;
79a58d1f 1048 cERROR(1, ("Bad MID state?"));
7ee1af76
JA
1049 }
1050 }
1051 DeleteMidQEntry(midQ);
1052 if (rstart && rc == -EACCES)
1053 return -ERESTARTSYS;
1da177e4
LT
1054 return rc;
1055}
This page took 0.317052 seconds and 5 git commands to generate.