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