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/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>
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 cifsSesInfo
*ses
)
42 struct mid_q_entry
*temp
;
45 cERROR(1, ("Null session passed in to AllocMidQEntry"));
48 if (ses
->server
== NULL
) {
49 cERROR(1, ("Null TCP session in AllocMidQEntry"));
53 temp
= (struct mid_q_entry
*) mempool_alloc(cifs_mid_poolp
,
54 GFP_KERNEL
| GFP_NOFS
);
58 memset(temp
, 0, sizeof(struct mid_q_entry
));
59 temp
->mid
= smb_buffer
->Mid
; /* always LE */
60 temp
->pid
= current
->pid
;
61 temp
->command
= smb_buffer
->Command
;
62 cFYI(1, ("For smb_command %d", temp
->command
));
63 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
64 /* when mid allocated can be before when sent */
65 temp
->when_alloc
= jiffies
;
70 spin_lock(&GlobalMid_Lock
);
71 list_add_tail(&temp
->qhead
, &ses
->server
->pending_mid_q
);
72 atomic_inc(&midCount
);
73 temp
->midState
= MID_REQUEST_ALLOCATED
;
74 spin_unlock(&GlobalMid_Lock
);
79 DeleteMidQEntry(struct mid_q_entry
*midEntry
)
81 #ifdef CONFIG_CIFS_STATS2
84 spin_lock(&GlobalMid_Lock
);
85 midEntry
->midState
= MID_FREE
;
86 list_del(&midEntry
->qhead
);
87 atomic_dec(&midCount
);
88 spin_unlock(&GlobalMid_Lock
);
89 if (midEntry
->largeBuf
)
90 cifs_buf_release(midEntry
->resp_buf
);
92 cifs_small_buf_release(midEntry
->resp_buf
);
93 #ifdef CONFIG_CIFS_STATS2
95 /* commands taking longer than one second are indications that
96 something is wrong, unless it is quite a slow link or server */
97 if ((now
- midEntry
->when_alloc
) > HZ
) {
98 if ((cifsFYI
& CIFS_TIMER
) &&
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
);
109 mempool_free(midEntry
, cifs_mid_poolp
);
112 struct oplock_q_entry
*
113 AllocOplockQEntry(struct inode
*pinode
, __u16 fid
, struct cifsTconInfo
*tcon
)
115 struct oplock_q_entry
*temp
;
116 if ((pinode
== NULL
) || (tcon
== NULL
)) {
117 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
120 temp
= (struct oplock_q_entry
*) kmem_cache_alloc(cifs_oplock_cachep
,
125 temp
->pinode
= pinode
;
128 spin_lock(&GlobalMid_Lock
);
129 list_add_tail(&temp
->qhead
, &GlobalOplock_Q
);
130 spin_unlock(&GlobalMid_Lock
);
136 void DeleteOplockQEntry(struct oplock_q_entry
*oplockEntry
)
138 spin_lock(&GlobalMid_Lock
);
139 /* should we check if list empty first? */
140 list_del(&oplockEntry
->qhead
);
141 spin_unlock(&GlobalMid_Lock
);
142 kmem_cache_free(cifs_oplock_cachep
, oplockEntry
);
146 void DeleteTconOplockQEntries(struct cifsTconInfo
*tcon
)
148 struct oplock_q_entry
*temp
;
153 spin_lock(&GlobalMid_Lock
);
154 list_for_each_entry(temp
, &GlobalOplock_Q
, qhead
) {
155 if ((temp
->tcon
) && (temp
->tcon
== tcon
)) {
156 list_del(&temp
->qhead
);
157 kmem_cache_free(cifs_oplock_cachep
, temp
);
160 spin_unlock(&GlobalMid_Lock
);
164 smb_send(struct socket
*ssocket
, struct smb_hdr
*smb_buffer
,
165 unsigned int smb_buf_length
, struct sockaddr
*sin
)
169 struct msghdr smb_msg
;
171 unsigned len
= smb_buf_length
+ 4;
174 return -ENOTSOCK
; /* BB eventually add reconnect code here */
175 iov
.iov_base
= smb_buffer
;
178 smb_msg
.msg_name
= sin
;
179 smb_msg
.msg_namelen
= sizeof(struct sockaddr
);
180 smb_msg
.msg_control
= NULL
;
181 smb_msg
.msg_controllen
= 0;
182 smb_msg
.msg_flags
= MSG_DONTWAIT
+ MSG_NOSIGNAL
; /* BB add more flags?*/
184 /* smb header is converted in header_assemble. bcc and rest of SMB word
185 area, and byte area if necessary, is converted to littleendian in
186 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
187 Flags2 is converted in SendReceive */
189 smb_buffer
->smb_buf_length
= cpu_to_be32(smb_buffer
->smb_buf_length
);
190 cFYI(1, ("Sending smb of length %d", smb_buf_length
));
191 dump_smb(smb_buffer
, len
);
194 rc
= kernel_sendmsg(ssocket
, &smb_msg
, &iov
, 1, len
);
195 if ((rc
== -ENOSPC
) || (rc
== -EAGAIN
)) {
197 /* smaller timeout here than send2 since smaller size */
198 /* Although it may not be required, this also is smaller
202 ("sends on sock %p stuck for 7 seconds",
213 i
= 0; /* reset i after each successful send */
220 cERROR(1, ("Error %d sending data on socket to server", rc
));
225 /* Don't want to modify the buffer as a
226 side effect of this call. */
227 smb_buffer
->smb_buf_length
= smb_buf_length
;
233 smb_send2(struct socket
*ssocket
, struct kvec
*iov
, int n_vec
,
234 struct sockaddr
*sin
)
238 struct msghdr smb_msg
;
239 struct smb_hdr
*smb_buffer
= iov
[0].iov_base
;
240 unsigned int len
= iov
[0].iov_len
;
241 unsigned int total_len
;
243 unsigned int smb_buf_length
= smb_buffer
->smb_buf_length
;
246 return -ENOTSOCK
; /* BB eventually add reconnect code here */
248 smb_msg
.msg_name
= sin
;
249 smb_msg
.msg_namelen
= sizeof(struct sockaddr
);
250 smb_msg
.msg_control
= NULL
;
251 smb_msg
.msg_controllen
= 0;
252 smb_msg
.msg_flags
= MSG_DONTWAIT
+ MSG_NOSIGNAL
; /* BB add more flags?*/
254 /* smb header is converted in header_assemble. bcc and rest of SMB word
255 area, and byte area if necessary, is converted to littleendian in
256 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
257 Flags2 is converted in SendReceive */
261 for (i
= 0; i
< n_vec
; i
++)
262 total_len
+= iov
[i
].iov_len
;
264 smb_buffer
->smb_buf_length
= cpu_to_be32(smb_buffer
->smb_buf_length
);
265 cFYI(1, ("Sending smb: total_len %d", total_len
));
266 dump_smb(smb_buffer
, len
);
269 rc
= kernel_sendmsg(ssocket
, &smb_msg
, &iov
[first_vec
],
270 n_vec
- first_vec
, total_len
);
271 if ((rc
== -ENOSPC
) || (rc
== -EAGAIN
)) {
275 ("sends on sock %p stuck for 15 seconds",
286 if (rc
>= total_len
) {
287 WARN_ON(rc
> total_len
);
291 /* should never happen, letting socket clear before
292 retrying is our only obvious option here */
293 cERROR(1, ("tcp sent no data"));
298 /* the line below resets i */
299 for (i
= first_vec
; i
< n_vec
; i
++) {
300 if (iov
[i
].iov_len
) {
301 if (rc
> iov
[i
].iov_len
) {
302 rc
-= iov
[i
].iov_len
;
305 iov
[i
].iov_base
+= rc
;
306 iov
[i
].iov_len
-= rc
;
312 i
= 0; /* in case we get ENOSPC on the next send */
316 cERROR(1, ("Error %d sending data on socket to server", rc
));
320 /* Don't want to modify the buffer as a
321 side effect of this call. */
322 smb_buffer
->smb_buf_length
= smb_buf_length
;
327 static int wait_for_free_request(struct cifsSesInfo
*ses
, const int long_op
)
329 if (long_op
== CIFS_ASYNC_OP
) {
330 /* oplock breaks must not be held up */
331 atomic_inc(&ses
->server
->inFlight
);
333 spin_lock(&GlobalMid_Lock
);
335 if (atomic_read(&ses
->server
->inFlight
) >=
337 spin_unlock(&GlobalMid_Lock
);
338 #ifdef CONFIG_CIFS_STATS2
339 atomic_inc(&ses
->server
->num_waiters
);
341 wait_event(ses
->server
->request_q
,
342 atomic_read(&ses
->server
->inFlight
)
344 #ifdef CONFIG_CIFS_STATS2
345 atomic_dec(&ses
->server
->num_waiters
);
347 spin_lock(&GlobalMid_Lock
);
349 if (ses
->server
->tcpStatus
== CifsExiting
) {
350 spin_unlock(&GlobalMid_Lock
);
354 /* can not count locking commands against total
355 as they are allowed to block on server */
357 /* update # of requests on the wire to server */
358 if (long_op
!= CIFS_BLOCKING_OP
)
359 atomic_inc(&ses
->server
->inFlight
);
360 spin_unlock(&GlobalMid_Lock
);
368 static int allocate_mid(struct cifsSesInfo
*ses
, struct smb_hdr
*in_buf
,
369 struct mid_q_entry
**ppmidQ
)
371 if (ses
->server
->tcpStatus
== CifsExiting
) {
373 } else if (ses
->server
->tcpStatus
== CifsNeedReconnect
) {
374 cFYI(1, ("tcp session dead - return to caller to retry"));
376 } else if (ses
->status
!= CifsGood
) {
377 /* check if SMB session is bad because we are setting it up */
378 if ((in_buf
->Command
!= SMB_COM_SESSION_SETUP_ANDX
) &&
379 (in_buf
->Command
!= SMB_COM_NEGOTIATE
))
381 /* else ok - we are setting up session */
383 *ppmidQ
= AllocMidQEntry(in_buf
, ses
);
389 static int wait_for_response(struct cifsSesInfo
*ses
,
390 struct mid_q_entry
*midQ
,
391 unsigned long timeout
,
392 unsigned long time_to_wait
)
394 unsigned long curr_timeout
;
397 curr_timeout
= timeout
+ jiffies
;
398 wait_event(ses
->server
->response_q
,
399 (!(midQ
->midState
== MID_REQUEST_SUBMITTED
)) ||
400 time_after(jiffies
, curr_timeout
) ||
401 ((ses
->server
->tcpStatus
!= CifsGood
) &&
402 (ses
->server
->tcpStatus
!= CifsNew
)));
404 if (time_after(jiffies
, curr_timeout
) &&
405 (midQ
->midState
== MID_REQUEST_SUBMITTED
) &&
406 ((ses
->server
->tcpStatus
== CifsGood
) ||
407 (ses
->server
->tcpStatus
== CifsNew
))) {
411 /* We timed out. Is the server still
413 spin_lock(&GlobalMid_Lock
);
414 lrt
= ses
->server
->lstrp
;
415 spin_unlock(&GlobalMid_Lock
);
417 /* Calculate time_to_wait past last receive time.
418 Although we prefer not to time out if the
419 server is still responding - we will time
420 out if the server takes more than 15 (or 45
421 or 180) seconds to respond to this request
422 and has not responded to any request from
423 other threads on the client within 10 seconds */
425 if (time_after(jiffies
, lrt
)) {
426 /* No replies for time_to_wait. */
427 cERROR(1, ("server not responding"));
439 * Send an SMB Request. No response info (other than return code)
440 * needs to be parsed.
442 * flags indicate the type of request buffer and how long to wait
443 * and whether to log NT STATUS code (error) before mapping it to POSIX error
447 SendReceiveNoRsp(const unsigned int xid
, struct cifsSesInfo
*ses
,
448 struct smb_hdr
*in_buf
, int flags
)
454 iov
[0].iov_base
= (char *)in_buf
;
455 iov
[0].iov_len
= in_buf
->smb_buf_length
+ 4;
456 flags
|= CIFS_NO_RESP
;
457 rc
= SendReceive2(xid
, ses
, iov
, 1, &resp_buf_type
, flags
);
458 cFYI(DBG2
, ("SendRcvNoRsp flags %d rc %d", flags
, rc
));
464 SendReceive2(const unsigned int xid
, struct cifsSesInfo
*ses
,
465 struct kvec
*iov
, int n_vec
, int *pRespBufType
/* ret */,
470 unsigned int receive_len
;
471 unsigned long timeout
;
472 struct mid_q_entry
*midQ
;
473 struct smb_hdr
*in_buf
= iov
[0].iov_base
;
475 long_op
= flags
& CIFS_TIMEOUT_MASK
;
477 *pRespBufType
= CIFS_NO_BUFFER
; /* no response buf yet */
479 if ((ses
== NULL
) || (ses
->server
== NULL
)) {
480 cifs_small_buf_release(in_buf
);
481 cERROR(1, ("Null session"));
485 if (ses
->server
->tcpStatus
== CifsExiting
) {
486 cifs_small_buf_release(in_buf
);
490 /* Ensure that we do not send more than 50 overlapping requests
491 to the same server. We may make this configurable later or
494 rc
= wait_for_free_request(ses
, long_op
);
496 cifs_small_buf_release(in_buf
);
500 /* make sure that we sign in the same order that we send on this socket
501 and avoid races inside tcp sendmsg code that could cause corruption
504 down(&ses
->server
->tcpSem
);
506 rc
= allocate_mid(ses
, in_buf
, &midQ
);
508 up(&ses
->server
->tcpSem
);
509 cifs_small_buf_release(in_buf
);
510 /* Update # of requests on wire to server */
511 atomic_dec(&ses
->server
->inFlight
);
512 wake_up(&ses
->server
->request_q
);
515 rc
= cifs_sign_smb2(iov
, n_vec
, ses
->server
, &midQ
->sequence_number
);
517 midQ
->midState
= MID_REQUEST_SUBMITTED
;
518 #ifdef CONFIG_CIFS_STATS2
519 atomic_inc(&ses
->server
->inSend
);
521 rc
= smb_send2(ses
->server
->ssocket
, iov
, n_vec
,
522 (struct sockaddr
*) &(ses
->server
->addr
.sockAddr
));
523 #ifdef CONFIG_CIFS_STATS2
524 atomic_dec(&ses
->server
->inSend
);
525 midQ
->when_sent
= jiffies
;
528 up(&ses
->server
->tcpSem
);
529 cifs_small_buf_release(in_buf
);
534 if (long_op
== CIFS_STD_OP
)
536 else if (long_op
== CIFS_VLONG_OP
) /* e.g. slow writes past EOF */
538 else if (long_op
== CIFS_LONG_OP
)
539 timeout
= 45 * HZ
; /* should be greater than
540 servers oplock break timeout (about 43 seconds) */
541 else if (long_op
== CIFS_ASYNC_OP
)
543 else if (long_op
== CIFS_BLOCKING_OP
)
544 timeout
= 0x7FFFFFFF; /* large, but not so large as to wrap */
546 cERROR(1, ("unknown timeout flag %d", long_op
));
551 /* wait for 15 seconds or until woken up due to response arriving or
552 due to last connection to this server being unmounted */
553 if (signal_pending(current
)) {
554 /* if signal pending do not hold up user for full smb timeout
555 but we still give response a chance to complete */
559 /* No user interrupts in wait - wreaks havoc with performance */
560 wait_for_response(ses
, midQ
, timeout
, 10 * HZ
);
562 spin_lock(&GlobalMid_Lock
);
563 if (midQ
->resp_buf
) {
564 spin_unlock(&GlobalMid_Lock
);
565 receive_len
= midQ
->resp_buf
->smb_buf_length
;
567 cERROR(1, ("No response to cmd %d mid %d",
568 midQ
->command
, midQ
->mid
));
569 if (midQ
->midState
== MID_REQUEST_SUBMITTED
) {
570 if (ses
->server
->tcpStatus
== CifsExiting
)
573 ses
->server
->tcpStatus
= CifsNeedReconnect
;
574 midQ
->midState
= MID_RETRY_NEEDED
;
578 if (rc
!= -EHOSTDOWN
) {
579 if (midQ
->midState
== MID_RETRY_NEEDED
) {
581 cFYI(1, ("marking request for retry"));
586 spin_unlock(&GlobalMid_Lock
);
587 DeleteMidQEntry(midQ
);
588 /* Update # of requests on wire to server */
589 atomic_dec(&ses
->server
->inFlight
);
590 wake_up(&ses
->server
->request_q
);
594 if (receive_len
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
) {
595 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
598 } else { /* rcvd frame is ok */
599 if (midQ
->resp_buf
&&
600 (midQ
->midState
== MID_RESPONSE_RECEIVED
)) {
602 iov
[0].iov_base
= (char *)midQ
->resp_buf
;
604 *pRespBufType
= CIFS_LARGE_BUFFER
;
606 *pRespBufType
= CIFS_SMALL_BUFFER
;
607 iov
[0].iov_len
= receive_len
+ 4;
609 dump_smb(midQ
->resp_buf
, 80);
610 /* convert the length into a more usable form */
611 if ((receive_len
> 24) &&
612 (ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
|
613 SECMODE_SIGN_ENABLED
))) {
614 rc
= cifs_verify_signature(midQ
->resp_buf
,
615 &ses
->server
->mac_signing_key
,
616 midQ
->sequence_number
+1);
618 cERROR(1, ("Unexpected SMB signature"));
619 /* BB FIXME add code to kill session */
623 /* BB special case reconnect tid and uid here? */
624 rc
= map_smb_to_linux_error(midQ
->resp_buf
,
625 flags
& CIFS_LOG_ERROR
);
627 /* convert ByteCount if necessary */
628 if (receive_len
>= sizeof(struct smb_hdr
) - 4
629 /* do not count RFC1001 header */ +
630 (2 * midQ
->resp_buf
->WordCount
) + 2 /* bcc */ )
631 BCC(midQ
->resp_buf
) =
632 le16_to_cpu(BCC_LE(midQ
->resp_buf
));
633 if ((flags
& CIFS_NO_RESP
) == 0)
634 midQ
->resp_buf
= NULL
; /* mark it so buf will
639 cFYI(1, ("Bad MID state?"));
644 DeleteMidQEntry(midQ
);
645 atomic_dec(&ses
->server
->inFlight
);
646 wake_up(&ses
->server
->request_q
);
652 SendReceive(const unsigned int xid
, struct cifsSesInfo
*ses
,
653 struct smb_hdr
*in_buf
, struct smb_hdr
*out_buf
,
654 int *pbytes_returned
, const int long_op
)
657 unsigned int receive_len
;
658 unsigned long timeout
;
659 struct mid_q_entry
*midQ
;
662 cERROR(1, ("Null smb session"));
665 if (ses
->server
== NULL
) {
666 cERROR(1, ("Null tcp session"));
670 if (ses
->server
->tcpStatus
== CifsExiting
)
673 /* Ensure that we do not send more than 50 overlapping requests
674 to the same server. We may make this configurable later or
677 rc
= wait_for_free_request(ses
, long_op
);
681 /* make sure that we sign in the same order that we send on this socket
682 and avoid races inside tcp sendmsg code that could cause corruption
685 down(&ses
->server
->tcpSem
);
687 rc
= allocate_mid(ses
, in_buf
, &midQ
);
689 up(&ses
->server
->tcpSem
);
690 /* Update # of requests on wire to server */
691 atomic_dec(&ses
->server
->inFlight
);
692 wake_up(&ses
->server
->request_q
);
696 if (in_buf
->smb_buf_length
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
- 4) {
697 cERROR(1, ("Illegal length, greater than maximum frame, %d",
698 in_buf
->smb_buf_length
));
699 DeleteMidQEntry(midQ
);
700 up(&ses
->server
->tcpSem
);
701 /* Update # of requests on wire to server */
702 atomic_dec(&ses
->server
->inFlight
);
703 wake_up(&ses
->server
->request_q
);
707 rc
= cifs_sign_smb(in_buf
, ses
->server
, &midQ
->sequence_number
);
709 midQ
->midState
= MID_REQUEST_SUBMITTED
;
710 #ifdef CONFIG_CIFS_STATS2
711 atomic_inc(&ses
->server
->inSend
);
713 rc
= smb_send(ses
->server
->ssocket
, in_buf
, in_buf
->smb_buf_length
,
714 (struct sockaddr
*) &(ses
->server
->addr
.sockAddr
));
715 #ifdef CONFIG_CIFS_STATS2
716 atomic_dec(&ses
->server
->inSend
);
717 midQ
->when_sent
= jiffies
;
719 up(&ses
->server
->tcpSem
);
724 if (long_op
== CIFS_STD_OP
)
726 /* wait for 15 seconds or until woken up due to response arriving or
727 due to last connection to this server being unmounted */
728 else if (long_op
== CIFS_ASYNC_OP
)
730 else if (long_op
== CIFS_VLONG_OP
) /* writes past EOF can be slow */
732 else if (long_op
== CIFS_LONG_OP
)
733 timeout
= 45 * HZ
; /* should be greater than
734 servers oplock break timeout (about 43 seconds) */
735 else if (long_op
== CIFS_BLOCKING_OP
)
736 timeout
= 0x7FFFFFFF; /* large but no so large as to wrap */
738 cERROR(1, ("unknown timeout flag %d", long_op
));
743 if (signal_pending(current
)) {
744 /* if signal pending do not hold up user for full smb timeout
745 but we still give response a chance to complete */
749 /* No user interrupts in wait - wreaks havoc with performance */
750 wait_for_response(ses
, midQ
, timeout
, 10 * HZ
);
752 spin_lock(&GlobalMid_Lock
);
753 if (midQ
->resp_buf
) {
754 spin_unlock(&GlobalMid_Lock
);
755 receive_len
= midQ
->resp_buf
->smb_buf_length
;
757 cERROR(1, ("No response for cmd %d mid %d",
758 midQ
->command
, midQ
->mid
));
759 if (midQ
->midState
== MID_REQUEST_SUBMITTED
) {
760 if (ses
->server
->tcpStatus
== CifsExiting
)
763 ses
->server
->tcpStatus
= CifsNeedReconnect
;
764 midQ
->midState
= MID_RETRY_NEEDED
;
768 if (rc
!= -EHOSTDOWN
) {
769 if (midQ
->midState
== MID_RETRY_NEEDED
) {
771 cFYI(1, ("marking request for retry"));
776 spin_unlock(&GlobalMid_Lock
);
777 DeleteMidQEntry(midQ
);
778 /* Update # of requests on wire to server */
779 atomic_dec(&ses
->server
->inFlight
);
780 wake_up(&ses
->server
->request_q
);
784 if (receive_len
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
) {
785 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
788 } else { /* rcvd frame is ok */
790 if (midQ
->resp_buf
&& out_buf
791 && (midQ
->midState
== MID_RESPONSE_RECEIVED
)) {
792 out_buf
->smb_buf_length
= receive_len
;
793 memcpy((char *)out_buf
+ 4,
794 (char *)midQ
->resp_buf
+ 4,
797 dump_smb(out_buf
, 92);
798 /* convert the length into a more usable form */
799 if ((receive_len
> 24) &&
800 (ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
|
801 SECMODE_SIGN_ENABLED
))) {
802 rc
= cifs_verify_signature(out_buf
,
803 &ses
->server
->mac_signing_key
,
804 midQ
->sequence_number
+1);
806 cERROR(1, ("Unexpected SMB signature"));
807 /* BB FIXME add code to kill session */
811 *pbytes_returned
= out_buf
->smb_buf_length
;
813 /* BB special case reconnect tid and uid here? */
814 rc
= map_smb_to_linux_error(out_buf
, 0 /* no log */ );
816 /* convert ByteCount if necessary */
817 if (receive_len
>= sizeof(struct smb_hdr
) - 4
818 /* do not count RFC1001 header */ +
819 (2 * out_buf
->WordCount
) + 2 /* bcc */ )
820 BCC(out_buf
) = le16_to_cpu(BCC_LE(out_buf
));
823 cERROR(1, ("Bad MID state?"));
828 DeleteMidQEntry(midQ
);
829 atomic_dec(&ses
->server
->inFlight
);
830 wake_up(&ses
->server
->request_q
);
835 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
838 send_nt_cancel(struct cifsTconInfo
*tcon
, struct smb_hdr
*in_buf
,
839 struct mid_q_entry
*midQ
)
842 struct cifsSesInfo
*ses
= tcon
->ses
;
843 __u16 mid
= in_buf
->Mid
;
845 header_assemble(in_buf
, SMB_COM_NT_CANCEL
, tcon
, 0);
847 down(&ses
->server
->tcpSem
);
848 rc
= cifs_sign_smb(in_buf
, ses
->server
, &midQ
->sequence_number
);
850 up(&ses
->server
->tcpSem
);
853 rc
= smb_send(ses
->server
->ssocket
, in_buf
, in_buf
->smb_buf_length
,
854 (struct sockaddr
*) &(ses
->server
->addr
.sockAddr
));
855 up(&ses
->server
->tcpSem
);
859 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
860 blocking lock to return. */
863 send_lock_cancel(const unsigned int xid
, struct cifsTconInfo
*tcon
,
864 struct smb_hdr
*in_buf
,
865 struct smb_hdr
*out_buf
)
868 struct cifsSesInfo
*ses
= tcon
->ses
;
869 LOCK_REQ
*pSMB
= (LOCK_REQ
*)in_buf
;
871 /* We just modify the current in_buf to change
872 the type of lock from LOCKING_ANDX_SHARED_LOCK
873 or LOCKING_ANDX_EXCLUSIVE_LOCK to
874 LOCKING_ANDX_CANCEL_LOCK. */
876 pSMB
->LockType
= LOCKING_ANDX_CANCEL_LOCK
|LOCKING_ANDX_LARGE_FILES
;
878 pSMB
->hdr
.Mid
= GetNextMid(ses
->server
);
880 return SendReceive(xid
, ses
, in_buf
, out_buf
,
881 &bytes_returned
, CIFS_STD_OP
);
885 SendReceiveBlockingLock(const unsigned int xid
, struct cifsTconInfo
*tcon
,
886 struct smb_hdr
*in_buf
, struct smb_hdr
*out_buf
,
887 int *pbytes_returned
)
891 unsigned int receive_len
;
892 struct mid_q_entry
*midQ
;
893 struct cifsSesInfo
*ses
;
895 if (tcon
== NULL
|| tcon
->ses
== NULL
) {
896 cERROR(1, ("Null smb session"));
901 if (ses
->server
== NULL
) {
902 cERROR(1, ("Null tcp session"));
906 if (ses
->server
->tcpStatus
== CifsExiting
)
909 /* Ensure that we do not send more than 50 overlapping requests
910 to the same server. We may make this configurable later or
913 rc
= wait_for_free_request(ses
, CIFS_BLOCKING_OP
);
917 /* make sure that we sign in the same order that we send on this socket
918 and avoid races inside tcp sendmsg code that could cause corruption
921 down(&ses
->server
->tcpSem
);
923 rc
= allocate_mid(ses
, in_buf
, &midQ
);
925 up(&ses
->server
->tcpSem
);
929 if (in_buf
->smb_buf_length
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
- 4) {
930 up(&ses
->server
->tcpSem
);
931 cERROR(1, ("Illegal length, greater than maximum frame, %d",
932 in_buf
->smb_buf_length
));
933 DeleteMidQEntry(midQ
);
937 rc
= cifs_sign_smb(in_buf
, ses
->server
, &midQ
->sequence_number
);
939 midQ
->midState
= MID_REQUEST_SUBMITTED
;
940 #ifdef CONFIG_CIFS_STATS2
941 atomic_inc(&ses
->server
->inSend
);
943 rc
= smb_send(ses
->server
->ssocket
, in_buf
, in_buf
->smb_buf_length
,
944 (struct sockaddr
*) &(ses
->server
->addr
.sockAddr
));
945 #ifdef CONFIG_CIFS_STATS2
946 atomic_dec(&ses
->server
->inSend
);
947 midQ
->when_sent
= jiffies
;
949 up(&ses
->server
->tcpSem
);
952 DeleteMidQEntry(midQ
);
956 /* Wait for a reply - allow signals to interrupt. */
957 rc
= wait_event_interruptible(ses
->server
->response_q
,
958 (!(midQ
->midState
== MID_REQUEST_SUBMITTED
)) ||
959 ((ses
->server
->tcpStatus
!= CifsGood
) &&
960 (ses
->server
->tcpStatus
!= CifsNew
)));
962 /* Were we interrupted by a signal ? */
963 if ((rc
== -ERESTARTSYS
) &&
964 (midQ
->midState
== MID_REQUEST_SUBMITTED
) &&
965 ((ses
->server
->tcpStatus
== CifsGood
) ||
966 (ses
->server
->tcpStatus
== CifsNew
))) {
968 if (in_buf
->Command
== SMB_COM_TRANSACTION2
) {
969 /* POSIX lock. We send a NT_CANCEL SMB to cause the
970 blocking lock to return. */
972 rc
= send_nt_cancel(tcon
, in_buf
, midQ
);
974 DeleteMidQEntry(midQ
);
978 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
979 to cause the blocking lock to return. */
981 rc
= send_lock_cancel(xid
, tcon
, in_buf
, out_buf
);
983 /* If we get -ENOLCK back the lock may have
984 already been removed. Don't exit in this case. */
985 if (rc
&& rc
!= -ENOLCK
) {
986 DeleteMidQEntry(midQ
);
991 /* Wait 5 seconds for the response. */
992 if (wait_for_response(ses
, midQ
, 5 * HZ
, 5 * HZ
) == 0) {
993 /* We got the response - restart system call. */
998 spin_lock(&GlobalMid_Lock
);
999 if (midQ
->resp_buf
) {
1000 spin_unlock(&GlobalMid_Lock
);
1001 receive_len
= midQ
->resp_buf
->smb_buf_length
;
1003 cERROR(1, ("No response for cmd %d mid %d",
1004 midQ
->command
, midQ
->mid
));
1005 if (midQ
->midState
== MID_REQUEST_SUBMITTED
) {
1006 if (ses
->server
->tcpStatus
== CifsExiting
)
1009 ses
->server
->tcpStatus
= CifsNeedReconnect
;
1010 midQ
->midState
= MID_RETRY_NEEDED
;
1014 if (rc
!= -EHOSTDOWN
) {
1015 if (midQ
->midState
== MID_RETRY_NEEDED
) {
1017 cFYI(1, ("marking request for retry"));
1022 spin_unlock(&GlobalMid_Lock
);
1023 DeleteMidQEntry(midQ
);
1027 if (receive_len
> CIFSMaxBufSize
+ MAX_CIFS_HDR_SIZE
) {
1028 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1031 } else { /* rcvd frame is ok */
1033 if (midQ
->resp_buf
&& out_buf
1034 && (midQ
->midState
== MID_RESPONSE_RECEIVED
)) {
1035 out_buf
->smb_buf_length
= receive_len
;
1036 memcpy((char *)out_buf
+ 4,
1037 (char *)midQ
->resp_buf
+ 4,
1040 dump_smb(out_buf
, 92);
1041 /* convert the length into a more usable form */
1042 if ((receive_len
> 24) &&
1043 (ses
->server
->secMode
& (SECMODE_SIGN_REQUIRED
|
1044 SECMODE_SIGN_ENABLED
))) {
1045 rc
= cifs_verify_signature(out_buf
,
1046 &ses
->server
->mac_signing_key
,
1047 midQ
->sequence_number
+1);
1049 cERROR(1, ("Unexpected SMB signature"));
1050 /* BB FIXME add code to kill session */
1054 *pbytes_returned
= out_buf
->smb_buf_length
;
1056 /* BB special case reconnect tid and uid here? */
1057 rc
= map_smb_to_linux_error(out_buf
, 0 /* no log */ );
1059 /* convert ByteCount if necessary */
1060 if (receive_len
>= sizeof(struct smb_hdr
) - 4
1061 /* do not count RFC1001 header */ +
1062 (2 * out_buf
->WordCount
) + 2 /* bcc */ )
1063 BCC(out_buf
) = le16_to_cpu(BCC_LE(out_buf
));
1066 cERROR(1, ("Bad MID state?"));
1069 DeleteMidQEntry(midQ
);
1070 if (rstart
&& rc
== -EACCES
)
1071 return -ERESTARTSYS
;