Full support for Ginger Console
[linux-ginger.git] / fs / cifs / transport.c
blob07b8e71544ee254e8941b03680cc8eaf62a20847
1 /*
2 * fs/cifs/transport.c
4 * Copyright (C) International Business Machines Corp., 2002,2008
5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * Jeremy Allison (jra@samba.org) 2006.
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.
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.
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
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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"
36 extern mempool_t *cifs_mid_poolp;
37 extern struct kmem_cache *cifs_oplock_cachep;
39 static struct mid_q_entry *
40 AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
42 struct mid_q_entry *temp;
44 if (server == NULL) {
45 cERROR(1, ("Null TCP session in AllocMidQEntry"));
46 return NULL;
49 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
50 if (temp == NULL)
51 return temp;
52 else {
53 memset(temp, 0, sizeof(struct mid_q_entry));
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));
58 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
59 /* when mid allocated can be before when sent */
60 temp->when_alloc = jiffies;
61 temp->tsk = current;
64 spin_lock(&GlobalMid_Lock);
65 list_add_tail(&temp->qhead, &server->pending_mid_q);
66 atomic_inc(&midCount);
67 temp->midState = MID_REQUEST_ALLOCATED;
68 spin_unlock(&GlobalMid_Lock);
69 return temp;
72 static void
73 DeleteMidQEntry(struct mid_q_entry *midEntry)
75 #ifdef CONFIG_CIFS_STATS2
76 unsigned long now;
77 #endif
78 spin_lock(&GlobalMid_Lock);
79 midEntry->midState = MID_FREE;
80 list_del(&midEntry->qhead);
81 atomic_dec(&midCount);
82 spin_unlock(&GlobalMid_Lock);
83 if (midEntry->largeBuf)
84 cifs_buf_release(midEntry->resp_buf);
85 else
86 cifs_small_buf_release(midEntry->resp_buf);
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 */
91 if ((now - midEntry->when_alloc) > HZ) {
92 if ((cifsFYI & CIFS_TIMER) &&
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);
102 #endif
103 mempool_free(midEntry, cifs_mid_poolp);
106 static int
107 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
109 int rc = 0;
110 int i = 0;
111 struct msghdr smb_msg;
112 struct smb_hdr *smb_buffer = iov[0].iov_base;
113 unsigned int len = iov[0].iov_len;
114 unsigned int total_len;
115 int first_vec = 0;
116 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
117 struct socket *ssocket = server->ssocket;
119 if (ssocket == NULL)
120 return -ENOTSOCK; /* BB eventually add reconnect code here */
122 smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr;
123 smb_msg.msg_namelen = sizeof(struct sockaddr);
124 smb_msg.msg_control = NULL;
125 smb_msg.msg_controllen = 0;
126 if (server->noblocksnd)
127 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
128 else
129 smb_msg.msg_flags = MSG_NOSIGNAL;
131 /* smb header is converted in header_assemble. bcc and rest of SMB word
132 area, and byte area if necessary, is converted to littleendian in
133 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
134 Flags2 is converted in SendReceive */
137 total_len = 0;
138 for (i = 0; i < n_vec; i++)
139 total_len += iov[i].iov_len;
141 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
142 cFYI(1, ("Sending smb: total_len %d", total_len));
143 dump_smb(smb_buffer, len);
145 i = 0;
146 while (total_len) {
147 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
148 n_vec - first_vec, total_len);
149 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
150 i++;
151 /* if blocking send we try 3 times, since each can block
152 for 5 seconds. For nonblocking we have to try more
153 but wait increasing amounts of time allowing time for
154 socket to clear. The overall time we wait in either
155 case to send on the socket is about 15 seconds.
156 Similarly we wait for 15 seconds for
157 a response from the server in SendReceive[2]
158 for the server to send a response back for
159 most types of requests (except SMB Write
160 past end of file which can be slow, and
161 blocking lock operations). NFS waits slightly longer
162 than CIFS, but this can make it take longer for
163 nonresponsive servers to be detected and 15 seconds
164 is more than enough time for modern networks to
165 send a packet. In most cases if we fail to send
166 after the retries we will kill the socket and
167 reconnect which may clear the network problem.
169 if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
170 cERROR(1,
171 ("sends on sock %p stuck for 15 seconds",
172 ssocket));
173 rc = -EAGAIN;
174 break;
176 msleep(1 << i);
177 continue;
179 if (rc < 0)
180 break;
182 if (rc == total_len) {
183 total_len = 0;
184 break;
185 } else if (rc > total_len) {
186 cERROR(1, ("sent %d requested %d", rc, total_len));
187 break;
189 if (rc == 0) {
190 /* should never happen, letting socket clear before
191 retrying is our only obvious option here */
192 cERROR(1, ("tcp sent no data"));
193 msleep(500);
194 continue;
196 total_len -= rc;
197 /* the line below resets i */
198 for (i = first_vec; i < n_vec; i++) {
199 if (iov[i].iov_len) {
200 if (rc > iov[i].iov_len) {
201 rc -= iov[i].iov_len;
202 iov[i].iov_len = 0;
203 } else {
204 iov[i].iov_base += rc;
205 iov[i].iov_len -= rc;
206 first_vec = i;
207 break;
211 i = 0; /* in case we get ENOSPC on the next send */
214 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
215 cFYI(1, ("partial send (%d remaining), terminating session",
216 total_len));
217 /* If we have only sent part of an SMB then the next SMB
218 could be taken as the remainder of this one. We need
219 to kill the socket so the server throws away the partial
220 SMB */
221 server->tcpStatus = CifsNeedReconnect;
224 if (rc < 0) {
225 cERROR(1, ("Error %d sending data on socket to server", rc));
226 } else
227 rc = 0;
229 /* Don't want to modify the buffer as a
230 side effect of this call. */
231 smb_buffer->smb_buf_length = smb_buf_length;
233 return rc;
237 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
238 unsigned int smb_buf_length)
240 struct kvec iov;
242 iov.iov_base = smb_buffer;
243 iov.iov_len = smb_buf_length + 4;
245 return smb_sendv(server, &iov, 1);
248 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
250 if (long_op == CIFS_ASYNC_OP) {
251 /* oplock breaks must not be held up */
252 atomic_inc(&ses->server->inFlight);
253 return 0;
256 spin_lock(&GlobalMid_Lock);
257 while (1) {
258 if (atomic_read(&ses->server->inFlight) >=
259 cifs_max_pending){
260 spin_unlock(&GlobalMid_Lock);
261 #ifdef CONFIG_CIFS_STATS2
262 atomic_inc(&ses->server->num_waiters);
263 #endif
264 wait_event(ses->server->request_q,
265 atomic_read(&ses->server->inFlight)
266 < cifs_max_pending);
267 #ifdef CONFIG_CIFS_STATS2
268 atomic_dec(&ses->server->num_waiters);
269 #endif
270 spin_lock(&GlobalMid_Lock);
271 } else {
272 if (ses->server->tcpStatus == CifsExiting) {
273 spin_unlock(&GlobalMid_Lock);
274 return -ENOENT;
277 /* can not count locking commands against total
278 as they are allowed to block on server */
280 /* update # of requests on the wire to server */
281 if (long_op != CIFS_BLOCKING_OP)
282 atomic_inc(&ses->server->inFlight);
283 spin_unlock(&GlobalMid_Lock);
284 break;
287 return 0;
290 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
291 struct mid_q_entry **ppmidQ)
293 if (ses->server->tcpStatus == CifsExiting) {
294 return -ENOENT;
297 if (ses->server->tcpStatus == CifsNeedReconnect) {
298 cFYI(1, ("tcp session dead - return to caller to retry"));
299 return -EAGAIN;
302 if (ses->status != CifsGood) {
303 /* check if SMB session is bad because we are setting it up */
304 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
305 (in_buf->Command != SMB_COM_NEGOTIATE))
306 return -EAGAIN;
307 /* else ok - we are setting up session */
309 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
310 if (*ppmidQ == NULL)
311 return -ENOMEM;
312 return 0;
315 static int wait_for_response(struct cifsSesInfo *ses,
316 struct mid_q_entry *midQ,
317 unsigned long timeout,
318 unsigned long time_to_wait)
320 unsigned long curr_timeout;
322 for (;;) {
323 curr_timeout = timeout + jiffies;
324 wait_event_timeout(ses->server->response_q,
325 midQ->midState != MID_REQUEST_SUBMITTED, timeout);
327 if (time_after(jiffies, curr_timeout) &&
328 (midQ->midState == MID_REQUEST_SUBMITTED) &&
329 ((ses->server->tcpStatus == CifsGood) ||
330 (ses->server->tcpStatus == CifsNew))) {
332 unsigned long lrt;
334 /* We timed out. Is the server still
335 sending replies ? */
336 spin_lock(&GlobalMid_Lock);
337 lrt = ses->server->lstrp;
338 spin_unlock(&GlobalMid_Lock);
340 /* Calculate time_to_wait past last receive time.
341 Although we prefer not to time out if the
342 server is still responding - we will time
343 out if the server takes more than 15 (or 45
344 or 180) seconds to respond to this request
345 and has not responded to any request from
346 other threads on the client within 10 seconds */
347 lrt += time_to_wait;
348 if (time_after(jiffies, lrt)) {
349 /* No replies for time_to_wait. */
350 cERROR(1, ("server not responding"));
351 return -1;
353 } else {
354 return 0;
362 * Send an SMB Request. No response info (other than return code)
363 * needs to be parsed.
365 * flags indicate the type of request buffer and how long to wait
366 * and whether to log NT STATUS code (error) before mapping it to POSIX error
370 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
371 struct smb_hdr *in_buf, int flags)
373 int rc;
374 struct kvec iov[1];
375 int resp_buf_type;
377 iov[0].iov_base = (char *)in_buf;
378 iov[0].iov_len = in_buf->smb_buf_length + 4;
379 flags |= CIFS_NO_RESP;
380 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
381 cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
383 return rc;
387 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
388 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
389 const int flags)
391 int rc = 0;
392 int long_op;
393 unsigned int receive_len;
394 unsigned long timeout;
395 struct mid_q_entry *midQ;
396 struct smb_hdr *in_buf = iov[0].iov_base;
398 long_op = flags & CIFS_TIMEOUT_MASK;
400 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
402 if ((ses == NULL) || (ses->server == NULL)) {
403 cifs_small_buf_release(in_buf);
404 cERROR(1, ("Null session"));
405 return -EIO;
408 if (ses->server->tcpStatus == CifsExiting) {
409 cifs_small_buf_release(in_buf);
410 return -ENOENT;
413 /* Ensure that we do not send more than 50 overlapping requests
414 to the same server. We may make this configurable later or
415 use ses->maxReq */
417 rc = wait_for_free_request(ses, long_op);
418 if (rc) {
419 cifs_small_buf_release(in_buf);
420 return rc;
423 /* make sure that we sign in the same order that we send on this socket
424 and avoid races inside tcp sendmsg code that could cause corruption
425 of smb data */
427 mutex_lock(&ses->server->srv_mutex);
429 rc = allocate_mid(ses, in_buf, &midQ);
430 if (rc) {
431 mutex_unlock(&ses->server->srv_mutex);
432 cifs_small_buf_release(in_buf);
433 /* Update # of requests on wire to server */
434 atomic_dec(&ses->server->inFlight);
435 wake_up(&ses->server->request_q);
436 return rc;
438 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
439 if (rc) {
440 mutex_unlock(&ses->server->srv_mutex);
441 cifs_small_buf_release(in_buf);
442 goto out;
445 midQ->midState = MID_REQUEST_SUBMITTED;
446 #ifdef CONFIG_CIFS_STATS2
447 atomic_inc(&ses->server->inSend);
448 #endif
449 rc = smb_sendv(ses->server, iov, n_vec);
450 #ifdef CONFIG_CIFS_STATS2
451 atomic_dec(&ses->server->inSend);
452 midQ->when_sent = jiffies;
453 #endif
455 mutex_unlock(&ses->server->srv_mutex);
456 cifs_small_buf_release(in_buf);
458 if (rc < 0)
459 goto out;
461 if (long_op == CIFS_STD_OP)
462 timeout = 15 * HZ;
463 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
464 timeout = 180 * HZ;
465 else if (long_op == CIFS_LONG_OP)
466 timeout = 45 * HZ; /* should be greater than
467 servers oplock break timeout (about 43 seconds) */
468 else if (long_op == CIFS_ASYNC_OP)
469 goto out;
470 else if (long_op == CIFS_BLOCKING_OP)
471 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
472 else {
473 cERROR(1, ("unknown timeout flag %d", long_op));
474 rc = -EIO;
475 goto out;
478 /* wait for 15 seconds or until woken up due to response arriving or
479 due to last connection to this server being unmounted */
480 if (signal_pending(current)) {
481 /* if signal pending do not hold up user for full smb timeout
482 but we still give response a chance to complete */
483 timeout = 2 * HZ;
486 /* No user interrupts in wait - wreaks havoc with performance */
487 wait_for_response(ses, midQ, timeout, 10 * HZ);
489 spin_lock(&GlobalMid_Lock);
491 if (midQ->resp_buf == NULL) {
492 cERROR(1, ("No response to cmd %d mid %d",
493 midQ->command, midQ->mid));
494 if (midQ->midState == MID_REQUEST_SUBMITTED) {
495 if (ses->server->tcpStatus == CifsExiting)
496 rc = -EHOSTDOWN;
497 else {
498 ses->server->tcpStatus = CifsNeedReconnect;
499 midQ->midState = MID_RETRY_NEEDED;
503 if (rc != -EHOSTDOWN) {
504 if (midQ->midState == MID_RETRY_NEEDED) {
505 rc = -EAGAIN;
506 cFYI(1, ("marking request for retry"));
507 } else {
508 rc = -EIO;
511 spin_unlock(&GlobalMid_Lock);
512 DeleteMidQEntry(midQ);
513 /* Update # of requests on wire to server */
514 atomic_dec(&ses->server->inFlight);
515 wake_up(&ses->server->request_q);
516 return rc;
519 spin_unlock(&GlobalMid_Lock);
520 receive_len = midQ->resp_buf->smb_buf_length;
522 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
523 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
524 receive_len, xid));
525 rc = -EIO;
526 goto out;
529 /* rcvd frame is ok */
531 if (midQ->resp_buf &&
532 (midQ->midState == MID_RESPONSE_RECEIVED)) {
534 iov[0].iov_base = (char *)midQ->resp_buf;
535 if (midQ->largeBuf)
536 *pRespBufType = CIFS_LARGE_BUFFER;
537 else
538 *pRespBufType = CIFS_SMALL_BUFFER;
539 iov[0].iov_len = receive_len + 4;
541 dump_smb(midQ->resp_buf, 80);
542 /* convert the length into a more usable form */
543 if ((receive_len > 24) &&
544 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
545 SECMODE_SIGN_ENABLED))) {
546 rc = cifs_verify_signature(midQ->resp_buf,
547 &ses->server->mac_signing_key,
548 midQ->sequence_number+1);
549 if (rc) {
550 cERROR(1, ("Unexpected SMB signature"));
551 /* BB FIXME add code to kill session */
555 /* BB special case reconnect tid and uid here? */
556 rc = map_smb_to_linux_error(midQ->resp_buf,
557 flags & CIFS_LOG_ERROR);
559 /* convert ByteCount if necessary */
560 if (receive_len >= sizeof(struct smb_hdr) - 4
561 /* do not count RFC1001 header */ +
562 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
563 BCC(midQ->resp_buf) =
564 le16_to_cpu(BCC_LE(midQ->resp_buf));
565 if ((flags & CIFS_NO_RESP) == 0)
566 midQ->resp_buf = NULL; /* mark it so buf will
567 not be freed by
568 DeleteMidQEntry */
569 } else {
570 rc = -EIO;
571 cFYI(1, ("Bad MID state?"));
574 out:
575 DeleteMidQEntry(midQ);
576 atomic_dec(&ses->server->inFlight);
577 wake_up(&ses->server->request_q);
579 return rc;
583 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
584 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
585 int *pbytes_returned, const int long_op)
587 int rc = 0;
588 unsigned int receive_len;
589 unsigned long timeout;
590 struct mid_q_entry *midQ;
592 if (ses == NULL) {
593 cERROR(1, ("Null smb session"));
594 return -EIO;
596 if (ses->server == NULL) {
597 cERROR(1, ("Null tcp session"));
598 return -EIO;
601 if (ses->server->tcpStatus == CifsExiting)
602 return -ENOENT;
604 /* Ensure that we do not send more than 50 overlapping requests
605 to the same server. We may make this configurable later or
606 use ses->maxReq */
608 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
609 cERROR(1, ("Illegal length, greater than maximum frame, %d",
610 in_buf->smb_buf_length));
611 return -EIO;
614 rc = wait_for_free_request(ses, long_op);
615 if (rc)
616 return rc;
618 /* make sure that we sign in the same order that we send on this socket
619 and avoid races inside tcp sendmsg code that could cause corruption
620 of smb data */
622 mutex_lock(&ses->server->srv_mutex);
624 rc = allocate_mid(ses, in_buf, &midQ);
625 if (rc) {
626 mutex_unlock(&ses->server->srv_mutex);
627 /* Update # of requests on wire to server */
628 atomic_dec(&ses->server->inFlight);
629 wake_up(&ses->server->request_q);
630 return rc;
633 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
634 if (rc) {
635 mutex_unlock(&ses->server->srv_mutex);
636 goto out;
639 midQ->midState = MID_REQUEST_SUBMITTED;
640 #ifdef CONFIG_CIFS_STATS2
641 atomic_inc(&ses->server->inSend);
642 #endif
643 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
644 #ifdef CONFIG_CIFS_STATS2
645 atomic_dec(&ses->server->inSend);
646 midQ->when_sent = jiffies;
647 #endif
648 mutex_unlock(&ses->server->srv_mutex);
650 if (rc < 0)
651 goto out;
653 if (long_op == CIFS_STD_OP)
654 timeout = 15 * HZ;
655 /* wait for 15 seconds or until woken up due to response arriving or
656 due to last connection to this server being unmounted */
657 else if (long_op == CIFS_ASYNC_OP)
658 goto out;
659 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
660 timeout = 180 * HZ;
661 else if (long_op == CIFS_LONG_OP)
662 timeout = 45 * HZ; /* should be greater than
663 servers oplock break timeout (about 43 seconds) */
664 else if (long_op == CIFS_BLOCKING_OP)
665 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
666 else {
667 cERROR(1, ("unknown timeout flag %d", long_op));
668 rc = -EIO;
669 goto out;
672 if (signal_pending(current)) {
673 /* if signal pending do not hold up user for full smb timeout
674 but we still give response a chance to complete */
675 timeout = 2 * HZ;
678 /* No user interrupts in wait - wreaks havoc with performance */
679 wait_for_response(ses, midQ, timeout, 10 * HZ);
681 spin_lock(&GlobalMid_Lock);
682 if (midQ->resp_buf == NULL) {
683 cERROR(1, ("No response for cmd %d mid %d",
684 midQ->command, midQ->mid));
685 if (midQ->midState == MID_REQUEST_SUBMITTED) {
686 if (ses->server->tcpStatus == CifsExiting)
687 rc = -EHOSTDOWN;
688 else {
689 ses->server->tcpStatus = CifsNeedReconnect;
690 midQ->midState = MID_RETRY_NEEDED;
694 if (rc != -EHOSTDOWN) {
695 if (midQ->midState == MID_RETRY_NEEDED) {
696 rc = -EAGAIN;
697 cFYI(1, ("marking request for retry"));
698 } else {
699 rc = -EIO;
702 spin_unlock(&GlobalMid_Lock);
703 DeleteMidQEntry(midQ);
704 /* Update # of requests on wire to server */
705 atomic_dec(&ses->server->inFlight);
706 wake_up(&ses->server->request_q);
707 return rc;
710 spin_unlock(&GlobalMid_Lock);
711 receive_len = midQ->resp_buf->smb_buf_length;
713 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
714 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
715 receive_len, xid));
716 rc = -EIO;
717 goto out;
720 /* rcvd frame is ok */
722 if (midQ->resp_buf && out_buf
723 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
724 out_buf->smb_buf_length = receive_len;
725 memcpy((char *)out_buf + 4,
726 (char *)midQ->resp_buf + 4,
727 receive_len);
729 dump_smb(out_buf, 92);
730 /* convert the length into a more usable form */
731 if ((receive_len > 24) &&
732 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
733 SECMODE_SIGN_ENABLED))) {
734 rc = cifs_verify_signature(out_buf,
735 &ses->server->mac_signing_key,
736 midQ->sequence_number+1);
737 if (rc) {
738 cERROR(1, ("Unexpected SMB signature"));
739 /* BB FIXME add code to kill session */
743 *pbytes_returned = out_buf->smb_buf_length;
745 /* BB special case reconnect tid and uid here? */
746 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
748 /* convert ByteCount if necessary */
749 if (receive_len >= sizeof(struct smb_hdr) - 4
750 /* do not count RFC1001 header */ +
751 (2 * out_buf->WordCount) + 2 /* bcc */ )
752 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
753 } else {
754 rc = -EIO;
755 cERROR(1, ("Bad MID state?"));
758 out:
759 DeleteMidQEntry(midQ);
760 atomic_dec(&ses->server->inFlight);
761 wake_up(&ses->server->request_q);
763 return rc;
766 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
768 static int
769 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
770 struct mid_q_entry *midQ)
772 int rc = 0;
773 struct cifsSesInfo *ses = tcon->ses;
774 __u16 mid = in_buf->Mid;
776 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
777 in_buf->Mid = mid;
778 mutex_lock(&ses->server->srv_mutex);
779 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
780 if (rc) {
781 mutex_unlock(&ses->server->srv_mutex);
782 return rc;
784 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
785 mutex_unlock(&ses->server->srv_mutex);
786 return rc;
789 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
790 blocking lock to return. */
792 static int
793 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
794 struct smb_hdr *in_buf,
795 struct smb_hdr *out_buf)
797 int bytes_returned;
798 struct cifsSesInfo *ses = tcon->ses;
799 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
801 /* We just modify the current in_buf to change
802 the type of lock from LOCKING_ANDX_SHARED_LOCK
803 or LOCKING_ANDX_EXCLUSIVE_LOCK to
804 LOCKING_ANDX_CANCEL_LOCK. */
806 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
807 pSMB->Timeout = 0;
808 pSMB->hdr.Mid = GetNextMid(ses->server);
810 return SendReceive(xid, ses, in_buf, out_buf,
811 &bytes_returned, CIFS_STD_OP);
815 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
816 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
817 int *pbytes_returned)
819 int rc = 0;
820 int rstart = 0;
821 unsigned int receive_len;
822 struct mid_q_entry *midQ;
823 struct cifsSesInfo *ses;
825 if (tcon == NULL || tcon->ses == NULL) {
826 cERROR(1, ("Null smb session"));
827 return -EIO;
829 ses = tcon->ses;
831 if (ses->server == NULL) {
832 cERROR(1, ("Null tcp session"));
833 return -EIO;
836 if (ses->server->tcpStatus == CifsExiting)
837 return -ENOENT;
839 /* Ensure that we do not send more than 50 overlapping requests
840 to the same server. We may make this configurable later or
841 use ses->maxReq */
843 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
844 cERROR(1, ("Illegal length, greater than maximum frame, %d",
845 in_buf->smb_buf_length));
846 return -EIO;
849 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
850 if (rc)
851 return rc;
853 /* make sure that we sign in the same order that we send on this socket
854 and avoid races inside tcp sendmsg code that could cause corruption
855 of smb data */
857 mutex_lock(&ses->server->srv_mutex);
859 rc = allocate_mid(ses, in_buf, &midQ);
860 if (rc) {
861 mutex_unlock(&ses->server->srv_mutex);
862 return rc;
865 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
866 if (rc) {
867 DeleteMidQEntry(midQ);
868 mutex_unlock(&ses->server->srv_mutex);
869 return rc;
872 midQ->midState = MID_REQUEST_SUBMITTED;
873 #ifdef CONFIG_CIFS_STATS2
874 atomic_inc(&ses->server->inSend);
875 #endif
876 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
877 #ifdef CONFIG_CIFS_STATS2
878 atomic_dec(&ses->server->inSend);
879 midQ->when_sent = jiffies;
880 #endif
881 mutex_unlock(&ses->server->srv_mutex);
883 if (rc < 0) {
884 DeleteMidQEntry(midQ);
885 return rc;
888 /* Wait for a reply - allow signals to interrupt. */
889 rc = wait_event_interruptible(ses->server->response_q,
890 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
891 ((ses->server->tcpStatus != CifsGood) &&
892 (ses->server->tcpStatus != CifsNew)));
894 /* Were we interrupted by a signal ? */
895 if ((rc == -ERESTARTSYS) &&
896 (midQ->midState == MID_REQUEST_SUBMITTED) &&
897 ((ses->server->tcpStatus == CifsGood) ||
898 (ses->server->tcpStatus == CifsNew))) {
900 if (in_buf->Command == SMB_COM_TRANSACTION2) {
901 /* POSIX lock. We send a NT_CANCEL SMB to cause the
902 blocking lock to return. */
904 rc = send_nt_cancel(tcon, in_buf, midQ);
905 if (rc) {
906 DeleteMidQEntry(midQ);
907 return rc;
909 } else {
910 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
911 to cause the blocking lock to return. */
913 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
915 /* If we get -ENOLCK back the lock may have
916 already been removed. Don't exit in this case. */
917 if (rc && rc != -ENOLCK) {
918 DeleteMidQEntry(midQ);
919 return rc;
923 /* Wait 5 seconds for the response. */
924 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
925 /* We got the response - restart system call. */
926 rstart = 1;
930 spin_lock(&GlobalMid_Lock);
931 if (midQ->resp_buf) {
932 spin_unlock(&GlobalMid_Lock);
933 receive_len = midQ->resp_buf->smb_buf_length;
934 } else {
935 cERROR(1, ("No response for cmd %d mid %d",
936 midQ->command, midQ->mid));
937 if (midQ->midState == MID_REQUEST_SUBMITTED) {
938 if (ses->server->tcpStatus == CifsExiting)
939 rc = -EHOSTDOWN;
940 else {
941 ses->server->tcpStatus = CifsNeedReconnect;
942 midQ->midState = MID_RETRY_NEEDED;
946 if (rc != -EHOSTDOWN) {
947 if (midQ->midState == MID_RETRY_NEEDED) {
948 rc = -EAGAIN;
949 cFYI(1, ("marking request for retry"));
950 } else {
951 rc = -EIO;
954 spin_unlock(&GlobalMid_Lock);
955 DeleteMidQEntry(midQ);
956 return rc;
959 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
960 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
961 receive_len, xid));
962 rc = -EIO;
963 goto out;
966 /* rcvd frame is ok */
968 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
969 rc = -EIO;
970 cERROR(1, ("Bad MID state?"));
971 goto out;
974 out_buf->smb_buf_length = receive_len;
975 memcpy((char *)out_buf + 4,
976 (char *)midQ->resp_buf + 4,
977 receive_len);
979 dump_smb(out_buf, 92);
980 /* convert the length into a more usable form */
981 if ((receive_len > 24) &&
982 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
983 SECMODE_SIGN_ENABLED))) {
984 rc = cifs_verify_signature(out_buf,
985 &ses->server->mac_signing_key,
986 midQ->sequence_number+1);
987 if (rc) {
988 cERROR(1, ("Unexpected SMB signature"));
989 /* BB FIXME add code to kill session */
993 *pbytes_returned = out_buf->smb_buf_length;
995 /* BB special case reconnect tid and uid here? */
996 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
998 /* convert ByteCount if necessary */
999 if (receive_len >= sizeof(struct smb_hdr) - 4
1000 /* do not count RFC1001 header */ +
1001 (2 * out_buf->WordCount) + 2 /* bcc */ )
1002 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1004 out:
1005 DeleteMidQEntry(midQ);
1006 if (rstart && rc == -EACCES)
1007 return -ERESTARTSYS;
1008 return rc;