cifs: Invoke id mapping functions (try #17 repost)
[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>
5a0e3ad6 25#include <linux/gfp.h>
1da177e4
LT
26#include <linux/wait.h>
27#include <linux/net.h>
28#include <linux/delay.h>
29#include <asm/uaccess.h>
30#include <asm/processor.h>
31#include <linux/mempool.h>
32#include "cifspdu.h"
33#include "cifsglob.h"
34#include "cifsproto.h"
35#include "cifs_debug.h"
50c2f753 36
1da177e4 37extern mempool_t *cifs_mid_poolp;
1da177e4 38
2b84a36c
JL
39static void
40wake_up_task(struct mid_q_entry *mid)
41{
42 wake_up_process(mid->callback_data);
43}
44
a6827c18 45struct mid_q_entry *
24b9b06b 46AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
1da177e4
LT
47{
48 struct mid_q_entry *temp;
49
24b9b06b 50 if (server == NULL) {
b6b38f70 51 cERROR(1, "Null TCP session in AllocMidQEntry");
1da177e4
LT
52 return NULL;
53 }
50c2f753 54
232087cb 55 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
1da177e4
LT
56 if (temp == NULL)
57 return temp;
58 else {
26f57364 59 memset(temp, 0, sizeof(struct mid_q_entry));
1da177e4
LT
60 temp->mid = smb_buffer->Mid; /* always LE */
61 temp->pid = current->pid;
62 temp->command = smb_buffer->Command;
b6b38f70 63 cFYI(1, "For smb_command %d", temp->command);
1047abc1
SF
64 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
65 /* when mid allocated can be before when sent */
66 temp->when_alloc = jiffies;
2b84a36c
JL
67
68 /*
69 * The default is for the mid to be synchronous, so the
70 * default callback just wakes up the current task.
71 */
72 temp->callback = wake_up_task;
73 temp->callback_data = current;
1da177e4
LT
74 }
75
1da177e4
LT
76 atomic_inc(&midCount);
77 temp->midState = MID_REQUEST_ALLOCATED;
1da177e4
LT
78 return temp;
79}
80
766fdbb5 81void
1da177e4
LT
82DeleteMidQEntry(struct mid_q_entry *midEntry)
83{
1047abc1
SF
84#ifdef CONFIG_CIFS_STATS2
85 unsigned long now;
86#endif
1da177e4 87 midEntry->midState = MID_FREE;
8097531a 88 atomic_dec(&midCount);
79a58d1f 89 if (midEntry->largeBuf)
b8643e1b
SF
90 cifs_buf_release(midEntry->resp_buf);
91 else
92 cifs_small_buf_release(midEntry->resp_buf);
1047abc1
SF
93#ifdef CONFIG_CIFS_STATS2
94 now = jiffies;
95 /* commands taking longer than one second are indications that
96 something is wrong, unless it is quite a slow link or server */
79a58d1f
SF
97 if ((now - midEntry->when_alloc) > HZ) {
98 if ((cifsFYI & CIFS_TIMER) &&
1047abc1
SF
99 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
100 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
101 midEntry->command, midEntry->mid);
102 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
103 now - midEntry->when_alloc,
104 now - midEntry->when_sent,
105 now - midEntry->when_received);
106 }
107 }
108#endif
1da177e4
LT
109 mempool_free(midEntry, cifs_mid_poolp);
110}
111
ddc8cf8f
JL
112static void
113delete_mid(struct mid_q_entry *mid)
114{
115 spin_lock(&GlobalMid_Lock);
116 list_del(&mid->qhead);
117 spin_unlock(&GlobalMid_Lock);
118
119 DeleteMidQEntry(mid);
120}
121
d6e04ae6 122static int
0496e02d 123smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
1da177e4
LT
124{
125 int rc = 0;
126 int i = 0;
127 struct msghdr smb_msg;
3e84469d
SF
128 struct smb_hdr *smb_buffer = iov[0].iov_base;
129 unsigned int len = iov[0].iov_len;
130 unsigned int total_len;
131 int first_vec = 0;
7ee1af76 132 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
edf1ae40 133 struct socket *ssocket = server->ssocket;
50c2f753 134
79a58d1f 135 if (ssocket == NULL)
1da177e4 136 return -ENOTSOCK; /* BB eventually add reconnect code here */
3e84469d 137
a9f1b85e 138 smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
26f57364 139 smb_msg.msg_namelen = sizeof(struct sockaddr);
1da177e4
LT
140 smb_msg.msg_control = NULL;
141 smb_msg.msg_controllen = 0;
0496e02d 142 if (server->noblocksnd)
edf1ae40
SF
143 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
144 else
145 smb_msg.msg_flags = MSG_NOSIGNAL;
1da177e4
LT
146
147 /* smb header is converted in header_assemble. bcc and rest of SMB word
79a58d1f
SF
148 area, and byte area if necessary, is converted to littleendian in
149 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
1da177e4
LT
150 Flags2 is converted in SendReceive */
151
3e84469d
SF
152
153 total_len = 0;
154 for (i = 0; i < n_vec; i++)
155 total_len += iov[i].iov_len;
156
1da177e4 157 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
b6b38f70 158 cFYI(1, "Sending smb: total_len %d", total_len);
1da177e4
LT
159 dump_smb(smb_buffer, len);
160
17680356 161 i = 0;
3e84469d
SF
162 while (total_len) {
163 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
164 n_vec - first_vec, total_len);
1da177e4
LT
165 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
166 i++;
da505c38
SF
167 /* if blocking send we try 3 times, since each can block
168 for 5 seconds. For nonblocking we have to try more
169 but wait increasing amounts of time allowing time for
170 socket to clear. The overall time we wait in either
171 case to send on the socket is about 15 seconds.
172 Similarly we wait for 15 seconds for
173 a response from the server in SendReceive[2]
174 for the server to send a response back for
175 most types of requests (except SMB Write
176 past end of file which can be slow, and
177 blocking lock operations). NFS waits slightly longer
178 than CIFS, but this can make it take longer for
179 nonresponsive servers to be detected and 15 seconds
180 is more than enough time for modern networks to
181 send a packet. In most cases if we fail to send
182 after the retries we will kill the socket and
183 reconnect which may clear the network problem.
184 */
185 if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
b6b38f70
JP
186 cERROR(1, "sends on sock %p stuck for 15 seconds",
187 ssocket);
1da177e4
LT
188 rc = -EAGAIN;
189 break;
190 }
68058e75 191 msleep(1 << i);
1da177e4
LT
192 continue;
193 }
79a58d1f 194 if (rc < 0)
1da177e4 195 break;
3e84469d 196
61de800d
SF
197 if (rc == total_len) {
198 total_len = 0;
199 break;
200 } else if (rc > total_len) {
b6b38f70 201 cERROR(1, "sent %d requested %d", rc, total_len);
3e84469d
SF
202 break;
203 }
79a58d1f 204 if (rc == 0) {
3e84469d
SF
205 /* should never happen, letting socket clear before
206 retrying is our only obvious option here */
b6b38f70 207 cERROR(1, "tcp sent no data");
3e84469d
SF
208 msleep(500);
209 continue;
d6e04ae6 210 }
3e84469d 211 total_len -= rc;
68058e75 212 /* the line below resets i */
3e84469d
SF
213 for (i = first_vec; i < n_vec; i++) {
214 if (iov[i].iov_len) {
215 if (rc > iov[i].iov_len) {
216 rc -= iov[i].iov_len;
217 iov[i].iov_len = 0;
218 } else {
219 iov[i].iov_base += rc;
220 iov[i].iov_len -= rc;
221 first_vec = i;
222 break;
223 }
224 }
d6e04ae6 225 }
5e1253b5 226 i = 0; /* in case we get ENOSPC on the next send */
1da177e4
LT
227 }
228
edf1ae40 229 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
b6b38f70
JP
230 cFYI(1, "partial send (%d remaining), terminating session",
231 total_len);
edf1ae40
SF
232 /* If we have only sent part of an SMB then the next SMB
233 could be taken as the remainder of this one. We need
234 to kill the socket so the server throws away the partial
235 SMB */
236 server->tcpStatus = CifsNeedReconnect;
237 }
238
d804d41d 239 if (rc < 0 && rc != -EINTR)
b6b38f70 240 cERROR(1, "Error %d sending data on socket to server", rc);
d804d41d 241 else
1da177e4 242 rc = 0;
1da177e4 243
7ee1af76
JA
244 /* Don't want to modify the buffer as a
245 side effect of this call. */
246 smb_buffer->smb_buf_length = smb_buf_length;
247
1da177e4
LT
248 return rc;
249}
250
0496e02d
JL
251int
252smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
253 unsigned int smb_buf_length)
254{
255 struct kvec iov;
256
257 iov.iov_base = smb_buffer;
258 iov.iov_len = smb_buf_length + 4;
259
260 return smb_sendv(server, &iov, 1);
261}
262
c5797a94
JL
263static int wait_for_free_request(struct TCP_Server_Info *server,
264 const int long_op)
1da177e4 265{
133672ef 266 if (long_op == CIFS_ASYNC_OP) {
1da177e4 267 /* oplock breaks must not be held up */
c5797a94 268 atomic_inc(&server->inFlight);
27a97a61
VL
269 return 0;
270 }
271
272 spin_lock(&GlobalMid_Lock);
273 while (1) {
c5797a94 274 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
27a97a61 275 spin_unlock(&GlobalMid_Lock);
131afd0b 276#ifdef CONFIG_CIFS_STATS2
c5797a94 277 atomic_inc(&server->num_waiters);
131afd0b 278#endif
c5797a94
JL
279 wait_event(server->request_q,
280 atomic_read(&server->inFlight)
27a97a61 281 < cifs_max_pending);
131afd0b 282#ifdef CONFIG_CIFS_STATS2
c5797a94 283 atomic_dec(&server->num_waiters);
131afd0b 284#endif
27a97a61
VL
285 spin_lock(&GlobalMid_Lock);
286 } else {
c5797a94 287 if (server->tcpStatus == CifsExiting) {
1da177e4 288 spin_unlock(&GlobalMid_Lock);
27a97a61 289 return -ENOENT;
1da177e4 290 }
27a97a61
VL
291
292 /* can not count locking commands against total
293 as they are allowed to block on server */
294
295 /* update # of requests on the wire to server */
296 if (long_op != CIFS_BLOCKING_OP)
c5797a94 297 atomic_inc(&server->inFlight);
27a97a61
VL
298 spin_unlock(&GlobalMid_Lock);
299 break;
1da177e4
LT
300 }
301 }
7ee1af76
JA
302 return 0;
303}
1da177e4 304
7ee1af76
JA
305static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
306 struct mid_q_entry **ppmidQ)
307{
1da177e4 308 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76 309 return -ENOENT;
8fbbd365
VL
310 }
311
312 if (ses->server->tcpStatus == CifsNeedReconnect) {
b6b38f70 313 cFYI(1, "tcp session dead - return to caller to retry");
7ee1af76 314 return -EAGAIN;
8fbbd365
VL
315 }
316
317 if (ses->status != CifsGood) {
1da177e4 318 /* check if SMB session is bad because we are setting it up */
79a58d1f 319 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
ad7a2926 320 (in_buf->Command != SMB_COM_NEGOTIATE))
7ee1af76 321 return -EAGAIN;
ad7a2926 322 /* else ok - we are setting up session */
1da177e4 323 }
24b9b06b 324 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
26f57364 325 if (*ppmidQ == NULL)
7ee1af76 326 return -ENOMEM;
ddc8cf8f
JL
327 spin_lock(&GlobalMid_Lock);
328 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
329 spin_unlock(&GlobalMid_Lock);
7ee1af76
JA
330 return 0;
331}
332
0ade640e
JL
333static int
334wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
7ee1af76 335{
0ade640e 336 int error;
7ee1af76 337
0ade640e
JL
338 error = wait_event_killable(server->response_q,
339 midQ->midState != MID_REQUEST_SUBMITTED);
340 if (error < 0)
341 return -ERESTARTSYS;
7ee1af76 342
0ade640e 343 return 0;
7ee1af76
JA
344}
345
133672ef 346
a6827c18
JL
347/*
348 * Send a SMB request and set the callback function in the mid to handle
349 * the result. Caller is responsible for dealing with timeouts.
350 */
351int
352cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
353 mid_callback_t *callback, void *cbdata)
354{
355 int rc;
356 struct mid_q_entry *mid;
357
358 rc = wait_for_free_request(server, CIFS_ASYNC_OP);
359 if (rc)
360 return rc;
361
e3f0dadb
JL
362 /* enable signing if server requires it */
363 if (server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
364 in_buf->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
365
a6827c18
JL
366 mutex_lock(&server->srv_mutex);
367 mid = AllocMidQEntry(in_buf, server);
368 if (mid == NULL) {
369 mutex_unlock(&server->srv_mutex);
370 return -ENOMEM;
371 }
372
373 /* put it on the pending_mid_q */
374 spin_lock(&GlobalMid_Lock);
375 list_add_tail(&mid->qhead, &server->pending_mid_q);
376 spin_unlock(&GlobalMid_Lock);
377
378 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
379 if (rc) {
380 mutex_unlock(&server->srv_mutex);
381 goto out_err;
382 }
383
384 mid->callback = callback;
385 mid->callback_data = cbdata;
386 mid->midState = MID_REQUEST_SUBMITTED;
387#ifdef CONFIG_CIFS_STATS2
388 atomic_inc(&server->inSend);
389#endif
390 rc = smb_send(server, in_buf, in_buf->smb_buf_length);
391#ifdef CONFIG_CIFS_STATS2
392 atomic_dec(&server->inSend);
393 mid->when_sent = jiffies;
394#endif
395 mutex_unlock(&server->srv_mutex);
396 if (rc)
397 goto out_err;
398
399 return rc;
400out_err:
401 delete_mid(mid);
402 atomic_dec(&server->inFlight);
403 wake_up(&server->request_q);
404 return rc;
405}
406
133672ef
SF
407/*
408 *
409 * Send an SMB Request. No response info (other than return code)
410 * needs to be parsed.
411 *
412 * flags indicate the type of request buffer and how long to wait
413 * and whether to log NT STATUS code (error) before mapping it to POSIX error
414 *
415 */
416int
417SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
418 struct smb_hdr *in_buf, int flags)
419{
420 int rc;
421 struct kvec iov[1];
422 int resp_buf_type;
423
424 iov[0].iov_base = (char *)in_buf;
425 iov[0].iov_len = in_buf->smb_buf_length + 4;
426 flags |= CIFS_NO_RESP;
427 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
b6b38f70 428 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
90c81e0b 429
133672ef
SF
430 return rc;
431}
432
053d5034
JL
433static int
434sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
435{
436 int rc = 0;
437
74dd92a8
JL
438 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
439 mid->mid, mid->midState);
053d5034 440
74dd92a8 441 spin_lock(&GlobalMid_Lock);
2b84a36c
JL
442 /* ensure that it's no longer on the pending_mid_q */
443 list_del_init(&mid->qhead);
444
74dd92a8
JL
445 switch (mid->midState) {
446 case MID_RESPONSE_RECEIVED:
053d5034
JL
447 spin_unlock(&GlobalMid_Lock);
448 return rc;
74dd92a8
JL
449 case MID_REQUEST_SUBMITTED:
450 /* socket is going down, reject all calls */
451 if (server->tcpStatus == CifsExiting) {
452 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
453 __func__, mid->mid, mid->command, mid->midState);
053d5034 454 rc = -EHOSTDOWN;
74dd92a8 455 break;
053d5034 456 }
74dd92a8
JL
457 case MID_RETRY_NEEDED:
458 rc = -EAGAIN;
459 break;
71823baf
JL
460 case MID_RESPONSE_MALFORMED:
461 rc = -EIO;
462 break;
74dd92a8
JL
463 default:
464 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
465 mid->mid, mid->midState);
466 rc = -EIO;
053d5034
JL
467 }
468 spin_unlock(&GlobalMid_Lock);
469
2b84a36c 470 DeleteMidQEntry(mid);
053d5034
JL
471 return rc;
472}
473
76dcc26f
JL
474/*
475 * An NT cancel request header looks just like the original request except:
476 *
477 * The Command is SMB_COM_NT_CANCEL
478 * The WordCount is zeroed out
479 * The ByteCount is zeroed out
480 *
481 * This function mangles an existing request buffer into a
482 * SMB_COM_NT_CANCEL request and then sends it.
483 */
484static int
485send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
486 struct mid_q_entry *mid)
487{
488 int rc = 0;
489
490 /* -4 for RFC1001 length and +2 for BCC field */
491 in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2;
492 in_buf->Command = SMB_COM_NT_CANCEL;
493 in_buf->WordCount = 0;
690c522f 494 put_bcc_le(0, in_buf);
76dcc26f
JL
495
496 mutex_lock(&server->srv_mutex);
497 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
498 if (rc) {
499 mutex_unlock(&server->srv_mutex);
500 return rc;
501 }
502 rc = smb_send(server, in_buf, in_buf->smb_buf_length);
503 mutex_unlock(&server->srv_mutex);
504
505 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
506 in_buf->Mid, rc);
507
508 return rc;
509}
510
7ee1af76 511int
79a58d1f
SF
512SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
513 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
133672ef 514 const int flags)
7ee1af76
JA
515{
516 int rc = 0;
133672ef 517 int long_op;
7ee1af76 518 unsigned int receive_len;
7ee1af76
JA
519 struct mid_q_entry *midQ;
520 struct smb_hdr *in_buf = iov[0].iov_base;
50c2f753 521
133672ef
SF
522 long_op = flags & CIFS_TIMEOUT_MASK;
523
7ee1af76
JA
524 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
525
526 if ((ses == NULL) || (ses->server == NULL)) {
527 cifs_small_buf_release(in_buf);
b6b38f70 528 cERROR(1, "Null session");
7ee1af76
JA
529 return -EIO;
530 }
531
79a58d1f 532 if (ses->server->tcpStatus == CifsExiting) {
7ee1af76
JA
533 cifs_small_buf_release(in_buf);
534 return -ENOENT;
535 }
536
79a58d1f 537 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
538 to the same server. We may make this configurable later or
539 use ses->maxReq */
540
c5797a94 541 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
542 if (rc) {
543 cifs_small_buf_release(in_buf);
544 return rc;
545 }
546
79a58d1f 547 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
548 and avoid races inside tcp sendmsg code that could cause corruption
549 of smb data */
550
72ca545b 551 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
552
553 rc = allocate_mid(ses, in_buf, &midQ);
554 if (rc) {
72ca545b 555 mutex_unlock(&ses->server->srv_mutex);
4b8f930f 556 cifs_small_buf_release(in_buf);
7ee1af76 557 /* Update # of requests on wire to server */
79a58d1f 558 atomic_dec(&ses->server->inFlight);
7ee1af76
JA
559 wake_up(&ses->server->request_q);
560 return rc;
1da177e4 561 }
79a58d1f 562 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
829049cb
VL
563 if (rc) {
564 mutex_unlock(&ses->server->srv_mutex);
565 cifs_small_buf_release(in_buf);
566 goto out;
567 }
1da177e4
LT
568
569 midQ->midState = MID_REQUEST_SUBMITTED;
131afd0b
SF
570#ifdef CONFIG_CIFS_STATS2
571 atomic_inc(&ses->server->inSend);
572#endif
0496e02d 573 rc = smb_sendv(ses->server, iov, n_vec);
131afd0b
SF
574#ifdef CONFIG_CIFS_STATS2
575 atomic_dec(&ses->server->inSend);
1047abc1 576 midQ->when_sent = jiffies;
131afd0b 577#endif
7ee1af76 578
72ca545b 579 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 580
2db7c581
JL
581 if (rc < 0) {
582 cifs_small_buf_release(in_buf);
7ee1af76 583 goto out;
2db7c581 584 }
4b8f930f 585
2db7c581
JL
586 if (long_op == CIFS_ASYNC_OP) {
587 cifs_small_buf_release(in_buf);
133672ef 588 goto out;
2db7c581 589 }
d6e04ae6 590
0ade640e 591 rc = wait_for_response(ses->server, midQ);
1be912dd 592 if (rc != 0) {
2db7c581 593 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
594 spin_lock(&GlobalMid_Lock);
595 if (midQ->midState == MID_REQUEST_SUBMITTED) {
596 midQ->callback = DeleteMidQEntry;
597 spin_unlock(&GlobalMid_Lock);
2db7c581 598 cifs_small_buf_release(in_buf);
1be912dd
JL
599 atomic_dec(&ses->server->inFlight);
600 wake_up(&ses->server->request_q);
601 return rc;
602 }
603 spin_unlock(&GlobalMid_Lock);
604 }
d6e04ae6 605
2db7c581
JL
606 cifs_small_buf_release(in_buf);
607
053d5034
JL
608 rc = sync_mid_result(midQ, ses->server);
609 if (rc != 0) {
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 receive_len = midQ->resp_buf->smb_buf_length;
616
d6e04ae6 617 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
b6b38f70
JP
618 cERROR(1, "Frame too large received. Length: %d Xid: %d",
619 receive_len, xid);
d6e04ae6 620 rc = -EIO;
2b2bdfba
SF
621 goto out;
622 }
623
624 /* rcvd frame is ok */
625
626 if (midQ->resp_buf &&
627 (midQ->midState == MID_RESPONSE_RECEIVED)) {
628
629 iov[0].iov_base = (char *)midQ->resp_buf;
630 if (midQ->largeBuf)
631 *pRespBufType = CIFS_LARGE_BUFFER;
632 else
633 *pRespBufType = CIFS_SMALL_BUFFER;
634 iov[0].iov_len = receive_len + 4;
635
636 dump_smb(midQ->resp_buf, 80);
637 /* convert the length into a more usable form */
638 if ((receive_len > 24) &&
639 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
640 SECMODE_SIGN_ENABLED))) {
641 rc = cifs_verify_signature(midQ->resp_buf,
21e73393 642 ses->server,
d6e04ae6 643 midQ->sequence_number+1);
2b2bdfba 644 if (rc) {
b6b38f70 645 cERROR(1, "Unexpected SMB signature");
2b2bdfba 646 /* BB FIXME add code to kill session */
d6e04ae6 647 }
d6e04ae6 648 }
2b2bdfba
SF
649
650 /* BB special case reconnect tid and uid here? */
651 rc = map_smb_to_linux_error(midQ->resp_buf,
652 flags & CIFS_LOG_ERROR);
653
654 /* convert ByteCount if necessary */
655 if (receive_len >= sizeof(struct smb_hdr) - 4
656 /* do not count RFC1001 header */ +
657 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
690c522f 658 put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf);
2b2bdfba
SF
659 if ((flags & CIFS_NO_RESP) == 0)
660 midQ->resp_buf = NULL; /* mark it so buf will
661 not be freed by
ddc8cf8f 662 delete_mid */
2b2bdfba
SF
663 } else {
664 rc = -EIO;
b6b38f70 665 cFYI(1, "Bad MID state?");
d6e04ae6 666 }
1da177e4 667
7ee1af76 668out:
ddc8cf8f 669 delete_mid(midQ);
79a58d1f 670 atomic_dec(&ses->server->inFlight);
7ee1af76 671 wake_up(&ses->server->request_q);
1da177e4 672
d6e04ae6
SF
673 return rc;
674}
1da177e4
LT
675
676int
677SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
678 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
679 int *pbytes_returned, const int long_op)
680{
681 int rc = 0;
682 unsigned int receive_len;
1da177e4
LT
683 struct mid_q_entry *midQ;
684
685 if (ses == NULL) {
b6b38f70 686 cERROR(1, "Null smb session");
1da177e4
LT
687 return -EIO;
688 }
79a58d1f 689 if (ses->server == NULL) {
b6b38f70 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 701 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
b6b38f70
JP
702 cERROR(1, "Illegal length, greater than maximum frame, %d",
703 in_buf->smb_buf_length);
6d9c6d54
VL
704 return -EIO;
705 }
706
c5797a94 707 rc = wait_for_free_request(ses->server, long_op);
7ee1af76
JA
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
0496e02d 736 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
131afd0b
SF
737#ifdef CONFIG_CIFS_STATS2
738 atomic_dec(&ses->server->inSend);
1047abc1 739 midQ->when_sent = jiffies;
131afd0b 740#endif
72ca545b 741 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 742
79a58d1f 743 if (rc < 0)
7ee1af76
JA
744 goto out;
745
0ade640e 746 if (long_op == CIFS_ASYNC_OP)
7ee1af76 747 goto out;
1da177e4 748
0ade640e 749 rc = wait_for_response(ses->server, midQ);
1be912dd 750 if (rc != 0) {
2db7c581 751 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
752 spin_lock(&GlobalMid_Lock);
753 if (midQ->midState == MID_REQUEST_SUBMITTED) {
754 /* no longer considered to be "in-flight" */
755 midQ->callback = DeleteMidQEntry;
756 spin_unlock(&GlobalMid_Lock);
757 atomic_dec(&ses->server->inFlight);
758 wake_up(&ses->server->request_q);
759 return rc;
760 }
761 spin_unlock(&GlobalMid_Lock);
762 }
1da177e4 763
053d5034
JL
764 rc = sync_mid_result(midQ, ses->server);
765 if (rc != 0) {
79a58d1f 766 atomic_dec(&ses->server->inFlight);
7ee1af76 767 wake_up(&ses->server->request_q);
1da177e4
LT
768 return rc;
769 }
50c2f753 770
8e4f2e8a
VL
771 receive_len = midQ->resp_buf->smb_buf_length;
772
1da177e4 773 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
b6b38f70
JP
774 cERROR(1, "Frame too large received. Length: %d Xid: %d",
775 receive_len, xid);
1da177e4 776 rc = -EIO;
2b2bdfba
SF
777 goto out;
778 }
779
780 /* rcvd frame is ok */
781
782 if (midQ->resp_buf && out_buf
783 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
784 out_buf->smb_buf_length = receive_len;
785 memcpy((char *)out_buf + 4,
786 (char *)midQ->resp_buf + 4,
787 receive_len);
788
789 dump_smb(out_buf, 92);
790 /* convert the length into a more usable form */
791 if ((receive_len > 24) &&
792 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
793 SECMODE_SIGN_ENABLED))) {
794 rc = cifs_verify_signature(out_buf,
21e73393 795 ses->server,
ad009ac9 796 midQ->sequence_number+1);
2b2bdfba 797 if (rc) {
b6b38f70 798 cERROR(1, "Unexpected SMB signature");
2b2bdfba 799 /* BB FIXME add code to kill session */
1da177e4 800 }
2b2bdfba 801 }
1da177e4 802
2b2bdfba 803 *pbytes_returned = out_buf->smb_buf_length;
1da177e4 804
2b2bdfba
SF
805 /* BB special case reconnect tid and uid here? */
806 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1da177e4 807
2b2bdfba
SF
808 /* convert ByteCount if necessary */
809 if (receive_len >= sizeof(struct smb_hdr) - 4
810 /* do not count RFC1001 header */ +
811 (2 * out_buf->WordCount) + 2 /* bcc */ )
690c522f 812 put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf);
2b2bdfba
SF
813 } else {
814 rc = -EIO;
b6b38f70 815 cERROR(1, "Bad MID state?");
1da177e4 816 }
7ee1af76
JA
817
818out:
ddc8cf8f 819 delete_mid(midQ);
79a58d1f 820 atomic_dec(&ses->server->inFlight);
7ee1af76 821 wake_up(&ses->server->request_q);
1da177e4 822
7ee1af76
JA
823 return rc;
824}
1da177e4 825
7ee1af76
JA
826/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
827 blocking lock to return. */
828
829static int
830send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
831 struct smb_hdr *in_buf,
832 struct smb_hdr *out_buf)
833{
834 int bytes_returned;
835 struct cifsSesInfo *ses = tcon->ses;
836 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
837
838 /* We just modify the current in_buf to change
839 the type of lock from LOCKING_ANDX_SHARED_LOCK
840 or LOCKING_ANDX_EXCLUSIVE_LOCK to
841 LOCKING_ANDX_CANCEL_LOCK. */
842
843 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
844 pSMB->Timeout = 0;
845 pSMB->hdr.Mid = GetNextMid(ses->server);
846
847 return SendReceive(xid, ses, in_buf, out_buf,
7749981e 848 &bytes_returned, 0);
7ee1af76
JA
849}
850
851int
852SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
853 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
854 int *pbytes_returned)
855{
856 int rc = 0;
857 int rstart = 0;
858 unsigned int receive_len;
859 struct mid_q_entry *midQ;
860 struct cifsSesInfo *ses;
861
862 if (tcon == NULL || tcon->ses == NULL) {
b6b38f70 863 cERROR(1, "Null smb session");
7ee1af76
JA
864 return -EIO;
865 }
866 ses = tcon->ses;
867
79a58d1f 868 if (ses->server == NULL) {
b6b38f70 869 cERROR(1, "Null tcp session");
7ee1af76
JA
870 return -EIO;
871 }
872
79a58d1f 873 if (ses->server->tcpStatus == CifsExiting)
7ee1af76
JA
874 return -ENOENT;
875
79a58d1f 876 /* Ensure that we do not send more than 50 overlapping requests
7ee1af76
JA
877 to the same server. We may make this configurable later or
878 use ses->maxReq */
879
6d9c6d54 880 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
b6b38f70
JP
881 cERROR(1, "Illegal length, greater than maximum frame, %d",
882 in_buf->smb_buf_length);
6d9c6d54
VL
883 return -EIO;
884 }
885
c5797a94 886 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
7ee1af76
JA
887 if (rc)
888 return rc;
889
79a58d1f 890 /* make sure that we sign in the same order that we send on this socket
7ee1af76
JA
891 and avoid races inside tcp sendmsg code that could cause corruption
892 of smb data */
893
72ca545b 894 mutex_lock(&ses->server->srv_mutex);
7ee1af76
JA
895
896 rc = allocate_mid(ses, in_buf, &midQ);
897 if (rc) {
72ca545b 898 mutex_unlock(&ses->server->srv_mutex);
7ee1af76
JA
899 return rc;
900 }
901
7ee1af76 902 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
829049cb 903 if (rc) {
ddc8cf8f 904 delete_mid(midQ);
829049cb
VL
905 mutex_unlock(&ses->server->srv_mutex);
906 return rc;
907 }
1da177e4 908
7ee1af76
JA
909 midQ->midState = MID_REQUEST_SUBMITTED;
910#ifdef CONFIG_CIFS_STATS2
911 atomic_inc(&ses->server->inSend);
912#endif
0496e02d 913 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
7ee1af76
JA
914#ifdef CONFIG_CIFS_STATS2
915 atomic_dec(&ses->server->inSend);
916 midQ->when_sent = jiffies;
917#endif
72ca545b 918 mutex_unlock(&ses->server->srv_mutex);
7ee1af76 919
79a58d1f 920 if (rc < 0) {
ddc8cf8f 921 delete_mid(midQ);
7ee1af76
JA
922 return rc;
923 }
924
925 /* Wait for a reply - allow signals to interrupt. */
926 rc = wait_event_interruptible(ses->server->response_q,
79a58d1f 927 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
7ee1af76
JA
928 ((ses->server->tcpStatus != CifsGood) &&
929 (ses->server->tcpStatus != CifsNew)));
930
931 /* Were we interrupted by a signal ? */
932 if ((rc == -ERESTARTSYS) &&
933 (midQ->midState == MID_REQUEST_SUBMITTED) &&
934 ((ses->server->tcpStatus == CifsGood) ||
935 (ses->server->tcpStatus == CifsNew))) {
936
937 if (in_buf->Command == SMB_COM_TRANSACTION2) {
938 /* POSIX lock. We send a NT_CANCEL SMB to cause the
939 blocking lock to return. */
76dcc26f 940 rc = send_nt_cancel(ses->server, in_buf, midQ);
7ee1af76 941 if (rc) {
ddc8cf8f 942 delete_mid(midQ);
7ee1af76
JA
943 return rc;
944 }
945 } else {
946 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
947 to cause the blocking lock to return. */
948
949 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
950
951 /* If we get -ENOLCK back the lock may have
952 already been removed. Don't exit in this case. */
953 if (rc && rc != -ENOLCK) {
ddc8cf8f 954 delete_mid(midQ);
7ee1af76
JA
955 return rc;
956 }
957 }
958
1be912dd
JL
959 rc = wait_for_response(ses->server, midQ);
960 if (rc) {
2db7c581 961 send_nt_cancel(ses->server, in_buf, midQ);
1be912dd
JL
962 spin_lock(&GlobalMid_Lock);
963 if (midQ->midState == MID_REQUEST_SUBMITTED) {
964 /* no longer considered to be "in-flight" */
965 midQ->callback = DeleteMidQEntry;
966 spin_unlock(&GlobalMid_Lock);
967 return rc;
968 }
969 spin_unlock(&GlobalMid_Lock);
7ee1af76 970 }
1be912dd
JL
971
972 /* We got the response - restart system call. */
973 rstart = 1;
7ee1af76
JA
974 }
975
053d5034
JL
976 rc = sync_mid_result(midQ, ses->server);
977 if (rc != 0)
7ee1af76 978 return rc;
50c2f753 979
053d5034 980 receive_len = midQ->resp_buf->smb_buf_length;
7ee1af76 981 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
b6b38f70
JP
982 cERROR(1, "Frame too large received. Length: %d Xid: %d",
983 receive_len, xid);
7ee1af76 984 rc = -EIO;
17c8bfed
VL
985 goto out;
986 }
7ee1af76 987
17c8bfed 988 /* rcvd frame is ok */
7ee1af76 989
ac6a3ef4 990 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
698e96a8 991 rc = -EIO;
b6b38f70 992 cERROR(1, "Bad MID state?");
698e96a8
VL
993 goto out;
994 }
1da177e4 995
698e96a8
VL
996 out_buf->smb_buf_length = receive_len;
997 memcpy((char *)out_buf + 4,
998 (char *)midQ->resp_buf + 4,
999 receive_len);
1000
1001 dump_smb(out_buf, 92);
1002 /* convert the length into a more usable form */
1003 if ((receive_len > 24) &&
1004 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1005 SECMODE_SIGN_ENABLED))) {
1006 rc = cifs_verify_signature(out_buf,
21e73393 1007 ses->server,
698e96a8
VL
1008 midQ->sequence_number+1);
1009 if (rc) {
b6b38f70 1010 cERROR(1, "Unexpected SMB signature");
698e96a8 1011 /* BB FIXME add code to kill session */
7ee1af76 1012 }
698e96a8 1013 }
17c8bfed 1014
698e96a8 1015 *pbytes_returned = out_buf->smb_buf_length;
17c8bfed 1016
698e96a8
VL
1017 /* BB special case reconnect tid and uid here? */
1018 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
17c8bfed 1019
698e96a8
VL
1020 /* convert ByteCount if necessary */
1021 if (receive_len >= sizeof(struct smb_hdr) - 4
1022 /* do not count RFC1001 header */ +
1023 (2 * out_buf->WordCount) + 2 /* bcc */ )
690c522f 1024 put_bcc(get_bcc_le(out_buf), out_buf);
17c8bfed
VL
1025
1026out:
ddc8cf8f 1027 delete_mid(midQ);
7ee1af76
JA
1028 if (rstart && rc == -EACCES)
1029 return -ERESTARTSYS;
1da177e4
LT
1030 return rc;
1031}
This page took 0.421114 seconds and 5 git commands to generate.