x86: add cache descriptors for Intel Core i7
[linux-2.6/mini2440.git] / fs / cifs / transport.c
blob7ebe6599ed3a07cb712d0f6e725277bb778e12f0
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 struct oplock_q_entry *
107 AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
109 struct oplock_q_entry *temp;
110 if ((pinode == NULL) || (tcon == NULL)) {
111 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
112 return NULL;
114 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
115 GFP_KERNEL);
116 if (temp == NULL)
117 return temp;
118 else {
119 temp->pinode = pinode;
120 temp->tcon = tcon;
121 temp->netfid = fid;
122 spin_lock(&GlobalMid_Lock);
123 list_add_tail(&temp->qhead, &GlobalOplock_Q);
124 spin_unlock(&GlobalMid_Lock);
126 return temp;
130 void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
132 spin_lock(&GlobalMid_Lock);
133 /* should we check if list empty first? */
134 list_del(&oplockEntry->qhead);
135 spin_unlock(&GlobalMid_Lock);
136 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
140 void DeleteTconOplockQEntries(struct cifsTconInfo *tcon)
142 struct oplock_q_entry *temp;
144 if (tcon == NULL)
145 return;
147 spin_lock(&GlobalMid_Lock);
148 list_for_each_entry(temp, &GlobalOplock_Q, qhead) {
149 if ((temp->tcon) && (temp->tcon == tcon)) {
150 list_del(&temp->qhead);
151 kmem_cache_free(cifs_oplock_cachep, temp);
154 spin_unlock(&GlobalMid_Lock);
158 smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
159 unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd)
161 int rc = 0;
162 int i = 0;
163 struct msghdr smb_msg;
164 struct kvec iov;
165 unsigned len = smb_buf_length + 4;
167 if (ssocket == NULL)
168 return -ENOTSOCK; /* BB eventually add reconnect code here */
169 iov.iov_base = smb_buffer;
170 iov.iov_len = len;
172 smb_msg.msg_name = sin;
173 smb_msg.msg_namelen = sizeof(struct sockaddr);
174 smb_msg.msg_control = NULL;
175 smb_msg.msg_controllen = 0;
176 if (noblocksnd)
177 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
178 else
179 smb_msg.msg_flags = MSG_NOSIGNAL;
181 /* smb header is converted in header_assemble. bcc and rest of SMB word
182 area, and byte area if necessary, is converted to littleendian in
183 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
184 Flags2 is converted in SendReceive */
186 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
187 cFYI(1, ("Sending smb of length %d", smb_buf_length));
188 dump_smb(smb_buffer, len);
190 while (len > 0) {
191 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
192 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
193 i++;
194 /* smaller timeout here than send2 since smaller size */
195 /* Although it may not be required, this also is smaller
196 oplock break time */
197 if (i > 12) {
198 cERROR(1,
199 ("sends on sock %p stuck for 7 seconds",
200 ssocket));
201 rc = -EAGAIN;
202 break;
204 msleep(1 << i);
205 continue;
207 if (rc < 0)
208 break;
209 else
210 i = 0; /* reset i after each successful send */
211 iov.iov_base += rc;
212 iov.iov_len -= rc;
213 len -= rc;
216 if (rc < 0) {
217 cERROR(1, ("Error %d sending data on socket to server", rc));
218 } else {
219 rc = 0;
222 /* Don't want to modify the buffer as a
223 side effect of this call. */
224 smb_buffer->smb_buf_length = smb_buf_length;
226 return rc;
229 static int
230 smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec,
231 struct sockaddr *sin, bool noblocksnd)
233 int rc = 0;
234 int i = 0;
235 struct msghdr smb_msg;
236 struct smb_hdr *smb_buffer = iov[0].iov_base;
237 unsigned int len = iov[0].iov_len;
238 unsigned int total_len;
239 int first_vec = 0;
240 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
241 struct socket *ssocket = server->ssocket;
243 if (ssocket == NULL)
244 return -ENOTSOCK; /* BB eventually add reconnect code here */
246 smb_msg.msg_name = sin;
247 smb_msg.msg_namelen = sizeof(struct sockaddr);
248 smb_msg.msg_control = NULL;
249 smb_msg.msg_controllen = 0;
250 if (noblocksnd)
251 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
252 else
253 smb_msg.msg_flags = MSG_NOSIGNAL;
255 /* smb header is converted in header_assemble. bcc and rest of SMB word
256 area, and byte area if necessary, is converted to littleendian in
257 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
258 Flags2 is converted in SendReceive */
261 total_len = 0;
262 for (i = 0; i < n_vec; i++)
263 total_len += iov[i].iov_len;
265 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
266 cFYI(1, ("Sending smb: total_len %d", total_len));
267 dump_smb(smb_buffer, len);
269 i = 0;
270 while (total_len) {
271 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
272 n_vec - first_vec, total_len);
273 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
274 i++;
275 if (i >= 14) {
276 cERROR(1,
277 ("sends on sock %p stuck for 15 seconds",
278 ssocket));
279 rc = -EAGAIN;
280 break;
282 msleep(1 << i);
283 continue;
285 if (rc < 0)
286 break;
288 if (rc == total_len) {
289 total_len = 0;
290 break;
291 } else if (rc > total_len) {
292 cERROR(1, ("sent %d requested %d", rc, total_len));
293 break;
295 if (rc == 0) {
296 /* should never happen, letting socket clear before
297 retrying is our only obvious option here */
298 cERROR(1, ("tcp sent no data"));
299 msleep(500);
300 continue;
302 total_len -= rc;
303 /* the line below resets i */
304 for (i = first_vec; i < n_vec; i++) {
305 if (iov[i].iov_len) {
306 if (rc > iov[i].iov_len) {
307 rc -= iov[i].iov_len;
308 iov[i].iov_len = 0;
309 } else {
310 iov[i].iov_base += rc;
311 iov[i].iov_len -= rc;
312 first_vec = i;
313 break;
317 i = 0; /* in case we get ENOSPC on the next send */
320 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
321 cFYI(1, ("partial send (%d remaining), terminating session",
322 total_len));
323 /* If we have only sent part of an SMB then the next SMB
324 could be taken as the remainder of this one. We need
325 to kill the socket so the server throws away the partial
326 SMB */
327 server->tcpStatus = CifsNeedReconnect;
330 if (rc < 0) {
331 cERROR(1, ("Error %d sending data on socket to server", rc));
332 } else
333 rc = 0;
335 /* Don't want to modify the buffer as a
336 side effect of this call. */
337 smb_buffer->smb_buf_length = smb_buf_length;
339 return rc;
342 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
344 if (long_op == CIFS_ASYNC_OP) {
345 /* oplock breaks must not be held up */
346 atomic_inc(&ses->server->inFlight);
347 return 0;
350 spin_lock(&GlobalMid_Lock);
351 while (1) {
352 if (atomic_read(&ses->server->inFlight) >=
353 cifs_max_pending){
354 spin_unlock(&GlobalMid_Lock);
355 #ifdef CONFIG_CIFS_STATS2
356 atomic_inc(&ses->server->num_waiters);
357 #endif
358 wait_event(ses->server->request_q,
359 atomic_read(&ses->server->inFlight)
360 < cifs_max_pending);
361 #ifdef CONFIG_CIFS_STATS2
362 atomic_dec(&ses->server->num_waiters);
363 #endif
364 spin_lock(&GlobalMid_Lock);
365 } else {
366 if (ses->server->tcpStatus == CifsExiting) {
367 spin_unlock(&GlobalMid_Lock);
368 return -ENOENT;
371 /* can not count locking commands against total
372 as they are allowed to block on server */
374 /* update # of requests on the wire to server */
375 if (long_op != CIFS_BLOCKING_OP)
376 atomic_inc(&ses->server->inFlight);
377 spin_unlock(&GlobalMid_Lock);
378 break;
381 return 0;
384 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
385 struct mid_q_entry **ppmidQ)
387 if (ses->server->tcpStatus == CifsExiting) {
388 return -ENOENT;
391 if (ses->server->tcpStatus == CifsNeedReconnect) {
392 cFYI(1, ("tcp session dead - return to caller to retry"));
393 return -EAGAIN;
396 if (ses->status != CifsGood) {
397 /* check if SMB session is bad because we are setting it up */
398 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
399 (in_buf->Command != SMB_COM_NEGOTIATE))
400 return -EAGAIN;
401 /* else ok - we are setting up session */
403 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
404 if (*ppmidQ == NULL)
405 return -ENOMEM;
406 return 0;
409 static int wait_for_response(struct cifsSesInfo *ses,
410 struct mid_q_entry *midQ,
411 unsigned long timeout,
412 unsigned long time_to_wait)
414 unsigned long curr_timeout;
416 for (;;) {
417 curr_timeout = timeout + jiffies;
418 wait_event_timeout(ses->server->response_q,
419 midQ->midState != MID_REQUEST_SUBMITTED, timeout);
421 if (time_after(jiffies, curr_timeout) &&
422 (midQ->midState == MID_REQUEST_SUBMITTED) &&
423 ((ses->server->tcpStatus == CifsGood) ||
424 (ses->server->tcpStatus == CifsNew))) {
426 unsigned long lrt;
428 /* We timed out. Is the server still
429 sending replies ? */
430 spin_lock(&GlobalMid_Lock);
431 lrt = ses->server->lstrp;
432 spin_unlock(&GlobalMid_Lock);
434 /* Calculate time_to_wait past last receive time.
435 Although we prefer not to time out if the
436 server is still responding - we will time
437 out if the server takes more than 15 (or 45
438 or 180) seconds to respond to this request
439 and has not responded to any request from
440 other threads on the client within 10 seconds */
441 lrt += time_to_wait;
442 if (time_after(jiffies, lrt)) {
443 /* No replies for time_to_wait. */
444 cERROR(1, ("server not responding"));
445 return -1;
447 } else {
448 return 0;
456 * Send an SMB Request. No response info (other than return code)
457 * needs to be parsed.
459 * flags indicate the type of request buffer and how long to wait
460 * and whether to log NT STATUS code (error) before mapping it to POSIX error
464 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
465 struct smb_hdr *in_buf, int flags)
467 int rc;
468 struct kvec iov[1];
469 int resp_buf_type;
471 iov[0].iov_base = (char *)in_buf;
472 iov[0].iov_len = in_buf->smb_buf_length + 4;
473 flags |= CIFS_NO_RESP;
474 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
475 cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
477 return rc;
481 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
482 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
483 const int flags)
485 int rc = 0;
486 int long_op;
487 unsigned int receive_len;
488 unsigned long timeout;
489 struct mid_q_entry *midQ;
490 struct smb_hdr *in_buf = iov[0].iov_base;
492 long_op = flags & CIFS_TIMEOUT_MASK;
494 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
496 if ((ses == NULL) || (ses->server == NULL)) {
497 cifs_small_buf_release(in_buf);
498 cERROR(1, ("Null session"));
499 return -EIO;
502 if (ses->server->tcpStatus == CifsExiting) {
503 cifs_small_buf_release(in_buf);
504 return -ENOENT;
507 /* Ensure that we do not send more than 50 overlapping requests
508 to the same server. We may make this configurable later or
509 use ses->maxReq */
511 rc = wait_for_free_request(ses, long_op);
512 if (rc) {
513 cifs_small_buf_release(in_buf);
514 return rc;
517 /* make sure that we sign in the same order that we send on this socket
518 and avoid races inside tcp sendmsg code that could cause corruption
519 of smb data */
521 mutex_lock(&ses->server->srv_mutex);
523 rc = allocate_mid(ses, in_buf, &midQ);
524 if (rc) {
525 mutex_unlock(&ses->server->srv_mutex);
526 cifs_small_buf_release(in_buf);
527 /* Update # of requests on wire to server */
528 atomic_dec(&ses->server->inFlight);
529 wake_up(&ses->server->request_q);
530 return rc;
532 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
533 if (rc) {
534 mutex_unlock(&ses->server->srv_mutex);
535 cifs_small_buf_release(in_buf);
536 goto out;
539 midQ->midState = MID_REQUEST_SUBMITTED;
540 #ifdef CONFIG_CIFS_STATS2
541 atomic_inc(&ses->server->inSend);
542 #endif
543 rc = smb_send2(ses->server, iov, n_vec,
544 (struct sockaddr *) &(ses->server->addr.sockAddr),
545 ses->server->noblocksnd);
546 #ifdef CONFIG_CIFS_STATS2
547 atomic_dec(&ses->server->inSend);
548 midQ->when_sent = jiffies;
549 #endif
551 mutex_unlock(&ses->server->srv_mutex);
552 cifs_small_buf_release(in_buf);
554 if (rc < 0)
555 goto out;
557 if (long_op == CIFS_STD_OP)
558 timeout = 15 * HZ;
559 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
560 timeout = 180 * HZ;
561 else if (long_op == CIFS_LONG_OP)
562 timeout = 45 * HZ; /* should be greater than
563 servers oplock break timeout (about 43 seconds) */
564 else if (long_op == CIFS_ASYNC_OP)
565 goto out;
566 else if (long_op == CIFS_BLOCKING_OP)
567 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
568 else {
569 cERROR(1, ("unknown timeout flag %d", long_op));
570 rc = -EIO;
571 goto out;
574 /* wait for 15 seconds or until woken up due to response arriving or
575 due to last connection to this server being unmounted */
576 if (signal_pending(current)) {
577 /* if signal pending do not hold up user for full smb timeout
578 but we still give response a chance to complete */
579 timeout = 2 * HZ;
582 /* No user interrupts in wait - wreaks havoc with performance */
583 wait_for_response(ses, midQ, timeout, 10 * HZ);
585 spin_lock(&GlobalMid_Lock);
587 if (midQ->resp_buf == NULL) {
588 cERROR(1, ("No response to cmd %d mid %d",
589 midQ->command, midQ->mid));
590 if (midQ->midState == MID_REQUEST_SUBMITTED) {
591 if (ses->server->tcpStatus == CifsExiting)
592 rc = -EHOSTDOWN;
593 else {
594 ses->server->tcpStatus = CifsNeedReconnect;
595 midQ->midState = MID_RETRY_NEEDED;
599 if (rc != -EHOSTDOWN) {
600 if (midQ->midState == MID_RETRY_NEEDED) {
601 rc = -EAGAIN;
602 cFYI(1, ("marking request for retry"));
603 } else {
604 rc = -EIO;
607 spin_unlock(&GlobalMid_Lock);
608 DeleteMidQEntry(midQ);
609 /* Update # of requests on wire to server */
610 atomic_dec(&ses->server->inFlight);
611 wake_up(&ses->server->request_q);
612 return rc;
615 spin_unlock(&GlobalMid_Lock);
616 receive_len = midQ->resp_buf->smb_buf_length;
618 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
619 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
620 receive_len, xid));
621 rc = -EIO;
622 goto out;
625 /* rcvd frame is ok */
627 if (midQ->resp_buf &&
628 (midQ->midState == MID_RESPONSE_RECEIVED)) {
630 iov[0].iov_base = (char *)midQ->resp_buf;
631 if (midQ->largeBuf)
632 *pRespBufType = CIFS_LARGE_BUFFER;
633 else
634 *pRespBufType = CIFS_SMALL_BUFFER;
635 iov[0].iov_len = receive_len + 4;
637 dump_smb(midQ->resp_buf, 80);
638 /* convert the length into a more usable form */
639 if ((receive_len > 24) &&
640 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
641 SECMODE_SIGN_ENABLED))) {
642 rc = cifs_verify_signature(midQ->resp_buf,
643 &ses->server->mac_signing_key,
644 midQ->sequence_number+1);
645 if (rc) {
646 cERROR(1, ("Unexpected SMB signature"));
647 /* BB FIXME add code to kill session */
651 /* BB special case reconnect tid and uid here? */
652 rc = map_smb_to_linux_error(midQ->resp_buf,
653 flags & CIFS_LOG_ERROR);
655 /* convert ByteCount if necessary */
656 if (receive_len >= sizeof(struct smb_hdr) - 4
657 /* do not count RFC1001 header */ +
658 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
659 BCC(midQ->resp_buf) =
660 le16_to_cpu(BCC_LE(midQ->resp_buf));
661 if ((flags & CIFS_NO_RESP) == 0)
662 midQ->resp_buf = NULL; /* mark it so buf will
663 not be freed by
664 DeleteMidQEntry */
665 } else {
666 rc = -EIO;
667 cFYI(1, ("Bad MID state?"));
670 out:
671 DeleteMidQEntry(midQ);
672 atomic_dec(&ses->server->inFlight);
673 wake_up(&ses->server->request_q);
675 return rc;
679 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
680 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
681 int *pbytes_returned, const int long_op)
683 int rc = 0;
684 unsigned int receive_len;
685 unsigned long timeout;
686 struct mid_q_entry *midQ;
688 if (ses == NULL) {
689 cERROR(1, ("Null smb session"));
690 return -EIO;
692 if (ses->server == NULL) {
693 cERROR(1, ("Null tcp session"));
694 return -EIO;
697 if (ses->server->tcpStatus == CifsExiting)
698 return -ENOENT;
700 /* Ensure that we do not send more than 50 overlapping requests
701 to the same server. We may make this configurable later or
702 use ses->maxReq */
704 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
705 cERROR(1, ("Illegal length, greater than maximum frame, %d",
706 in_buf->smb_buf_length));
707 return -EIO;
710 rc = wait_for_free_request(ses, long_op);
711 if (rc)
712 return rc;
714 /* make sure that we sign in the same order that we send on this socket
715 and avoid races inside tcp sendmsg code that could cause corruption
716 of smb data */
718 mutex_lock(&ses->server->srv_mutex);
720 rc = allocate_mid(ses, in_buf, &midQ);
721 if (rc) {
722 mutex_unlock(&ses->server->srv_mutex);
723 /* Update # of requests on wire to server */
724 atomic_dec(&ses->server->inFlight);
725 wake_up(&ses->server->request_q);
726 return rc;
729 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
730 if (rc) {
731 mutex_unlock(&ses->server->srv_mutex);
732 goto out;
735 midQ->midState = MID_REQUEST_SUBMITTED;
736 #ifdef CONFIG_CIFS_STATS2
737 atomic_inc(&ses->server->inSend);
738 #endif
739 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
740 (struct sockaddr *) &(ses->server->addr.sockAddr),
741 ses->server->noblocksnd);
742 #ifdef CONFIG_CIFS_STATS2
743 atomic_dec(&ses->server->inSend);
744 midQ->when_sent = jiffies;
745 #endif
746 mutex_unlock(&ses->server->srv_mutex);
748 if (rc < 0)
749 goto out;
751 if (long_op == CIFS_STD_OP)
752 timeout = 15 * HZ;
753 /* wait for 15 seconds or until woken up due to response arriving or
754 due to last connection to this server being unmounted */
755 else if (long_op == CIFS_ASYNC_OP)
756 goto out;
757 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
758 timeout = 180 * HZ;
759 else if (long_op == CIFS_LONG_OP)
760 timeout = 45 * HZ; /* should be greater than
761 servers oplock break timeout (about 43 seconds) */
762 else if (long_op == CIFS_BLOCKING_OP)
763 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
764 else {
765 cERROR(1, ("unknown timeout flag %d", long_op));
766 rc = -EIO;
767 goto out;
770 if (signal_pending(current)) {
771 /* if signal pending do not hold up user for full smb timeout
772 but we still give response a chance to complete */
773 timeout = 2 * HZ;
776 /* No user interrupts in wait - wreaks havoc with performance */
777 wait_for_response(ses, midQ, timeout, 10 * HZ);
779 spin_lock(&GlobalMid_Lock);
780 if (midQ->resp_buf == NULL) {
781 cERROR(1, ("No response for cmd %d mid %d",
782 midQ->command, midQ->mid));
783 if (midQ->midState == MID_REQUEST_SUBMITTED) {
784 if (ses->server->tcpStatus == CifsExiting)
785 rc = -EHOSTDOWN;
786 else {
787 ses->server->tcpStatus = CifsNeedReconnect;
788 midQ->midState = MID_RETRY_NEEDED;
792 if (rc != -EHOSTDOWN) {
793 if (midQ->midState == MID_RETRY_NEEDED) {
794 rc = -EAGAIN;
795 cFYI(1, ("marking request for retry"));
796 } else {
797 rc = -EIO;
800 spin_unlock(&GlobalMid_Lock);
801 DeleteMidQEntry(midQ);
802 /* Update # of requests on wire to server */
803 atomic_dec(&ses->server->inFlight);
804 wake_up(&ses->server->request_q);
805 return rc;
808 spin_unlock(&GlobalMid_Lock);
809 receive_len = midQ->resp_buf->smb_buf_length;
811 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
812 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
813 receive_len, xid));
814 rc = -EIO;
815 goto out;
818 /* rcvd frame is ok */
820 if (midQ->resp_buf && out_buf
821 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
822 out_buf->smb_buf_length = receive_len;
823 memcpy((char *)out_buf + 4,
824 (char *)midQ->resp_buf + 4,
825 receive_len);
827 dump_smb(out_buf, 92);
828 /* convert the length into a more usable form */
829 if ((receive_len > 24) &&
830 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
831 SECMODE_SIGN_ENABLED))) {
832 rc = cifs_verify_signature(out_buf,
833 &ses->server->mac_signing_key,
834 midQ->sequence_number+1);
835 if (rc) {
836 cERROR(1, ("Unexpected SMB signature"));
837 /* BB FIXME add code to kill session */
841 *pbytes_returned = out_buf->smb_buf_length;
843 /* BB special case reconnect tid and uid here? */
844 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
846 /* convert ByteCount if necessary */
847 if (receive_len >= sizeof(struct smb_hdr) - 4
848 /* do not count RFC1001 header */ +
849 (2 * out_buf->WordCount) + 2 /* bcc */ )
850 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
851 } else {
852 rc = -EIO;
853 cERROR(1, ("Bad MID state?"));
856 out:
857 DeleteMidQEntry(midQ);
858 atomic_dec(&ses->server->inFlight);
859 wake_up(&ses->server->request_q);
861 return rc;
864 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
866 static int
867 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
868 struct mid_q_entry *midQ)
870 int rc = 0;
871 struct cifsSesInfo *ses = tcon->ses;
872 __u16 mid = in_buf->Mid;
874 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
875 in_buf->Mid = mid;
876 mutex_lock(&ses->server->srv_mutex);
877 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
878 if (rc) {
879 mutex_unlock(&ses->server->srv_mutex);
880 return rc;
882 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
883 (struct sockaddr *) &(ses->server->addr.sockAddr),
884 ses->server->noblocksnd);
885 mutex_unlock(&ses->server->srv_mutex);
886 return rc;
889 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
890 blocking lock to return. */
892 static int
893 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
894 struct smb_hdr *in_buf,
895 struct smb_hdr *out_buf)
897 int bytes_returned;
898 struct cifsSesInfo *ses = tcon->ses;
899 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
901 /* We just modify the current in_buf to change
902 the type of lock from LOCKING_ANDX_SHARED_LOCK
903 or LOCKING_ANDX_EXCLUSIVE_LOCK to
904 LOCKING_ANDX_CANCEL_LOCK. */
906 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
907 pSMB->Timeout = 0;
908 pSMB->hdr.Mid = GetNextMid(ses->server);
910 return SendReceive(xid, ses, in_buf, out_buf,
911 &bytes_returned, CIFS_STD_OP);
915 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
916 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
917 int *pbytes_returned)
919 int rc = 0;
920 int rstart = 0;
921 unsigned int receive_len;
922 struct mid_q_entry *midQ;
923 struct cifsSesInfo *ses;
925 if (tcon == NULL || tcon->ses == NULL) {
926 cERROR(1, ("Null smb session"));
927 return -EIO;
929 ses = tcon->ses;
931 if (ses->server == NULL) {
932 cERROR(1, ("Null tcp session"));
933 return -EIO;
936 if (ses->server->tcpStatus == CifsExiting)
937 return -ENOENT;
939 /* Ensure that we do not send more than 50 overlapping requests
940 to the same server. We may make this configurable later or
941 use ses->maxReq */
943 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
944 cERROR(1, ("Illegal length, greater than maximum frame, %d",
945 in_buf->smb_buf_length));
946 return -EIO;
949 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
950 if (rc)
951 return rc;
953 /* make sure that we sign in the same order that we send on this socket
954 and avoid races inside tcp sendmsg code that could cause corruption
955 of smb data */
957 mutex_lock(&ses->server->srv_mutex);
959 rc = allocate_mid(ses, in_buf, &midQ);
960 if (rc) {
961 mutex_unlock(&ses->server->srv_mutex);
962 return rc;
965 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
966 if (rc) {
967 DeleteMidQEntry(midQ);
968 mutex_unlock(&ses->server->srv_mutex);
969 return rc;
972 midQ->midState = MID_REQUEST_SUBMITTED;
973 #ifdef CONFIG_CIFS_STATS2
974 atomic_inc(&ses->server->inSend);
975 #endif
976 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
977 (struct sockaddr *) &(ses->server->addr.sockAddr),
978 ses->server->noblocksnd);
979 #ifdef CONFIG_CIFS_STATS2
980 atomic_dec(&ses->server->inSend);
981 midQ->when_sent = jiffies;
982 #endif
983 mutex_unlock(&ses->server->srv_mutex);
985 if (rc < 0) {
986 DeleteMidQEntry(midQ);
987 return rc;
990 /* Wait for a reply - allow signals to interrupt. */
991 rc = wait_event_interruptible(ses->server->response_q,
992 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
993 ((ses->server->tcpStatus != CifsGood) &&
994 (ses->server->tcpStatus != CifsNew)));
996 /* Were we interrupted by a signal ? */
997 if ((rc == -ERESTARTSYS) &&
998 (midQ->midState == MID_REQUEST_SUBMITTED) &&
999 ((ses->server->tcpStatus == CifsGood) ||
1000 (ses->server->tcpStatus == CifsNew))) {
1002 if (in_buf->Command == SMB_COM_TRANSACTION2) {
1003 /* POSIX lock. We send a NT_CANCEL SMB to cause the
1004 blocking lock to return. */
1006 rc = send_nt_cancel(tcon, in_buf, midQ);
1007 if (rc) {
1008 DeleteMidQEntry(midQ);
1009 return rc;
1011 } else {
1012 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
1013 to cause the blocking lock to return. */
1015 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1017 /* If we get -ENOLCK back the lock may have
1018 already been removed. Don't exit in this case. */
1019 if (rc && rc != -ENOLCK) {
1020 DeleteMidQEntry(midQ);
1021 return rc;
1025 /* Wait 5 seconds for the response. */
1026 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
1027 /* We got the response - restart system call. */
1028 rstart = 1;
1032 spin_lock(&GlobalMid_Lock);
1033 if (midQ->resp_buf) {
1034 spin_unlock(&GlobalMid_Lock);
1035 receive_len = midQ->resp_buf->smb_buf_length;
1036 } else {
1037 cERROR(1, ("No response for cmd %d mid %d",
1038 midQ->command, midQ->mid));
1039 if (midQ->midState == MID_REQUEST_SUBMITTED) {
1040 if (ses->server->tcpStatus == CifsExiting)
1041 rc = -EHOSTDOWN;
1042 else {
1043 ses->server->tcpStatus = CifsNeedReconnect;
1044 midQ->midState = MID_RETRY_NEEDED;
1048 if (rc != -EHOSTDOWN) {
1049 if (midQ->midState == MID_RETRY_NEEDED) {
1050 rc = -EAGAIN;
1051 cFYI(1, ("marking request for retry"));
1052 } else {
1053 rc = -EIO;
1056 spin_unlock(&GlobalMid_Lock);
1057 DeleteMidQEntry(midQ);
1058 return rc;
1061 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1062 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1063 receive_len, xid));
1064 rc = -EIO;
1065 goto out;
1068 /* rcvd frame is ok */
1070 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
1071 rc = -EIO;
1072 cERROR(1, ("Bad MID state?"));
1073 goto out;
1076 out_buf->smb_buf_length = receive_len;
1077 memcpy((char *)out_buf + 4,
1078 (char *)midQ->resp_buf + 4,
1079 receive_len);
1081 dump_smb(out_buf, 92);
1082 /* convert the length into a more usable form */
1083 if ((receive_len > 24) &&
1084 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1085 SECMODE_SIGN_ENABLED))) {
1086 rc = cifs_verify_signature(out_buf,
1087 &ses->server->mac_signing_key,
1088 midQ->sequence_number+1);
1089 if (rc) {
1090 cERROR(1, ("Unexpected SMB signature"));
1091 /* BB FIXME add code to kill session */
1095 *pbytes_returned = out_buf->smb_buf_length;
1097 /* BB special case reconnect tid and uid here? */
1098 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1100 /* convert ByteCount if necessary */
1101 if (receive_len >= sizeof(struct smb_hdr) - 4
1102 /* do not count RFC1001 header */ +
1103 (2 * out_buf->WordCount) + 2 /* bcc */ )
1104 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1106 out:
1107 DeleteMidQEntry(midQ);
1108 if (rstart && rc == -EACCES)
1109 return -ERESTARTSYS;
1110 return rc;