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
24 #include <linux/list.h>
25 #include <linux/gfp.h>
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>
34 #include "cifsproto.h"
35 #include "cifs_debug.h"
37 extern mempool_t *cifs_mid_poolp;
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;
45 cERROR(1, "Null TCP session in AllocMidQEntry");
49 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
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;
64 atomic_inc(&midCount);
65 temp->midState = MID_REQUEST_ALLOCATED;
70 DeleteMidQEntry(struct mid_q_entry *midEntry)
72 #ifdef CONFIG_CIFS_STATS2
75 midEntry->midState = MID_FREE;
76 atomic_dec(&midCount);
77 if (midEntry->largeBuf)
78 cifs_buf_release(midEntry->resp_buf);
80 cifs_small_buf_release(midEntry->resp_buf);
81 #ifdef CONFIG_CIFS_STATS2
83 /* commands taking longer than one second are indications that
84 something is wrong, unless it is quite a slow link or server */
85 if ((now - midEntry->when_alloc) > HZ) {
86 if ((cifsFYI & CIFS_TIMER) &&
87 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
88 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
89 midEntry->command, midEntry->mid);
90 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
91 now - midEntry->when_alloc,
92 now - midEntry->when_sent,
93 now - midEntry->when_received);
97 mempool_free(midEntry, cifs_mid_poolp);
101 delete_mid(struct mid_q_entry *mid)
103 spin_lock(&GlobalMid_Lock);
104 list_del(&mid->qhead);
105 spin_unlock(&GlobalMid_Lock);
107 DeleteMidQEntry(mid);
111 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
115 struct msghdr smb_msg;
116 struct smb_hdr *smb_buffer = iov[0].iov_base;
117 unsigned int len = iov[0].iov_len;
118 unsigned int total_len;
120 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
121 struct socket *ssocket = server->ssocket;
124 return -ENOTSOCK; /* BB eventually add reconnect code here */
126 smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
127 smb_msg.msg_namelen = sizeof(struct sockaddr);
128 smb_msg.msg_control = NULL;
129 smb_msg.msg_controllen = 0;
130 if (server->noblocksnd)
131 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
133 smb_msg.msg_flags = MSG_NOSIGNAL;
135 /* smb header is converted in header_assemble. bcc and rest of SMB word
136 area, and byte area if necessary, is converted to littleendian in
137 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
138 Flags2 is converted in SendReceive */
142 for (i = 0; i < n_vec; i++)
143 total_len += iov[i].iov_len;
145 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
146 cFYI(1, "Sending smb: total_len %d", total_len);
147 dump_smb(smb_buffer, len);
151 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
152 n_vec - first_vec, total_len);
153 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
155 /* if blocking send we try 3 times, since each can block
156 for 5 seconds. For nonblocking we have to try more
157 but wait increasing amounts of time allowing time for
158 socket to clear. The overall time we wait in either
159 case to send on the socket is about 15 seconds.
160 Similarly we wait for 15 seconds for
161 a response from the server in SendReceive[2]
162 for the server to send a response back for
163 most types of requests (except SMB Write
164 past end of file which can be slow, and
165 blocking lock operations). NFS waits slightly longer
166 than CIFS, but this can make it take longer for
167 nonresponsive servers to be detected and 15 seconds
168 is more than enough time for modern networks to
169 send a packet. In most cases if we fail to send
170 after the retries we will kill the socket and
171 reconnect which may clear the network problem.
173 if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
174 cERROR(1, "sends on sock %p stuck for 15 seconds",
185 if (rc == total_len) {
188 } else if (rc > total_len) {
189 cERROR(1, "sent %d requested %d", rc, total_len);
193 /* should never happen, letting socket clear before
194 retrying is our only obvious option here */
195 cERROR(1, "tcp sent no data");
200 /* the line below resets i */
201 for (i = first_vec; i < n_vec; i++) {
202 if (iov[i].iov_len) {
203 if (rc > iov[i].iov_len) {
204 rc -= iov[i].iov_len;
207 iov[i].iov_base += rc;
208 iov[i].iov_len -= rc;
214 i = 0; /* in case we get ENOSPC on the next send */
217 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
218 cFYI(1, "partial send (%d remaining), terminating session",
220 /* If we have only sent part of an SMB then the next SMB
221 could be taken as the remainder of this one. We need
222 to kill the socket so the server throws away the partial
224 server->tcpStatus = CifsNeedReconnect;
228 cERROR(1, "Error %d sending data on socket to server", rc);
232 /* Don't want to modify the buffer as a
233 side effect of this call. */
234 smb_buffer->smb_buf_length = smb_buf_length;
240 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
241 unsigned int smb_buf_length)
245 iov.iov_base = smb_buffer;
246 iov.iov_len = smb_buf_length + 4;
248 return smb_sendv(server, &iov, 1);
251 static int wait_for_free_request(struct TCP_Server_Info *server,
254 if (long_op == CIFS_ASYNC_OP) {
255 /* oplock breaks must not be held up */
256 atomic_inc(&server->inFlight);
260 spin_lock(&GlobalMid_Lock);
262 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
263 spin_unlock(&GlobalMid_Lock);
264 #ifdef CONFIG_CIFS_STATS2
265 atomic_inc(&server->num_waiters);
267 wait_event(server->request_q,
268 atomic_read(&server->inFlight)
270 #ifdef CONFIG_CIFS_STATS2
271 atomic_dec(&server->num_waiters);
273 spin_lock(&GlobalMid_Lock);
275 if (server->tcpStatus == CifsExiting) {
276 spin_unlock(&GlobalMid_Lock);
280 /* can not count locking commands against total
281 as they are allowed to block on server */
283 /* update # of requests on the wire to server */
284 if (long_op != CIFS_BLOCKING_OP)
285 atomic_inc(&server->inFlight);
286 spin_unlock(&GlobalMid_Lock);
293 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
294 struct mid_q_entry **ppmidQ)
296 if (ses->server->tcpStatus == CifsExiting) {
300 if (ses->server->tcpStatus == CifsNeedReconnect) {
301 cFYI(1, "tcp session dead - return to caller to retry");
305 if (ses->status != CifsGood) {
306 /* check if SMB session is bad because we are setting it up */
307 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
308 (in_buf->Command != SMB_COM_NEGOTIATE))
310 /* else ok - we are setting up session */
312 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
315 spin_lock(&GlobalMid_Lock);
316 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
317 spin_unlock(&GlobalMid_Lock);
322 wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
326 error = wait_event_killable(server->response_q,
327 midQ->midState != MID_REQUEST_SUBMITTED);
337 * Send an SMB Request. No response info (other than return code)
338 * needs to be parsed.
340 * flags indicate the type of request buffer and how long to wait
341 * and whether to log NT STATUS code (error) before mapping it to POSIX error
345 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
346 struct smb_hdr *in_buf, int flags)
352 iov[0].iov_base = (char *)in_buf;
353 iov[0].iov_len = in_buf->smb_buf_length + 4;
354 flags |= CIFS_NO_RESP;
355 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
356 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
362 sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
366 spin_lock(&GlobalMid_Lock);
369 spin_unlock(&GlobalMid_Lock);
373 cERROR(1, "No response to cmd %d mid %d", mid->command, mid->mid);
374 if (mid->midState == MID_REQUEST_SUBMITTED) {
375 if (server->tcpStatus == CifsExiting)
378 server->tcpStatus = CifsNeedReconnect;
379 mid->midState = MID_RETRY_NEEDED;
383 if (rc != -EHOSTDOWN) {
384 if (mid->midState == MID_RETRY_NEEDED) {
386 cFYI(1, "marking request for retry");
391 spin_unlock(&GlobalMid_Lock);
398 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
399 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
404 unsigned int receive_len;
405 struct mid_q_entry *midQ;
406 struct smb_hdr *in_buf = iov[0].iov_base;
408 long_op = flags & CIFS_TIMEOUT_MASK;
410 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
412 if ((ses == NULL) || (ses->server == NULL)) {
413 cifs_small_buf_release(in_buf);
414 cERROR(1, "Null session");
418 if (ses->server->tcpStatus == CifsExiting) {
419 cifs_small_buf_release(in_buf);
423 /* Ensure that we do not send more than 50 overlapping requests
424 to the same server. We may make this configurable later or
427 rc = wait_for_free_request(ses->server, long_op);
429 cifs_small_buf_release(in_buf);
433 /* make sure that we sign in the same order that we send on this socket
434 and avoid races inside tcp sendmsg code that could cause corruption
437 mutex_lock(&ses->server->srv_mutex);
439 rc = allocate_mid(ses, in_buf, &midQ);
441 mutex_unlock(&ses->server->srv_mutex);
442 cifs_small_buf_release(in_buf);
443 /* Update # of requests on wire to server */
444 atomic_dec(&ses->server->inFlight);
445 wake_up(&ses->server->request_q);
448 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
450 mutex_unlock(&ses->server->srv_mutex);
451 cifs_small_buf_release(in_buf);
455 midQ->midState = MID_REQUEST_SUBMITTED;
456 #ifdef CONFIG_CIFS_STATS2
457 atomic_inc(&ses->server->inSend);
459 rc = smb_sendv(ses->server, iov, n_vec);
460 #ifdef CONFIG_CIFS_STATS2
461 atomic_dec(&ses->server->inSend);
462 midQ->when_sent = jiffies;
465 mutex_unlock(&ses->server->srv_mutex);
466 cifs_small_buf_release(in_buf);
471 if (long_op == CIFS_ASYNC_OP)
474 rc = wait_for_response(ses->server, midQ);
478 rc = sync_mid_result(midQ, ses->server);
480 atomic_dec(&ses->server->inFlight);
481 wake_up(&ses->server->request_q);
485 receive_len = midQ->resp_buf->smb_buf_length;
487 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
488 cERROR(1, "Frame too large received. Length: %d Xid: %d",
494 /* rcvd frame is ok */
496 if (midQ->resp_buf &&
497 (midQ->midState == MID_RESPONSE_RECEIVED)) {
499 iov[0].iov_base = (char *)midQ->resp_buf;
501 *pRespBufType = CIFS_LARGE_BUFFER;
503 *pRespBufType = CIFS_SMALL_BUFFER;
504 iov[0].iov_len = receive_len + 4;
506 dump_smb(midQ->resp_buf, 80);
507 /* convert the length into a more usable form */
508 if ((receive_len > 24) &&
509 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
510 SECMODE_SIGN_ENABLED))) {
511 rc = cifs_verify_signature(midQ->resp_buf,
513 midQ->sequence_number+1);
515 cERROR(1, "Unexpected SMB signature");
516 /* BB FIXME add code to kill session */
520 /* BB special case reconnect tid and uid here? */
521 rc = map_smb_to_linux_error(midQ->resp_buf,
522 flags & CIFS_LOG_ERROR);
524 /* convert ByteCount if necessary */
525 if (receive_len >= sizeof(struct smb_hdr) - 4
526 /* do not count RFC1001 header */ +
527 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
528 BCC(midQ->resp_buf) =
529 le16_to_cpu(BCC_LE(midQ->resp_buf));
530 if ((flags & CIFS_NO_RESP) == 0)
531 midQ->resp_buf = NULL; /* mark it so buf will
536 cFYI(1, "Bad MID state?");
541 atomic_dec(&ses->server->inFlight);
542 wake_up(&ses->server->request_q);
548 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
549 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
550 int *pbytes_returned, const int long_op)
553 unsigned int receive_len;
554 struct mid_q_entry *midQ;
557 cERROR(1, "Null smb session");
560 if (ses->server == NULL) {
561 cERROR(1, "Null tcp session");
565 if (ses->server->tcpStatus == CifsExiting)
568 /* Ensure that we do not send more than 50 overlapping requests
569 to the same server. We may make this configurable later or
572 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
573 cERROR(1, "Illegal length, greater than maximum frame, %d",
574 in_buf->smb_buf_length);
578 rc = wait_for_free_request(ses->server, long_op);
582 /* make sure that we sign in the same order that we send on this socket
583 and avoid races inside tcp sendmsg code that could cause corruption
586 mutex_lock(&ses->server->srv_mutex);
588 rc = allocate_mid(ses, in_buf, &midQ);
590 mutex_unlock(&ses->server->srv_mutex);
591 /* Update # of requests on wire to server */
592 atomic_dec(&ses->server->inFlight);
593 wake_up(&ses->server->request_q);
597 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
599 mutex_unlock(&ses->server->srv_mutex);
603 midQ->midState = MID_REQUEST_SUBMITTED;
604 #ifdef CONFIG_CIFS_STATS2
605 atomic_inc(&ses->server->inSend);
607 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
608 #ifdef CONFIG_CIFS_STATS2
609 atomic_dec(&ses->server->inSend);
610 midQ->when_sent = jiffies;
612 mutex_unlock(&ses->server->srv_mutex);
617 if (long_op == CIFS_ASYNC_OP)
620 rc = wait_for_response(ses->server, midQ);
624 rc = sync_mid_result(midQ, ses->server);
626 atomic_dec(&ses->server->inFlight);
627 wake_up(&ses->server->request_q);
631 receive_len = midQ->resp_buf->smb_buf_length;
633 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
634 cERROR(1, "Frame too large received. Length: %d Xid: %d",
640 /* rcvd frame is ok */
642 if (midQ->resp_buf && out_buf
643 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
644 out_buf->smb_buf_length = receive_len;
645 memcpy((char *)out_buf + 4,
646 (char *)midQ->resp_buf + 4,
649 dump_smb(out_buf, 92);
650 /* convert the length into a more usable form */
651 if ((receive_len > 24) &&
652 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
653 SECMODE_SIGN_ENABLED))) {
654 rc = cifs_verify_signature(out_buf,
656 midQ->sequence_number+1);
658 cERROR(1, "Unexpected SMB signature");
659 /* BB FIXME add code to kill session */
663 *pbytes_returned = out_buf->smb_buf_length;
665 /* BB special case reconnect tid and uid here? */
666 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
668 /* convert ByteCount if necessary */
669 if (receive_len >= sizeof(struct smb_hdr) - 4
670 /* do not count RFC1001 header */ +
671 (2 * out_buf->WordCount) + 2 /* bcc */ )
672 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
675 cERROR(1, "Bad MID state?");
680 atomic_dec(&ses->server->inFlight);
681 wake_up(&ses->server->request_q);
686 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
689 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
690 struct mid_q_entry *midQ)
693 struct cifsSesInfo *ses = tcon->ses;
694 __u16 mid = in_buf->Mid;
696 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
698 mutex_lock(&ses->server->srv_mutex);
699 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
701 mutex_unlock(&ses->server->srv_mutex);
704 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
705 mutex_unlock(&ses->server->srv_mutex);
709 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
710 blocking lock to return. */
713 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
714 struct smb_hdr *in_buf,
715 struct smb_hdr *out_buf)
718 struct cifsSesInfo *ses = tcon->ses;
719 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
721 /* We just modify the current in_buf to change
722 the type of lock from LOCKING_ANDX_SHARED_LOCK
723 or LOCKING_ANDX_EXCLUSIVE_LOCK to
724 LOCKING_ANDX_CANCEL_LOCK. */
726 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
728 pSMB->hdr.Mid = GetNextMid(ses->server);
730 return SendReceive(xid, ses, in_buf, out_buf,
731 &bytes_returned, CIFS_STD_OP);
735 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
736 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
737 int *pbytes_returned)
741 unsigned int receive_len;
742 struct mid_q_entry *midQ;
743 struct cifsSesInfo *ses;
745 if (tcon == NULL || tcon->ses == NULL) {
746 cERROR(1, "Null smb session");
751 if (ses->server == NULL) {
752 cERROR(1, "Null tcp session");
756 if (ses->server->tcpStatus == CifsExiting)
759 /* Ensure that we do not send more than 50 overlapping requests
760 to the same server. We may make this configurable later or
763 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
764 cERROR(1, "Illegal length, greater than maximum frame, %d",
765 in_buf->smb_buf_length);
769 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
773 /* make sure that we sign in the same order that we send on this socket
774 and avoid races inside tcp sendmsg code that could cause corruption
777 mutex_lock(&ses->server->srv_mutex);
779 rc = allocate_mid(ses, in_buf, &midQ);
781 mutex_unlock(&ses->server->srv_mutex);
785 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
788 mutex_unlock(&ses->server->srv_mutex);
792 midQ->midState = MID_REQUEST_SUBMITTED;
793 #ifdef CONFIG_CIFS_STATS2
794 atomic_inc(&ses->server->inSend);
796 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
797 #ifdef CONFIG_CIFS_STATS2
798 atomic_dec(&ses->server->inSend);
799 midQ->when_sent = jiffies;
801 mutex_unlock(&ses->server->srv_mutex);
808 /* Wait for a reply - allow signals to interrupt. */
809 rc = wait_event_interruptible(ses->server->response_q,
810 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
811 ((ses->server->tcpStatus != CifsGood) &&
812 (ses->server->tcpStatus != CifsNew)));
814 /* Were we interrupted by a signal ? */
815 if ((rc == -ERESTARTSYS) &&
816 (midQ->midState == MID_REQUEST_SUBMITTED) &&
817 ((ses->server->tcpStatus == CifsGood) ||
818 (ses->server->tcpStatus == CifsNew))) {
820 if (in_buf->Command == SMB_COM_TRANSACTION2) {
821 /* POSIX lock. We send a NT_CANCEL SMB to cause the
822 blocking lock to return. */
824 rc = send_nt_cancel(tcon, in_buf, midQ);
830 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
831 to cause the blocking lock to return. */
833 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
835 /* If we get -ENOLCK back the lock may have
836 already been removed. Don't exit in this case. */
837 if (rc && rc != -ENOLCK) {
843 if (wait_for_response(ses->server, midQ) == 0) {
844 /* We got the response - restart system call. */
849 rc = sync_mid_result(midQ, ses->server);
853 receive_len = midQ->resp_buf->smb_buf_length;
854 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
855 cERROR(1, "Frame too large received. Length: %d Xid: %d",
861 /* rcvd frame is ok */
863 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
865 cERROR(1, "Bad MID state?");
869 out_buf->smb_buf_length = receive_len;
870 memcpy((char *)out_buf + 4,
871 (char *)midQ->resp_buf + 4,
874 dump_smb(out_buf, 92);
875 /* convert the length into a more usable form */
876 if ((receive_len > 24) &&
877 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
878 SECMODE_SIGN_ENABLED))) {
879 rc = cifs_verify_signature(out_buf,
881 midQ->sequence_number+1);
883 cERROR(1, "Unexpected SMB signature");
884 /* BB FIXME add code to kill session */
888 *pbytes_returned = out_buf->smb_buf_length;
890 /* BB special case reconnect tid and uid here? */
891 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
893 /* convert ByteCount if necessary */
894 if (receive_len >= sizeof(struct smb_hdr) - 4
895 /* do not count RFC1001 header */ +
896 (2 * out_buf->WordCount) + 2 /* bcc */ )
897 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
901 if (rstart && rc == -EACCES)