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);
67 spin_lock(&GlobalMid_Lock);
68 list_add_tail(&temp->qhead, &ses->server->pending_mid_q);
69 atomic_inc(&midCount);
70 temp->midState = MID_REQUEST_ALLOCATED;
71 spin_unlock(&GlobalMid_Lock);
76 DeleteMidQEntry(struct mid_q_entry *midEntry)
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);
86 cifs_small_buf_release(midEntry->resp_buf);
87 mempool_free(midEntry, cifs_mid_poolp);
90 struct oplock_q_entry *
91 AllocOplockQEntry(struct inode * pinode, __u16 fid, struct cifsTconInfo * tcon)
93 struct oplock_q_entry *temp;
94 if ((pinode== NULL) || (tcon == NULL)) {
95 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
98 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
103 temp->pinode = pinode;
106 spin_lock(&GlobalMid_Lock);
107 list_add_tail(&temp->qhead, &GlobalOplock_Q);
108 spin_unlock(&GlobalMid_Lock);
114 void DeleteOplockQEntry(struct oplock_q_entry * oplockEntry)
116 spin_lock(&GlobalMid_Lock);
117 /* should we check if list empty first? */
118 list_del(&oplockEntry->qhead);
119 spin_unlock(&GlobalMid_Lock);
120 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
124 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
125 unsigned int smb_buf_length, struct sockaddr *sin)
129 struct msghdr smb_msg;
131 unsigned len = smb_buf_length + 4;
134 return -ENOTSOCK; /* BB eventually add reconnect code here */
135 iov.iov_base = smb_buffer;
138 smb_msg.msg_name = sin;
139 smb_msg.msg_namelen = sizeof (struct sockaddr);
140 smb_msg.msg_control = NULL;
141 smb_msg.msg_controllen = 0;
142 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
144 /* smb header is converted in header_assemble. bcc and rest of SMB word
145 area, and byte area if necessary, is converted to littleendian in
146 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
147 Flags2 is converted in SendReceive */
149 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
150 cFYI(1, ("Sending smb of length %d", smb_buf_length));
151 dump_smb(smb_buffer, len);
154 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
155 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
157 /* smaller timeout here than send2 since smaller size */
158 /* Although it may not be required, this also is smaller
162 ("sends on sock %p stuck for 7 seconds",
173 i = 0; /* reset i after each successful send */
180 cERROR(1,("Error %d sending data on socket to server", rc));
188 #ifdef CONFIG_CIFS_EXPERIMENTAL
190 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
191 struct sockaddr *sin)
195 struct msghdr smb_msg;
196 struct smb_hdr *smb_buffer = iov[0].iov_base;
197 unsigned int len = iov[0].iov_len;
198 unsigned int total_len;
202 return -ENOTSOCK; /* BB eventually add reconnect code here */
204 smb_msg.msg_name = sin;
205 smb_msg.msg_namelen = sizeof (struct sockaddr);
206 smb_msg.msg_control = NULL;
207 smb_msg.msg_controllen = 0;
208 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/
210 /* smb header is converted in header_assemble. bcc and rest of SMB word
211 area, and byte area if necessary, is converted to littleendian in
212 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
213 Flags2 is converted in SendReceive */
217 for (i = 0; i < n_vec; i++)
218 total_len += iov[i].iov_len;
220 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
221 cFYI(1, ("Sending smb: total_len %d", total_len));
222 dump_smb(smb_buffer, len);
225 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
226 n_vec - first_vec, total_len);
227 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
231 ("sends on sock %p stuck for 15 seconds",
242 if (rc >= total_len) {
243 WARN_ON(rc > total_len);
247 /* should never happen, letting socket clear before
248 retrying is our only obvious option here */
249 cERROR(1,("tcp sent no data"));
254 /* the line below resets i */
255 for (i = first_vec; i < n_vec; i++) {
256 if (iov[i].iov_len) {
257 if (rc > iov[i].iov_len) {
258 rc -= iov[i].iov_len;
261 iov[i].iov_base += rc;
262 iov[i].iov_len -= rc;
268 i = 0; /* in case we get ENOSPC on the next send */
272 cERROR(1,("Error %d sending data on socket to server", rc));
280 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
281 struct kvec *iov, int n_vec, int *pbytes_returned,
285 unsigned int receive_len;
286 unsigned long timeout;
287 struct mid_q_entry *midQ;
288 struct smb_hdr *in_buf = iov[0].iov_base;
291 cERROR(1,("Null smb session"));
294 if(ses->server == NULL) {
295 cERROR(1,("Null tcp session"));
299 if(ses->server->tcpStatus == CifsExiting)
302 /* Ensure that we do not send more than 50 overlapping requests
303 to the same server. We may make this configurable later or
306 /* oplock breaks must not be held up */
307 atomic_inc(&ses->server->inFlight);
309 spin_lock(&GlobalMid_Lock);
311 if(atomic_read(&ses->server->inFlight) >=
313 spin_unlock(&GlobalMid_Lock);
314 #ifdef CONFIG_CIFS_STATS2
315 atomic_inc(&ses->server->num_waiters);
317 wait_event(ses->server->request_q,
318 atomic_read(&ses->server->inFlight)
320 #ifdef CONFIG_CIFS_STATS2
321 atomic_dec(&ses->server->num_waiters);
323 spin_lock(&GlobalMid_Lock);
325 if(ses->server->tcpStatus == CifsExiting) {
326 spin_unlock(&GlobalMid_Lock);
330 /* can not count locking commands against total since
331 they are allowed to block on server */
334 /* update # of requests on the wire to server */
335 atomic_inc(&ses->server->inFlight);
337 spin_unlock(&GlobalMid_Lock);
342 /* make sure that we sign in the same order that we send on this socket
343 and avoid races inside tcp sendmsg code that could cause corruption
346 down(&ses->server->tcpSem);
348 if (ses->server->tcpStatus == CifsExiting) {
351 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
352 cFYI(1,("tcp session dead - return to caller to retry"));
355 } else if (ses->status != CifsGood) {
356 /* check if SMB session is bad because we are setting it up */
357 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
358 (in_buf->Command != SMB_COM_NEGOTIATE)) {
361 } /* else ok - we are setting up session */
363 midQ = AllocMidQEntry(in_buf, ses);
365 up(&ses->server->tcpSem);
366 /* If not lock req, update # of requests on wire to server */
368 atomic_dec(&ses->server->inFlight);
369 wake_up(&ses->server->request_q);
375 /* rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); */
377 midQ->midState = MID_REQUEST_SUBMITTED;
378 #ifdef CONFIG_CIFS_STATS2
379 atomic_inc(&ses->server->inSend);
381 rc = smb_send2(ses->server->ssocket, iov, n_vec,
382 (struct sockaddr *) &(ses->server->addr.sockAddr));
383 #ifdef CONFIG_CIFS_STATS2
384 atomic_dec(&ses->server->inSend);
387 DeleteMidQEntry(midQ);
388 up(&ses->server->tcpSem);
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);
396 up(&ses->server->tcpSem);
398 goto cifs_no_response_exit2;
399 else if (long_op == 2) /* writes past end of file can take loong time */
401 else if (long_op == 1)
402 timeout = 45 * HZ; /* should be greater than
403 servers oplock break timeout (about 43 seconds) */
404 else if (long_op > 2) {
405 timeout = MAX_SCHEDULE_TIMEOUT;
408 /* wait for 15 seconds or until woken up due to response arriving or
409 due to last connection to this server being unmounted */
410 if (signal_pending(current)) {
411 /* if signal pending do not hold up user for full smb timeout
412 but we still give response a change to complete */
416 /* No user interrupts in wait - wreaks havoc with performance */
417 if(timeout != MAX_SCHEDULE_TIMEOUT) {
419 wait_event(ses->server->response_q,
420 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
421 time_after(jiffies, timeout) ||
422 ((ses->server->tcpStatus != CifsGood) &&
423 (ses->server->tcpStatus != CifsNew)));
425 wait_event(ses->server->response_q,
426 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
427 ((ses->server->tcpStatus != CifsGood) &&
428 (ses->server->tcpStatus != CifsNew)));
431 spin_lock(&GlobalMid_Lock);
432 if (midQ->resp_buf) {
433 spin_unlock(&GlobalMid_Lock);
434 receive_len = midQ->resp_buf->smb_buf_length;
436 cERROR(1,("No response to cmd %d mid %d",
437 midQ->command, midQ->mid));
438 if(midQ->midState == MID_REQUEST_SUBMITTED) {
439 if(ses->server->tcpStatus == CifsExiting)
442 ses->server->tcpStatus = CifsNeedReconnect;
443 midQ->midState = MID_RETRY_NEEDED;
447 if (rc != -EHOSTDOWN) {
448 if(midQ->midState == MID_RETRY_NEEDED) {
450 cFYI(1,("marking request for retry"));
455 spin_unlock(&GlobalMid_Lock);
456 DeleteMidQEntry(midQ);
457 /* If not lock req, update # of requests on wire to server */
459 atomic_dec(&ses->server->inFlight);
460 wake_up(&ses->server->request_q);
465 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
466 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
469 } else { /* rcvd frame is ok */
471 if (midQ->resp_buf &&
472 (midQ->midState == MID_RESPONSE_RECEIVED)) {
473 in_buf->smb_buf_length = receive_len;
474 /* BB verify that length would not overrun small buf */
475 memcpy((char *)in_buf + 4,
476 (char *)midQ->resp_buf + 4,
479 dump_smb(in_buf, 80);
480 /* convert the length into a more usable form */
481 if((receive_len > 24) &&
482 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
483 SECMODE_SIGN_ENABLED))) {
484 rc = cifs_verify_signature(in_buf,
485 ses->server->mac_signing_key,
486 midQ->sequence_number+1);
488 cERROR(1,("Unexpected SMB signature"));
489 /* BB FIXME add code to kill session */
493 *pbytes_returned = in_buf->smb_buf_length;
495 /* BB special case reconnect tid and uid here? */
496 rc = map_smb_to_linux_error(in_buf);
498 /* convert ByteCount if necessary */
500 sizeof (struct smb_hdr) -
501 4 /* do not count RFC1001 header */ +
502 (2 * in_buf->WordCount) + 2 /* bcc */ )
503 BCC(in_buf) = le16_to_cpu(BCC(in_buf));
506 cFYI(1,("Bad MID state?"));
509 cifs_no_response_exit2:
510 DeleteMidQEntry(midQ);
513 atomic_dec(&ses->server->inFlight);
514 wake_up(&ses->server->request_q);
520 up(&ses->server->tcpSem);
521 /* If not lock req, update # of requests on wire to server */
523 atomic_dec(&ses->server->inFlight);
524 wake_up(&ses->server->request_q);
529 #endif /* CIFS_EXPERIMENTAL */
532 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
533 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
534 int *pbytes_returned, const int long_op)
537 unsigned int receive_len;
538 unsigned long timeout;
539 struct mid_q_entry *midQ;
542 cERROR(1,("Null smb session"));
545 if(ses->server == NULL) {
546 cERROR(1,("Null tcp session"));
550 if(ses->server->tcpStatus == CifsExiting)
553 /* Ensure that we do not send more than 50 overlapping requests
554 to the same server. We may make this configurable later or
557 /* oplock breaks must not be held up */
558 atomic_inc(&ses->server->inFlight);
560 spin_lock(&GlobalMid_Lock);
562 if(atomic_read(&ses->server->inFlight) >=
564 spin_unlock(&GlobalMid_Lock);
565 #ifdef CONFIG_CIFS_STATS2
566 atomic_inc(&ses->server->num_waiters);
568 wait_event(ses->server->request_q,
569 atomic_read(&ses->server->inFlight)
571 #ifdef CONFIG_CIFS_STATS2
572 atomic_dec(&ses->server->num_waiters);
574 spin_lock(&GlobalMid_Lock);
576 if(ses->server->tcpStatus == CifsExiting) {
577 spin_unlock(&GlobalMid_Lock);
581 /* can not count locking commands against total since
582 they are allowed to block on server */
585 /* update # of requests on the wire to server */
586 atomic_inc(&ses->server->inFlight);
588 spin_unlock(&GlobalMid_Lock);
593 /* make sure that we sign in the same order that we send on this socket
594 and avoid races inside tcp sendmsg code that could cause corruption
597 down(&ses->server->tcpSem);
599 if (ses->server->tcpStatus == CifsExiting) {
602 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
603 cFYI(1,("tcp session dead - return to caller to retry"));
606 } else if (ses->status != CifsGood) {
607 /* check if SMB session is bad because we are setting it up */
608 if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
609 (in_buf->Command != SMB_COM_NEGOTIATE)) {
612 } /* else ok - we are setting up session */
614 midQ = AllocMidQEntry(in_buf, ses);
616 up(&ses->server->tcpSem);
617 /* If not lock req, update # of requests on wire to server */
619 atomic_dec(&ses->server->inFlight);
620 wake_up(&ses->server->request_q);
625 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
626 up(&ses->server->tcpSem);
628 ("Illegal length, greater than maximum frame, %d ",
629 in_buf->smb_buf_length));
630 DeleteMidQEntry(midQ);
631 /* If not lock req, update # of requests on wire to server */
633 atomic_dec(&ses->server->inFlight);
634 wake_up(&ses->server->request_q);
639 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
641 midQ->midState = MID_REQUEST_SUBMITTED;
642 #ifdef CONFIG_CIFS_STATS2
643 atomic_inc(&ses->server->inSend);
645 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
646 (struct sockaddr *) &(ses->server->addr.sockAddr));
647 #ifdef CONFIG_CIFS_STATS2
648 atomic_dec(&ses->server->inSend);
651 DeleteMidQEntry(midQ);
652 up(&ses->server->tcpSem);
653 /* If not lock req, update # of requests on wire to server */
655 atomic_dec(&ses->server->inFlight);
656 wake_up(&ses->server->request_q);
660 up(&ses->server->tcpSem);
662 goto cifs_no_response_exit;
663 else if (long_op == 2) /* writes past end of file can take loong time */
665 else if (long_op == 1)
666 timeout = 45 * HZ; /* should be greater than
667 servers oplock break timeout (about 43 seconds) */
668 else if (long_op > 2) {
669 timeout = MAX_SCHEDULE_TIMEOUT;
672 /* wait for 15 seconds or until woken up due to response arriving or
673 due to last connection to this server being unmounted */
674 if (signal_pending(current)) {
675 /* if signal pending do not hold up user for full smb timeout
676 but we still give response a change to complete */
680 /* No user interrupts in wait - wreaks havoc with performance */
681 if(timeout != MAX_SCHEDULE_TIMEOUT) {
683 wait_event(ses->server->response_q,
684 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
685 time_after(jiffies, timeout) ||
686 ((ses->server->tcpStatus != CifsGood) &&
687 (ses->server->tcpStatus != CifsNew)));
689 wait_event(ses->server->response_q,
690 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
691 ((ses->server->tcpStatus != CifsGood) &&
692 (ses->server->tcpStatus != CifsNew)));
695 spin_lock(&GlobalMid_Lock);
696 if (midQ->resp_buf) {
697 spin_unlock(&GlobalMid_Lock);
698 receive_len = midQ->resp_buf->smb_buf_length;
700 cERROR(1,("No response for cmd %d mid %d",
701 midQ->command, midQ->mid));
702 if(midQ->midState == MID_REQUEST_SUBMITTED) {
703 if(ses->server->tcpStatus == CifsExiting)
706 ses->server->tcpStatus = CifsNeedReconnect;
707 midQ->midState = MID_RETRY_NEEDED;
711 if (rc != -EHOSTDOWN) {
712 if(midQ->midState == MID_RETRY_NEEDED) {
714 cFYI(1,("marking request for retry"));
719 spin_unlock(&GlobalMid_Lock);
720 DeleteMidQEntry(midQ);
721 /* If not lock req, update # of requests on wire to server */
723 atomic_dec(&ses->server->inFlight);
724 wake_up(&ses->server->request_q);
729 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
730 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
733 } else { /* rcvd frame is ok */
735 if (midQ->resp_buf && out_buf
736 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
737 out_buf->smb_buf_length = receive_len;
738 memcpy((char *)out_buf + 4,
739 (char *)midQ->resp_buf + 4,
742 dump_smb(out_buf, 92);
743 /* convert the length into a more usable form */
744 if((receive_len > 24) &&
745 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
746 SECMODE_SIGN_ENABLED))) {
747 rc = cifs_verify_signature(out_buf,
748 ses->server->mac_signing_key,
749 midQ->sequence_number+1);
751 cERROR(1,("Unexpected SMB signature"));
752 /* BB FIXME add code to kill session */
756 *pbytes_returned = out_buf->smb_buf_length;
758 /* BB special case reconnect tid and uid here? */
759 rc = map_smb_to_linux_error(out_buf);
761 /* convert ByteCount if necessary */
763 sizeof (struct smb_hdr) -
764 4 /* do not count RFC1001 header */ +
765 (2 * out_buf->WordCount) + 2 /* bcc */ )
766 BCC(out_buf) = le16_to_cpu(BCC(out_buf));
769 cERROR(1,("Bad MID state? "));
772 cifs_no_response_exit:
773 DeleteMidQEntry(midQ);
776 atomic_dec(&ses->server->inFlight);
777 wake_up(&ses->server->request_q);
783 up(&ses->server->tcpSem);
784 /* If not lock req, update # of requests on wire to server */
786 atomic_dec(&ses->server->inFlight);
787 wake_up(&ses->server->request_q);