4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com)
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or
10 * (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
15 * the GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <linux/list.h>
24 #include <linux/wait.h>
25 #include <linux/net.h>
26 #include <linux/delay.h>
27 #include <asm/uaccess.h>
28 #include <asm/processor.h>
29 #include <linux/mempool.h>
32 #include "cifsproto.h"
33 #include "cifs_debug.h"
35 extern mempool_t *cifs_mid_poolp;
36 extern kmem_cache_t *cifs_oplock_cachep;
38 static struct mid_q_entry *
39 AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41 struct mid_q_entry *temp;
44 cERROR(1, ("Null session passed in to AllocMidQEntry"));
47 if (ses->server == NULL) {
48 cERROR(1, ("Null TCP session in AllocMidQEntry"));
52 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
53 SLAB_KERNEL | SLAB_NOFS);
57 memset(temp, 0, sizeof (struct mid_q_entry));
58 temp->mid = smb_buffer->Mid; /* always LE */
59 temp->pid = current->pid;
60 temp->command = smb_buffer->Command;
61 cFYI(1, ("For smb_command %d", temp->command));
62 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
63 /* when mid allocated can be before when sent */
64 temp->when_alloc = jiffies;
69 spin_lock(&GlobalMid_Lock);
70 list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
71 atomic_inc(&midCount);
72 temp->midState = MID_REQUEST_ALLOCATED;
73 spin_unlock(&GlobalMid_Lock);
78 DeleteMidQEntry(struct mid_q_entry *midEntry)
80 #ifdef CONFIG_CIFS_STATS2
83 spin_lock(&GlobalMid_Lock);
84 midEntry->midState = MID_FREE;
85 list_del(&midEntry->qhead);
86 atomic_dec(&midCount);
87 spin_unlock(&GlobalMid_Lock);
88 if(midEntry->largeBuf)
89 cifs_buf_release(midEntry->resp_buf);
91 cifs_small_buf_release(midEntry->resp_buf);
92 #ifdef CONFIG_CIFS_STATS2
94 /* commands taking longer than one second are indications that
95 something is wrong, unless it is quite a slow link or server */
96 if((now - midEntry->when_alloc) > HZ) {
97 if((cifsFYI & CIFS_TIMER) &&
98 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
99 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
100 midEntry->command, midEntry->mid);
101 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
102 now - midEntry->when_alloc,
103 now - midEntry->when_sent,
104 now - midEntry->when_received);
108 mempool_free(midEntry, cifs_mid_poolp);
111 struct oplock_q_entry *
112 AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
114 struct oplock_q_entry *temp;
115 if ((pinode== NULL) || (tcon == NULL)) {
116 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
119 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
124 temp->pinode = pinode;
127 spin_lock(&GlobalMid_Lock);
128 list_add_tail(&temp->qhead, &GlobalOplock_Q);
129 spin_unlock(&GlobalMid_Lock);
135 void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
137 spin_lock(&GlobalMid_Lock);
138 /* should we check if list empty first? */
139 list_del(&oplockEntry->qhead);
140 spin_unlock(&GlobalMid_Lock);
141 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
145 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
146 unsigned int smb_buf_length, struct sockaddr *sin)
150 struct msghdr smb_msg;
152 unsigned len = smb_buf_length + 4;
155 return -ENOTSOCK; /* BB eventually add reconnect code here */
156 iov.iov_base = smb_buffer;
159 smb_msg.msg_name = sin;
160 smb_msg.msg_namelen = sizeof (struct sockaddr);
161 smb_msg.msg_control = NULL;
162 smb_msg.msg_controllen = 0;
163 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
165 /* smb header is converted in header_assemble. bcc and rest of SMB word
166 area, and byte area if necessary, is converted to littleendian in
167 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
168 Flags2 is converted in SendReceive */
170 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
171 cFYI(1, ("Sending smb of length %d", smb_buf_length));
172 dump_smb(smb_buffer, len);
175 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
176 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
178 /* smaller timeout here than send2 since smaller size */
179 /* Although it may not be required, this also is smaller
183 ("sends on sock %p stuck for 7 seconds",
194 i = 0; /* reset i after each successful send */
201 cERROR(1,("Error %d sending data on socket to server", rc));
210 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
211 struct sockaddr *sin)
215 struct msghdr smb_msg;
216 struct smb_hdr *smb_buffer = iov[0].iov_base;
217 unsigned int len = iov[0].iov_len;
218 unsigned int total_len;
222 return -ENOTSOCK; /* BB eventually add reconnect code here */
224 smb_msg.msg_name = sin;
225 smb_msg.msg_namelen = sizeof (struct sockaddr);
226 smb_msg.msg_control = NULL;
227 smb_msg.msg_controllen = 0;
228 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
230 /* smb header is converted in header_assemble. bcc and rest of SMB word
231 area, and byte area if necessary, is converted to littleendian in
232 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
233 Flags2 is converted in SendReceive */
237 for (i = 0; i < n_vec; i++)
238 total_len += iov[i].iov_len;
240 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
241 cFYI(1, ("Sending smb: total_len %d", total_len));
242 dump_smb(smb_buffer, len);
245 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
246 n_vec - first_vec, total_len);
247 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
251 ("sends on sock %p stuck for 15 seconds",
262 if (rc >= total_len) {
263 WARN_ON(rc > total_len);
267 /* should never happen, letting socket clear before
268 retrying is our only obvious option here */
269 cERROR(1,("tcp sent no data"));
274 /* the line below resets i */
275 for (i = first_vec; i < n_vec; i++) {
276 if (iov[i].iov_len) {
277 if (rc > iov[i].iov_len) {
278 rc -= iov[i].iov_len;
281 iov[i].iov_base += rc;
282 iov[i].iov_len -= rc;
288 i = 0; /* in case we get ENOSPC on the next send */
292 cERROR(1,("Error %d sending data on socket to server", rc));
300 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
301 struct kvec *iov, int n_vec, int * pRespBufType /* ret */,
305 unsigned int receive_len;
306 unsigned long timeout;
307 struct mid_q_entry *midQ;
308 struct smb_hdr *in_buf = iov[0].iov_base;
310 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
312 if ((ses == NULL) || (ses->server == NULL)) {
313 cifs_small_buf_release(in_buf);
314 cERROR(1,("Null session"));
318 if(ses->server->tcpStatus == CifsExiting) {
319 cifs_small_buf_release(in_buf);
323 /* Ensure that we do not send more than 50 overlapping requests
324 to the same server. We may make this configurable later or
327 /* oplock breaks must not be held up */
328 atomic_inc(&ses->server->inFlight);
330 spin_lock(&GlobalMid_Lock);
332 if(atomic_read(&ses->server->inFlight) >=
334 spin_unlock(&GlobalMid_Lock);
335 #ifdef CONFIG_CIFS_STATS2
336 atomic_inc(&ses->server->num_waiters);
338 wait_event(ses->server->request_q,
339 atomic_read(&ses->server->inFlight)
341 #ifdef CONFIG_CIFS_STATS2
342 atomic_dec(&ses->server->num_waiters);
344 spin_lock(&GlobalMid_Lock);
346 if(ses->server->tcpStatus == CifsExiting) {
347 spin_unlock(&GlobalMid_Lock);
348 cifs_small_buf_release(in_buf);
352 /* can not count locking commands against total since
353 they are allowed to block on server */
356 /* update # of requests on the wire to server */
357 atomic_inc(&ses->server->inFlight);
359 spin_unlock(&GlobalMid_Lock);
364 /* make sure that we sign in the same order that we send on this socket
365 and avoid races inside tcp sendmsg code that could cause corruption
368 down(&ses->server->tcpSem);
370 if (ses->server->tcpStatus == CifsExiting) {
373 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
374 cFYI(1,("tcp session dead - return to caller to retry"));
377 } else if (ses->status != CifsGood) {
378 /* check if SMB session is bad because we are setting it up */
379 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
380 (in_buf->Command != SMB_COM_NEGOTIATE)) {
383 } /* else ok - we are setting up session */
385 midQ = AllocMidQEntry(in_buf, ses);
387 up(&ses->server->tcpSem);
388 cifs_small_buf_release(in_buf);
389 /* If not lock req, update # of requests on wire to server */
391 atomic_dec(&ses->server->inFlight);
392 wake_up(&ses->server->request_q);
397 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
399 midQ->midState = MID_REQUEST_SUBMITTED;
400 #ifdef CONFIG_CIFS_STATS2
401 atomic_inc(&ses->server->inSend);
403 rc = smb_send2(ses->server->ssocket, iov, n_vec,
404 (struct sockaddr *) &(ses->server->addr.sockAddr));
405 #ifdef CONFIG_CIFS_STATS2
406 atomic_dec(&ses->server->inSend);
407 midQ->when_sent = jiffies;
410 DeleteMidQEntry(midQ);
411 up(&ses->server->tcpSem);
412 cifs_small_buf_release(in_buf);
413 /* If not lock req, update # of requests on wire to server */
415 atomic_dec(&ses->server->inFlight);
416 wake_up(&ses->server->request_q);
420 up(&ses->server->tcpSem);
421 cifs_small_buf_release(in_buf);
425 goto cifs_no_response_exit2;
426 else if (long_op == 2) /* writes past end of file can take loong time */
428 else if (long_op == 1)
429 timeout = 45 * HZ; /* should be greater than
430 servers oplock break timeout (about 43 seconds) */
431 else if (long_op > 2) {
432 timeout = MAX_SCHEDULE_TIMEOUT;
435 /* wait for 15 seconds or until woken up due to response arriving or
436 due to last connection to this server being unmounted */
437 if (signal_pending(current)) {
438 /* if signal pending do not hold up user for full smb timeout
439 but we still give response a change to complete */
443 /* No user interrupts in wait - wreaks havoc with performance */
444 if(timeout != MAX_SCHEDULE_TIMEOUT) {
446 wait_event(ses->server->response_q,
447 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
448 time_after(jiffies, timeout) ||
449 ((ses->server->tcpStatus != CifsGood) &&
450 (ses->server->tcpStatus != CifsNew)));
452 wait_event(ses->server->response_q,
453 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
454 ((ses->server->tcpStatus != CifsGood) &&
455 (ses->server->tcpStatus != CifsNew)));
458 spin_lock(&GlobalMid_Lock);
459 if (midQ->resp_buf) {
460 spin_unlock(&GlobalMid_Lock);
461 receive_len = midQ->resp_buf->smb_buf_length;
463 cERROR(1,("No response to cmd %d mid %d",
464 midQ->command, midQ->mid));
465 if(midQ->midState == MID_REQUEST_SUBMITTED) {
466 if(ses->server->tcpStatus == CifsExiting)
469 ses->server->tcpStatus = CifsNeedReconnect;
470 midQ->midState = MID_RETRY_NEEDED;
474 if (rc != -EHOSTDOWN) {
475 if(midQ->midState == MID_RETRY_NEEDED) {
477 cFYI(1,("marking request for retry"));
482 spin_unlock(&GlobalMid_Lock);
483 DeleteMidQEntry(midQ);
484 /* If not lock req, update # of requests on wire to server */
486 atomic_dec(&ses->server->inFlight);
487 wake_up(&ses->server->request_q);
492 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
493 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
496 } else { /* rcvd frame is ok */
497 if (midQ->resp_buf &&
498 (midQ->midState == MID_RESPONSE_RECEIVED)) {
500 iov[0].iov_base = (char *)midQ->resp_buf;
502 *pRespBufType = CIFS_LARGE_BUFFER;
504 *pRespBufType = CIFS_SMALL_BUFFER;
505 iov[0].iov_len = receive_len + 4;
507 dump_smb(midQ->resp_buf, 80);
508 /* convert the length into a more usable form */
509 if((receive_len > 24) &&
510 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
511 SECMODE_SIGN_ENABLED))) {
512 rc = cifs_verify_signature(midQ->resp_buf,
513 ses->server->mac_signing_key,
514 midQ->sequence_number+1);
516 cERROR(1,("Unexpected SMB signature"));
517 /* BB FIXME add code to kill session */
521 /* BB special case reconnect tid and uid here? */
522 /* BB special case Errbadpassword and pwdexpired here */
523 rc = map_smb_to_linux_error(midQ->resp_buf);
525 /* convert ByteCount if necessary */
527 sizeof (struct smb_hdr) -
528 4 /* do not count RFC1001 header */ +
529 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
530 BCC(midQ->resp_buf) =
531 le16_to_cpu(BCC_LE(midQ->resp_buf));
532 midQ->resp_buf = NULL; /* mark it so will not be freed
533 by DeleteMidQEntry */
536 cFYI(1,("Bad MID state?"));
539 cifs_no_response_exit2:
540 DeleteMidQEntry(midQ);
543 atomic_dec(&ses->server->inFlight);
544 wake_up(&ses->server->request_q);
550 up(&ses->server->tcpSem);
551 cifs_small_buf_release(in_buf);
552 /* If not lock req, update # of requests on wire to server */
554 atomic_dec(&ses->server->inFlight);
555 wake_up(&ses->server->request_q);
562 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
563 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
564 int *pbytes_returned, const int long_op)
567 unsigned int receive_len;
568 unsigned long timeout;
569 struct mid_q_entry *midQ;
572 cERROR(1,("Null smb session"));
575 if(ses->server == NULL) {
576 cERROR(1,("Null tcp session"));
580 if(ses->server->tcpStatus == CifsExiting)
583 /* Ensure that we do not send more than 50 overlapping requests
584 to the same server. We may make this configurable later or
587 /* oplock breaks must not be held up */
588 atomic_inc(&ses->server->inFlight);
590 spin_lock(&GlobalMid_Lock);
592 if(atomic_read(&ses->server->inFlight) >=
594 spin_unlock(&GlobalMid_Lock);
595 #ifdef CONFIG_CIFS_STATS2
596 atomic_inc(&ses->server->num_waiters);
598 wait_event(ses->server->request_q,
599 atomic_read(&ses->server->inFlight)
601 #ifdef CONFIG_CIFS_STATS2
602 atomic_dec(&ses->server->num_waiters);
604 spin_lock(&GlobalMid_Lock);
606 if(ses->server->tcpStatus == CifsExiting) {
607 spin_unlock(&GlobalMid_Lock);
611 /* can not count locking commands against total since
612 they are allowed to block on server */
615 /* update # of requests on the wire to server */
616 atomic_inc(&ses->server->inFlight);
618 spin_unlock(&GlobalMid_Lock);
623 /* make sure that we sign in the same order that we send on this socket
624 and avoid races inside tcp sendmsg code that could cause corruption
627 down(&ses->server->tcpSem);
629 if (ses->server->tcpStatus == CifsExiting) {
632 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
633 cFYI(1,("tcp session dead - return to caller to retry"));
636 } else if (ses->status != CifsGood) {
637 /* check if SMB session is bad because we are setting it up */
638 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
639 (in_buf->Command != SMB_COM_NEGOTIATE)) {
642 } /* else ok - we are setting up session */
644 midQ = AllocMidQEntry(in_buf, ses);
646 up(&ses->server->tcpSem);
647 /* If not lock req, update # of requests on wire to server */
649 atomic_dec(&ses->server->inFlight);
650 wake_up(&ses->server->request_q);
655 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
656 up(&ses->server->tcpSem);
657 cERROR(1, ("Illegal length, greater than maximum frame, %d",
658 in_buf->smb_buf_length));
659 DeleteMidQEntry(midQ);
660 /* If not lock req, update # of requests on wire to server */
662 atomic_dec(&ses->server->inFlight);
663 wake_up(&ses->server->request_q);
668 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
670 midQ->midState = MID_REQUEST_SUBMITTED;
671 #ifdef CONFIG_CIFS_STATS2
672 atomic_inc(&ses->server->inSend);
674 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
675 (struct sockaddr *) &(ses->server->addr.sockAddr));
676 #ifdef CONFIG_CIFS_STATS2
677 atomic_dec(&ses->server->inSend);
678 midQ->when_sent = jiffies;
681 DeleteMidQEntry(midQ);
682 up(&ses->server->tcpSem);
683 /* If not lock req, update # of requests on wire to server */
685 atomic_dec(&ses->server->inFlight);
686 wake_up(&ses->server->request_q);
690 up(&ses->server->tcpSem);
692 goto cifs_no_response_exit;
693 else if (long_op == 2) /* writes past end of file can take loong time */
695 else if (long_op == 1)
696 timeout = 45 * HZ; /* should be greater than
697 servers oplock break timeout (about 43 seconds) */
698 else if (long_op > 2) {
699 timeout = MAX_SCHEDULE_TIMEOUT;
702 /* wait for 15 seconds or until woken up due to response arriving or
703 due to last connection to this server being unmounted */
704 if (signal_pending(current)) {
705 /* if signal pending do not hold up user for full smb timeout
706 but we still give response a change to complete */
710 /* No user interrupts in wait - wreaks havoc with performance */
711 if(timeout != MAX_SCHEDULE_TIMEOUT) {
713 wait_event(ses->server->response_q,
714 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
715 time_after(jiffies, timeout) ||
716 ((ses->server->tcpStatus != CifsGood) &&
717 (ses->server->tcpStatus != CifsNew)));
719 wait_event(ses->server->response_q,
720 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
721 ((ses->server->tcpStatus != CifsGood) &&
722 (ses->server->tcpStatus != CifsNew)));
725 spin_lock(&GlobalMid_Lock);
726 if (midQ->resp_buf) {
727 spin_unlock(&GlobalMid_Lock);
728 receive_len = midQ->resp_buf->smb_buf_length;
730 cERROR(1,("No response for cmd %d mid %d",
731 midQ->command, midQ->mid));
732 if(midQ->midState == MID_REQUEST_SUBMITTED) {
733 if(ses->server->tcpStatus == CifsExiting)
736 ses->server->tcpStatus = CifsNeedReconnect;
737 midQ->midState = MID_RETRY_NEEDED;
741 if (rc != -EHOSTDOWN) {
742 if(midQ->midState == MID_RETRY_NEEDED) {
744 cFYI(1,("marking request for retry"));
749 spin_unlock(&GlobalMid_Lock);
750 DeleteMidQEntry(midQ);
751 /* If not lock req, update # of requests on wire to server */
753 atomic_dec(&ses->server->inFlight);
754 wake_up(&ses->server->request_q);
759 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
760 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
763 } else { /* rcvd frame is ok */
765 if (midQ->resp_buf && out_buf
766 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
767 out_buf->smb_buf_length = receive_len;
768 memcpy((char *)out_buf + 4,
769 (char *)midQ->resp_buf + 4,
772 dump_smb(out_buf, 92);
773 /* convert the length into a more usable form */
774 if((receive_len > 24) &&
775 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
776 SECMODE_SIGN_ENABLED))) {
777 rc = cifs_verify_signature(out_buf,
778 ses->server->mac_signing_key,
779 midQ->sequence_number+1);
781 cERROR(1,("Unexpected SMB signature"));
782 /* BB FIXME add code to kill session */
786 *pbytes_returned = out_buf->smb_buf_length;
788 /* BB special case reconnect tid and uid here? */
789 rc = map_smb_to_linux_error(out_buf);
791 /* convert ByteCount if necessary */
793 sizeof (struct smb_hdr) -
794 4 /* do not count RFC1001 header */ +
795 (2 * out_buf->WordCount) + 2 /* bcc */ )
796 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
799 cERROR(1,("Bad MID state?"));
802 cifs_no_response_exit:
803 DeleteMidQEntry(midQ);
806 atomic_dec(&ses->server->inFlight);
807 wake_up(&ses->server->request_q);
813 up(&ses->server->tcpSem);
814 /* If not lock req, update # of requests on wire to server */
816 atomic_dec(&ses->server->inFlight);
817 wake_up(&ses->server->request_q);