do_wait reorganization
[linux-2.6/mini2440.git] / fs / cifs / transport.c
blob000ac509c98a32e884322149e88b53e4bdb2a4c1
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 cifsSesInfo *ses)
42 struct mid_q_entry *temp;
44 if (ses == NULL) {
45 cERROR(1, ("Null session passed in to AllocMidQEntry"));
46 return NULL;
48 if (ses->server == NULL) {
49 cERROR(1, ("Null TCP session in AllocMidQEntry"));
50 return NULL;
53 temp = (struct mid_q_entry *) mempool_alloc(cifs_mid_poolp,
54 GFP_KERNEL | GFP_NOFS);
55 if (temp == NULL)
56 return temp;
57 else {
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;
66 temp->ses = ses;
67 temp->tsk = current;
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);
75 return temp;
78 static void
79 DeleteMidQEntry(struct mid_q_entry *midEntry)
81 #ifdef CONFIG_CIFS_STATS2
82 unsigned long now;
83 #endif
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);
91 else
92 cifs_small_buf_release(midEntry->resp_buf);
93 #ifdef CONFIG_CIFS_STATS2
94 now = jiffies;
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);
108 #endif
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"));
118 return NULL;
120 temp = (struct oplock_q_entry *) kmem_cache_alloc(cifs_oplock_cachep,
121 GFP_KERNEL);
122 if (temp == NULL)
123 return temp;
124 else {
125 temp->pinode = pinode;
126 temp->tcon = tcon;
127 temp->netfid = fid;
128 spin_lock(&GlobalMid_Lock);
129 list_add_tail(&temp->qhead, &GlobalOplock_Q);
130 spin_unlock(&GlobalMid_Lock);
132 return temp;
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;
150 if (tcon == NULL)
151 return;
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)
167 int rc = 0;
168 int i = 0;
169 struct msghdr smb_msg;
170 struct kvec iov;
171 unsigned len = smb_buf_length + 4;
173 if (ssocket == NULL)
174 return -ENOTSOCK; /* BB eventually add reconnect code here */
175 iov.iov_base = smb_buffer;
176 iov.iov_len = len;
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);
193 while (len > 0) {
194 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
195 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
196 i++;
197 /* smaller timeout here than send2 since smaller size */
198 /* Although it may not be required, this also is smaller
199 oplock break time */
200 if (i > 12) {
201 cERROR(1,
202 ("sends on sock %p stuck for 7 seconds",
203 ssocket));
204 rc = -EAGAIN;
205 break;
207 msleep(1 << i);
208 continue;
210 if (rc < 0)
211 break;
212 else
213 i = 0; /* reset i after each successful send */
214 iov.iov_base += rc;
215 iov.iov_len -= rc;
216 len -= rc;
219 if (rc < 0) {
220 cERROR(1, ("Error %d sending data on socket to server", rc));
221 } else {
222 rc = 0;
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;
229 return rc;
232 static int
233 smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
234 struct sockaddr *sin)
236 int rc = 0;
237 int i = 0;
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;
242 int first_vec = 0;
243 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
245 if (ssocket == NULL)
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 */
260 total_len = 0;
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);
268 while (total_len) {
269 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
270 n_vec - first_vec, total_len);
271 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
272 i++;
273 if (i >= 14) {
274 cERROR(1,
275 ("sends on sock %p stuck for 15 seconds",
276 ssocket));
277 rc = -EAGAIN;
278 break;
280 msleep(1 << i);
281 continue;
283 if (rc < 0)
284 break;
286 if (rc >= total_len) {
287 WARN_ON(rc > total_len);
288 break;
290 if (rc == 0) {
291 /* should never happen, letting socket clear before
292 retrying is our only obvious option here */
293 cERROR(1, ("tcp sent no data"));
294 msleep(500);
295 continue;
297 total_len -= rc;
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;
303 iov[i].iov_len = 0;
304 } else {
305 iov[i].iov_base += rc;
306 iov[i].iov_len -= rc;
307 first_vec = i;
308 break;
312 i = 0; /* in case we get ENOSPC on the next send */
315 if (rc < 0) {
316 cERROR(1, ("Error %d sending data on socket to server", rc));
317 } else
318 rc = 0;
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;
324 return rc;
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);
332 } else {
333 spin_lock(&GlobalMid_Lock);
334 while (1) {
335 if (atomic_read(&ses->server->inFlight) >=
336 cifs_max_pending){
337 spin_unlock(&GlobalMid_Lock);
338 #ifdef CONFIG_CIFS_STATS2
339 atomic_inc(&ses->server->num_waiters);
340 #endif
341 wait_event(ses->server->request_q,
342 atomic_read(&ses->server->inFlight)
343 < cifs_max_pending);
344 #ifdef CONFIG_CIFS_STATS2
345 atomic_dec(&ses->server->num_waiters);
346 #endif
347 spin_lock(&GlobalMid_Lock);
348 } else {
349 if (ses->server->tcpStatus == CifsExiting) {
350 spin_unlock(&GlobalMid_Lock);
351 return -ENOENT;
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);
361 break;
365 return 0;
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) {
372 return -ENOENT;
373 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
374 cFYI(1, ("tcp session dead - return to caller to retry"));
375 return -EAGAIN;
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))
380 return -EAGAIN;
381 /* else ok - we are setting up session */
383 *ppmidQ = AllocMidQEntry(in_buf, ses);
384 if (*ppmidQ == NULL)
385 return -ENOMEM;
386 return 0;
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;
396 for (;;) {
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))) {
409 unsigned long lrt;
411 /* We timed out. Is the server still
412 sending replies ? */
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 */
424 lrt += time_to_wait;
425 if (time_after(jiffies, lrt)) {
426 /* No replies for time_to_wait. */
427 cERROR(1, ("server not responding"));
428 return -1;
430 } else {
431 return 0;
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)
450 int rc;
451 struct kvec iov[1];
452 int resp_buf_type;
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));
460 return rc;
464 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
465 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
466 const int flags)
468 int rc = 0;
469 int long_op;
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"));
482 return -EIO;
485 if (ses->server->tcpStatus == CifsExiting) {
486 cifs_small_buf_release(in_buf);
487 return -ENOENT;
490 /* Ensure that we do not send more than 50 overlapping requests
491 to the same server. We may make this configurable later or
492 use ses->maxReq */
494 rc = wait_for_free_request(ses, long_op);
495 if (rc) {
496 cifs_small_buf_release(in_buf);
497 return rc;
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
502 of smb data */
504 down(&ses->server->tcpSem);
506 rc = allocate_mid(ses, in_buf, &midQ);
507 if (rc) {
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);
513 return rc;
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);
520 #endif
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;
526 #endif
528 up(&ses->server->tcpSem);
529 cifs_small_buf_release(in_buf);
531 if (rc < 0)
532 goto out;
534 if (long_op == CIFS_STD_OP)
535 timeout = 15 * HZ;
536 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
537 timeout = 180 * HZ;
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)
542 goto out;
543 else if (long_op == CIFS_BLOCKING_OP)
544 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
545 else {
546 cERROR(1, ("unknown timeout flag %d", long_op));
547 rc = -EIO;
548 goto out;
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 */
556 timeout = 2 * HZ;
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;
566 } else {
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)
571 rc = -EHOSTDOWN;
572 else {
573 ses->server->tcpStatus = CifsNeedReconnect;
574 midQ->midState = MID_RETRY_NEEDED;
578 if (rc != -EHOSTDOWN) {
579 if (midQ->midState == MID_RETRY_NEEDED) {
580 rc = -EAGAIN;
581 cFYI(1, ("marking request for retry"));
582 } else {
583 rc = -EIO;
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);
591 return rc;
594 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
595 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
596 receive_len, xid));
597 rc = -EIO;
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;
603 if (midQ->largeBuf)
604 *pRespBufType = CIFS_LARGE_BUFFER;
605 else
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);
617 if (rc) {
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
635 not be freed by
636 DeleteMidQEntry */
637 } else {
638 rc = -EIO;
639 cFYI(1, ("Bad MID state?"));
643 out:
644 DeleteMidQEntry(midQ);
645 atomic_dec(&ses->server->inFlight);
646 wake_up(&ses->server->request_q);
648 return rc;
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)
656 int rc = 0;
657 unsigned int receive_len;
658 unsigned long timeout;
659 struct mid_q_entry *midQ;
661 if (ses == NULL) {
662 cERROR(1, ("Null smb session"));
663 return -EIO;
665 if (ses->server == NULL) {
666 cERROR(1, ("Null tcp session"));
667 return -EIO;
670 if (ses->server->tcpStatus == CifsExiting)
671 return -ENOENT;
673 /* Ensure that we do not send more than 50 overlapping requests
674 to the same server. We may make this configurable later or
675 use ses->maxReq */
677 rc = wait_for_free_request(ses, long_op);
678 if (rc)
679 return rc;
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
683 of smb data */
685 down(&ses->server->tcpSem);
687 rc = allocate_mid(ses, in_buf, &midQ);
688 if (rc) {
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);
693 return rc;
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);
704 return -EIO;
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);
712 #endif
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;
718 #endif
719 up(&ses->server->tcpSem);
721 if (rc < 0)
722 goto out;
724 if (long_op == CIFS_STD_OP)
725 timeout = 15 * HZ;
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)
729 goto out;
730 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
731 timeout = 180 * HZ;
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 */
737 else {
738 cERROR(1, ("unknown timeout flag %d", long_op));
739 rc = -EIO;
740 goto out;
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 */
746 timeout = 2 * HZ;
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;
756 } else {
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)
761 rc = -EHOSTDOWN;
762 else {
763 ses->server->tcpStatus = CifsNeedReconnect;
764 midQ->midState = MID_RETRY_NEEDED;
768 if (rc != -EHOSTDOWN) {
769 if (midQ->midState == MID_RETRY_NEEDED) {
770 rc = -EAGAIN;
771 cFYI(1, ("marking request for retry"));
772 } else {
773 rc = -EIO;
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);
781 return rc;
784 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
785 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
786 receive_len, xid));
787 rc = -EIO;
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,
795 receive_len);
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);
805 if (rc) {
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));
821 } else {
822 rc = -EIO;
823 cERROR(1, ("Bad MID state?"));
827 out:
828 DeleteMidQEntry(midQ);
829 atomic_dec(&ses->server->inFlight);
830 wake_up(&ses->server->request_q);
832 return rc;
835 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
837 static int
838 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
839 struct mid_q_entry *midQ)
841 int rc = 0;
842 struct cifsSesInfo *ses = tcon->ses;
843 __u16 mid = in_buf->Mid;
845 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
846 in_buf->Mid = mid;
847 down(&ses->server->tcpSem);
848 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
849 if (rc) {
850 up(&ses->server->tcpSem);
851 return rc;
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);
856 return rc;
859 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
860 blocking lock to return. */
862 static int
863 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
864 struct smb_hdr *in_buf,
865 struct smb_hdr *out_buf)
867 int bytes_returned;
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;
877 pSMB->Timeout = 0;
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)
889 int rc = 0;
890 int rstart = 0;
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"));
897 return -EIO;
899 ses = tcon->ses;
901 if (ses->server == NULL) {
902 cERROR(1, ("Null tcp session"));
903 return -EIO;
906 if (ses->server->tcpStatus == CifsExiting)
907 return -ENOENT;
909 /* Ensure that we do not send more than 50 overlapping requests
910 to the same server. We may make this configurable later or
911 use ses->maxReq */
913 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
914 if (rc)
915 return rc;
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
919 of smb data */
921 down(&ses->server->tcpSem);
923 rc = allocate_mid(ses, in_buf, &midQ);
924 if (rc) {
925 up(&ses->server->tcpSem);
926 return rc;
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);
934 return -EIO;
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);
942 #endif
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;
948 #endif
949 up(&ses->server->tcpSem);
951 if (rc < 0) {
952 DeleteMidQEntry(midQ);
953 return rc;
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);
973 if (rc) {
974 DeleteMidQEntry(midQ);
975 return rc;
977 } else {
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);
987 return rc;
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. */
994 rstart = 1;
998 spin_lock(&GlobalMid_Lock);
999 if (midQ->resp_buf) {
1000 spin_unlock(&GlobalMid_Lock);
1001 receive_len = midQ->resp_buf->smb_buf_length;
1002 } else {
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)
1007 rc = -EHOSTDOWN;
1008 else {
1009 ses->server->tcpStatus = CifsNeedReconnect;
1010 midQ->midState = MID_RETRY_NEEDED;
1014 if (rc != -EHOSTDOWN) {
1015 if (midQ->midState == MID_RETRY_NEEDED) {
1016 rc = -EAGAIN;
1017 cFYI(1, ("marking request for retry"));
1018 } else {
1019 rc = -EIO;
1022 spin_unlock(&GlobalMid_Lock);
1023 DeleteMidQEntry(midQ);
1024 return rc;
1027 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1028 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1029 receive_len, xid));
1030 rc = -EIO;
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,
1038 receive_len);
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);
1048 if (rc) {
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));
1064 } else {
1065 rc = -EIO;
1066 cERROR(1, ("Bad MID state?"));
1069 DeleteMidQEntry(midQ);
1070 if (rstart && rc == -EACCES)
1071 return -ERESTARTSYS;
1072 return rc;