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