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