cifs: turn smb_send into a wrapper around smb_sendv
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / cifs / transport.c
blob2c7efd26992de25cc7f1dde83c158d2c28668fa2
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);
157 static int
158 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
160 int rc = 0;
161 int i = 0;
162 struct msghdr smb_msg;
163 struct smb_hdr *smb_buffer = iov[0].iov_base;
164 unsigned int len = iov[0].iov_len;
165 unsigned int total_len;
166 int first_vec = 0;
167 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
168 struct socket *ssocket = server->ssocket;
170 if (ssocket == NULL)
171 return -ENOTSOCK; /* BB eventually add reconnect code here */
173 smb_msg.msg_name = (struct sockaddr *) &server->addr.sockAddr;
174 smb_msg.msg_namelen = sizeof(struct sockaddr);
175 smb_msg.msg_control = NULL;
176 smb_msg.msg_controllen = 0;
177 if (server->noblocksnd)
178 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
179 else
180 smb_msg.msg_flags = MSG_NOSIGNAL;
182 /* smb header is converted in header_assemble. bcc and rest of SMB word
183 area, and byte area if necessary, is converted to littleendian in
184 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
185 Flags2 is converted in SendReceive */
188 total_len = 0;
189 for (i = 0; i < n_vec; i++)
190 total_len += iov[i].iov_len;
192 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
193 cFYI(1, ("Sending smb: total_len %d", total_len));
194 dump_smb(smb_buffer, len);
196 i = 0;
197 while (total_len) {
198 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
199 n_vec - first_vec, total_len);
200 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
201 i++;
202 if (i >= 14) {
203 cERROR(1,
204 ("sends on sock %p stuck for 15 seconds",
205 ssocket));
206 rc = -EAGAIN;
207 break;
209 msleep(1 << i);
210 continue;
212 if (rc < 0)
213 break;
215 if (rc == total_len) {
216 total_len = 0;
217 break;
218 } else if (rc > total_len) {
219 cERROR(1, ("sent %d requested %d", rc, total_len));
220 break;
222 if (rc == 0) {
223 /* should never happen, letting socket clear before
224 retrying is our only obvious option here */
225 cERROR(1, ("tcp sent no data"));
226 msleep(500);
227 continue;
229 total_len -= rc;
230 /* the line below resets i */
231 for (i = first_vec; i < n_vec; i++) {
232 if (iov[i].iov_len) {
233 if (rc > iov[i].iov_len) {
234 rc -= iov[i].iov_len;
235 iov[i].iov_len = 0;
236 } else {
237 iov[i].iov_base += rc;
238 iov[i].iov_len -= rc;
239 first_vec = i;
240 break;
244 i = 0; /* in case we get ENOSPC on the next send */
247 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
248 cFYI(1, ("partial send (%d remaining), terminating session",
249 total_len));
250 /* If we have only sent part of an SMB then the next SMB
251 could be taken as the remainder of this one. We need
252 to kill the socket so the server throws away the partial
253 SMB */
254 server->tcpStatus = CifsNeedReconnect;
257 if (rc < 0) {
258 cERROR(1, ("Error %d sending data on socket to server", rc));
259 } else
260 rc = 0;
262 /* Don't want to modify the buffer as a
263 side effect of this call. */
264 smb_buffer->smb_buf_length = smb_buf_length;
266 return rc;
270 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
271 unsigned int smb_buf_length)
273 struct kvec iov;
275 iov.iov_base = smb_buffer;
276 iov.iov_len = smb_buf_length + 4;
278 return smb_sendv(server, &iov, 1);
281 static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
283 if (long_op == CIFS_ASYNC_OP) {
284 /* oplock breaks must not be held up */
285 atomic_inc(&ses->server->inFlight);
286 return 0;
289 spin_lock(&GlobalMid_Lock);
290 while (1) {
291 if (atomic_read(&ses->server->inFlight) >=
292 cifs_max_pending){
293 spin_unlock(&GlobalMid_Lock);
294 #ifdef CONFIG_CIFS_STATS2
295 atomic_inc(&ses->server->num_waiters);
296 #endif
297 wait_event(ses->server->request_q,
298 atomic_read(&ses->server->inFlight)
299 < cifs_max_pending);
300 #ifdef CONFIG_CIFS_STATS2
301 atomic_dec(&ses->server->num_waiters);
302 #endif
303 spin_lock(&GlobalMid_Lock);
304 } else {
305 if (ses->server->tcpStatus == CifsExiting) {
306 spin_unlock(&GlobalMid_Lock);
307 return -ENOENT;
310 /* can not count locking commands against total
311 as they are allowed to block on server */
313 /* update # of requests on the wire to server */
314 if (long_op != CIFS_BLOCKING_OP)
315 atomic_inc(&ses->server->inFlight);
316 spin_unlock(&GlobalMid_Lock);
317 break;
320 return 0;
323 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
324 struct mid_q_entry **ppmidQ)
326 if (ses->server->tcpStatus == CifsExiting) {
327 return -ENOENT;
330 if (ses->server->tcpStatus == CifsNeedReconnect) {
331 cFYI(1, ("tcp session dead - return to caller to retry"));
332 return -EAGAIN;
335 if (ses->status != CifsGood) {
336 /* check if SMB session is bad because we are setting it up */
337 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
338 (in_buf->Command != SMB_COM_NEGOTIATE))
339 return -EAGAIN;
340 /* else ok - we are setting up session */
342 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
343 if (*ppmidQ == NULL)
344 return -ENOMEM;
345 return 0;
348 static int wait_for_response(struct cifsSesInfo *ses,
349 struct mid_q_entry *midQ,
350 unsigned long timeout,
351 unsigned long time_to_wait)
353 unsigned long curr_timeout;
355 for (;;) {
356 curr_timeout = timeout + jiffies;
357 wait_event_timeout(ses->server->response_q,
358 midQ->midState != MID_REQUEST_SUBMITTED, timeout);
360 if (time_after(jiffies, curr_timeout) &&
361 (midQ->midState == MID_REQUEST_SUBMITTED) &&
362 ((ses->server->tcpStatus == CifsGood) ||
363 (ses->server->tcpStatus == CifsNew))) {
365 unsigned long lrt;
367 /* We timed out. Is the server still
368 sending replies ? */
369 spin_lock(&GlobalMid_Lock);
370 lrt = ses->server->lstrp;
371 spin_unlock(&GlobalMid_Lock);
373 /* Calculate time_to_wait past last receive time.
374 Although we prefer not to time out if the
375 server is still responding - we will time
376 out if the server takes more than 15 (or 45
377 or 180) seconds to respond to this request
378 and has not responded to any request from
379 other threads on the client within 10 seconds */
380 lrt += time_to_wait;
381 if (time_after(jiffies, lrt)) {
382 /* No replies for time_to_wait. */
383 cERROR(1, ("server not responding"));
384 return -1;
386 } else {
387 return 0;
395 * Send an SMB Request. No response info (other than return code)
396 * needs to be parsed.
398 * flags indicate the type of request buffer and how long to wait
399 * and whether to log NT STATUS code (error) before mapping it to POSIX error
403 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
404 struct smb_hdr *in_buf, int flags)
406 int rc;
407 struct kvec iov[1];
408 int resp_buf_type;
410 iov[0].iov_base = (char *)in_buf;
411 iov[0].iov_len = in_buf->smb_buf_length + 4;
412 flags |= CIFS_NO_RESP;
413 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
414 cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc));
416 return rc;
420 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
421 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
422 const int flags)
424 int rc = 0;
425 int long_op;
426 unsigned int receive_len;
427 unsigned long timeout;
428 struct mid_q_entry *midQ;
429 struct smb_hdr *in_buf = iov[0].iov_base;
431 long_op = flags & CIFS_TIMEOUT_MASK;
433 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
435 if ((ses == NULL) || (ses->server == NULL)) {
436 cifs_small_buf_release(in_buf);
437 cERROR(1, ("Null session"));
438 return -EIO;
441 if (ses->server->tcpStatus == CifsExiting) {
442 cifs_small_buf_release(in_buf);
443 return -ENOENT;
446 /* Ensure that we do not send more than 50 overlapping requests
447 to the same server. We may make this configurable later or
448 use ses->maxReq */
450 rc = wait_for_free_request(ses, long_op);
451 if (rc) {
452 cifs_small_buf_release(in_buf);
453 return rc;
456 /* make sure that we sign in the same order that we send on this socket
457 and avoid races inside tcp sendmsg code that could cause corruption
458 of smb data */
460 mutex_lock(&ses->server->srv_mutex);
462 rc = allocate_mid(ses, in_buf, &midQ);
463 if (rc) {
464 mutex_unlock(&ses->server->srv_mutex);
465 cifs_small_buf_release(in_buf);
466 /* Update # of requests on wire to server */
467 atomic_dec(&ses->server->inFlight);
468 wake_up(&ses->server->request_q);
469 return rc;
471 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
472 if (rc) {
473 mutex_unlock(&ses->server->srv_mutex);
474 cifs_small_buf_release(in_buf);
475 goto out;
478 midQ->midState = MID_REQUEST_SUBMITTED;
479 #ifdef CONFIG_CIFS_STATS2
480 atomic_inc(&ses->server->inSend);
481 #endif
482 rc = smb_sendv(ses->server, iov, n_vec);
483 #ifdef CONFIG_CIFS_STATS2
484 atomic_dec(&ses->server->inSend);
485 midQ->when_sent = jiffies;
486 #endif
488 mutex_unlock(&ses->server->srv_mutex);
489 cifs_small_buf_release(in_buf);
491 if (rc < 0)
492 goto out;
494 if (long_op == CIFS_STD_OP)
495 timeout = 15 * HZ;
496 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
497 timeout = 180 * HZ;
498 else if (long_op == CIFS_LONG_OP)
499 timeout = 45 * HZ; /* should be greater than
500 servers oplock break timeout (about 43 seconds) */
501 else if (long_op == CIFS_ASYNC_OP)
502 goto out;
503 else if (long_op == CIFS_BLOCKING_OP)
504 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
505 else {
506 cERROR(1, ("unknown timeout flag %d", long_op));
507 rc = -EIO;
508 goto out;
511 /* wait for 15 seconds or until woken up due to response arriving or
512 due to last connection to this server being unmounted */
513 if (signal_pending(current)) {
514 /* if signal pending do not hold up user for full smb timeout
515 but we still give response a chance to complete */
516 timeout = 2 * HZ;
519 /* No user interrupts in wait - wreaks havoc with performance */
520 wait_for_response(ses, midQ, timeout, 10 * HZ);
522 spin_lock(&GlobalMid_Lock);
524 if (midQ->resp_buf == NULL) {
525 cERROR(1, ("No response to cmd %d mid %d",
526 midQ->command, midQ->mid));
527 if (midQ->midState == MID_REQUEST_SUBMITTED) {
528 if (ses->server->tcpStatus == CifsExiting)
529 rc = -EHOSTDOWN;
530 else {
531 ses->server->tcpStatus = CifsNeedReconnect;
532 midQ->midState = MID_RETRY_NEEDED;
536 if (rc != -EHOSTDOWN) {
537 if (midQ->midState == MID_RETRY_NEEDED) {
538 rc = -EAGAIN;
539 cFYI(1, ("marking request for retry"));
540 } else {
541 rc = -EIO;
544 spin_unlock(&GlobalMid_Lock);
545 DeleteMidQEntry(midQ);
546 /* Update # of requests on wire to server */
547 atomic_dec(&ses->server->inFlight);
548 wake_up(&ses->server->request_q);
549 return rc;
552 spin_unlock(&GlobalMid_Lock);
553 receive_len = midQ->resp_buf->smb_buf_length;
555 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
556 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
557 receive_len, xid));
558 rc = -EIO;
559 goto out;
562 /* rcvd frame is ok */
564 if (midQ->resp_buf &&
565 (midQ->midState == MID_RESPONSE_RECEIVED)) {
567 iov[0].iov_base = (char *)midQ->resp_buf;
568 if (midQ->largeBuf)
569 *pRespBufType = CIFS_LARGE_BUFFER;
570 else
571 *pRespBufType = CIFS_SMALL_BUFFER;
572 iov[0].iov_len = receive_len + 4;
574 dump_smb(midQ->resp_buf, 80);
575 /* convert the length into a more usable form */
576 if ((receive_len > 24) &&
577 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
578 SECMODE_SIGN_ENABLED))) {
579 rc = cifs_verify_signature(midQ->resp_buf,
580 &ses->server->mac_signing_key,
581 midQ->sequence_number+1);
582 if (rc) {
583 cERROR(1, ("Unexpected SMB signature"));
584 /* BB FIXME add code to kill session */
588 /* BB special case reconnect tid and uid here? */
589 rc = map_smb_to_linux_error(midQ->resp_buf,
590 flags & CIFS_LOG_ERROR);
592 /* convert ByteCount if necessary */
593 if (receive_len >= sizeof(struct smb_hdr) - 4
594 /* do not count RFC1001 header */ +
595 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
596 BCC(midQ->resp_buf) =
597 le16_to_cpu(BCC_LE(midQ->resp_buf));
598 if ((flags & CIFS_NO_RESP) == 0)
599 midQ->resp_buf = NULL; /* mark it so buf will
600 not be freed by
601 DeleteMidQEntry */
602 } else {
603 rc = -EIO;
604 cFYI(1, ("Bad MID state?"));
607 out:
608 DeleteMidQEntry(midQ);
609 atomic_dec(&ses->server->inFlight);
610 wake_up(&ses->server->request_q);
612 return rc;
616 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
617 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
618 int *pbytes_returned, const int long_op)
620 int rc = 0;
621 unsigned int receive_len;
622 unsigned long timeout;
623 struct mid_q_entry *midQ;
625 if (ses == NULL) {
626 cERROR(1, ("Null smb session"));
627 return -EIO;
629 if (ses->server == NULL) {
630 cERROR(1, ("Null tcp session"));
631 return -EIO;
634 if (ses->server->tcpStatus == CifsExiting)
635 return -ENOENT;
637 /* Ensure that we do not send more than 50 overlapping requests
638 to the same server. We may make this configurable later or
639 use ses->maxReq */
641 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
642 cERROR(1, ("Illegal length, greater than maximum frame, %d",
643 in_buf->smb_buf_length));
644 return -EIO;
647 rc = wait_for_free_request(ses, long_op);
648 if (rc)
649 return rc;
651 /* make sure that we sign in the same order that we send on this socket
652 and avoid races inside tcp sendmsg code that could cause corruption
653 of smb data */
655 mutex_lock(&ses->server->srv_mutex);
657 rc = allocate_mid(ses, in_buf, &midQ);
658 if (rc) {
659 mutex_unlock(&ses->server->srv_mutex);
660 /* Update # of requests on wire to server */
661 atomic_dec(&ses->server->inFlight);
662 wake_up(&ses->server->request_q);
663 return rc;
666 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
667 if (rc) {
668 mutex_unlock(&ses->server->srv_mutex);
669 goto out;
672 midQ->midState = MID_REQUEST_SUBMITTED;
673 #ifdef CONFIG_CIFS_STATS2
674 atomic_inc(&ses->server->inSend);
675 #endif
676 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
677 #ifdef CONFIG_CIFS_STATS2
678 atomic_dec(&ses->server->inSend);
679 midQ->when_sent = jiffies;
680 #endif
681 mutex_unlock(&ses->server->srv_mutex);
683 if (rc < 0)
684 goto out;
686 if (long_op == CIFS_STD_OP)
687 timeout = 15 * HZ;
688 /* wait for 15 seconds or until woken up due to response arriving or
689 due to last connection to this server being unmounted */
690 else if (long_op == CIFS_ASYNC_OP)
691 goto out;
692 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
693 timeout = 180 * HZ;
694 else if (long_op == CIFS_LONG_OP)
695 timeout = 45 * HZ; /* should be greater than
696 servers oplock break timeout (about 43 seconds) */
697 else if (long_op == CIFS_BLOCKING_OP)
698 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
699 else {
700 cERROR(1, ("unknown timeout flag %d", long_op));
701 rc = -EIO;
702 goto out;
705 if (signal_pending(current)) {
706 /* if signal pending do not hold up user for full smb timeout
707 but we still give response a chance to complete */
708 timeout = 2 * HZ;
711 /* No user interrupts in wait - wreaks havoc with performance */
712 wait_for_response(ses, midQ, timeout, 10 * HZ);
714 spin_lock(&GlobalMid_Lock);
715 if (midQ->resp_buf == NULL) {
716 cERROR(1, ("No response for cmd %d mid %d",
717 midQ->command, midQ->mid));
718 if (midQ->midState == MID_REQUEST_SUBMITTED) {
719 if (ses->server->tcpStatus == CifsExiting)
720 rc = -EHOSTDOWN;
721 else {
722 ses->server->tcpStatus = CifsNeedReconnect;
723 midQ->midState = MID_RETRY_NEEDED;
727 if (rc != -EHOSTDOWN) {
728 if (midQ->midState == MID_RETRY_NEEDED) {
729 rc = -EAGAIN;
730 cFYI(1, ("marking request for retry"));
731 } else {
732 rc = -EIO;
735 spin_unlock(&GlobalMid_Lock);
736 DeleteMidQEntry(midQ);
737 /* Update # of requests on wire to server */
738 atomic_dec(&ses->server->inFlight);
739 wake_up(&ses->server->request_q);
740 return rc;
743 spin_unlock(&GlobalMid_Lock);
744 receive_len = midQ->resp_buf->smb_buf_length;
746 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
747 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
748 receive_len, xid));
749 rc = -EIO;
750 goto out;
753 /* rcvd frame is ok */
755 if (midQ->resp_buf && out_buf
756 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
757 out_buf->smb_buf_length = receive_len;
758 memcpy((char *)out_buf + 4,
759 (char *)midQ->resp_buf + 4,
760 receive_len);
762 dump_smb(out_buf, 92);
763 /* convert the length into a more usable form */
764 if ((receive_len > 24) &&
765 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
766 SECMODE_SIGN_ENABLED))) {
767 rc = cifs_verify_signature(out_buf,
768 &ses->server->mac_signing_key,
769 midQ->sequence_number+1);
770 if (rc) {
771 cERROR(1, ("Unexpected SMB signature"));
772 /* BB FIXME add code to kill session */
776 *pbytes_returned = out_buf->smb_buf_length;
778 /* BB special case reconnect tid and uid here? */
779 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
781 /* convert ByteCount if necessary */
782 if (receive_len >= sizeof(struct smb_hdr) - 4
783 /* do not count RFC1001 header */ +
784 (2 * out_buf->WordCount) + 2 /* bcc */ )
785 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
786 } else {
787 rc = -EIO;
788 cERROR(1, ("Bad MID state?"));
791 out:
792 DeleteMidQEntry(midQ);
793 atomic_dec(&ses->server->inFlight);
794 wake_up(&ses->server->request_q);
796 return rc;
799 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
801 static int
802 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
803 struct mid_q_entry *midQ)
805 int rc = 0;
806 struct cifsSesInfo *ses = tcon->ses;
807 __u16 mid = in_buf->Mid;
809 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
810 in_buf->Mid = mid;
811 mutex_lock(&ses->server->srv_mutex);
812 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
813 if (rc) {
814 mutex_unlock(&ses->server->srv_mutex);
815 return rc;
817 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
818 mutex_unlock(&ses->server->srv_mutex);
819 return rc;
822 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
823 blocking lock to return. */
825 static int
826 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
827 struct smb_hdr *in_buf,
828 struct smb_hdr *out_buf)
830 int bytes_returned;
831 struct cifsSesInfo *ses = tcon->ses;
832 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
834 /* We just modify the current in_buf to change
835 the type of lock from LOCKING_ANDX_SHARED_LOCK
836 or LOCKING_ANDX_EXCLUSIVE_LOCK to
837 LOCKING_ANDX_CANCEL_LOCK. */
839 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
840 pSMB->Timeout = 0;
841 pSMB->hdr.Mid = GetNextMid(ses->server);
843 return SendReceive(xid, ses, in_buf, out_buf,
844 &bytes_returned, CIFS_STD_OP);
848 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
849 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
850 int *pbytes_returned)
852 int rc = 0;
853 int rstart = 0;
854 unsigned int receive_len;
855 struct mid_q_entry *midQ;
856 struct cifsSesInfo *ses;
858 if (tcon == NULL || tcon->ses == NULL) {
859 cERROR(1, ("Null smb session"));
860 return -EIO;
862 ses = tcon->ses;
864 if (ses->server == NULL) {
865 cERROR(1, ("Null tcp session"));
866 return -EIO;
869 if (ses->server->tcpStatus == CifsExiting)
870 return -ENOENT;
872 /* Ensure that we do not send more than 50 overlapping requests
873 to the same server. We may make this configurable later or
874 use ses->maxReq */
876 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
877 cERROR(1, ("Illegal length, greater than maximum frame, %d",
878 in_buf->smb_buf_length));
879 return -EIO;
882 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
883 if (rc)
884 return rc;
886 /* make sure that we sign in the same order that we send on this socket
887 and avoid races inside tcp sendmsg code that could cause corruption
888 of smb data */
890 mutex_lock(&ses->server->srv_mutex);
892 rc = allocate_mid(ses, in_buf, &midQ);
893 if (rc) {
894 mutex_unlock(&ses->server->srv_mutex);
895 return rc;
898 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
899 if (rc) {
900 DeleteMidQEntry(midQ);
901 mutex_unlock(&ses->server->srv_mutex);
902 return rc;
905 midQ->midState = MID_REQUEST_SUBMITTED;
906 #ifdef CONFIG_CIFS_STATS2
907 atomic_inc(&ses->server->inSend);
908 #endif
909 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
910 #ifdef CONFIG_CIFS_STATS2
911 atomic_dec(&ses->server->inSend);
912 midQ->when_sent = jiffies;
913 #endif
914 mutex_unlock(&ses->server->srv_mutex);
916 if (rc < 0) {
917 DeleteMidQEntry(midQ);
918 return rc;
921 /* Wait for a reply - allow signals to interrupt. */
922 rc = wait_event_interruptible(ses->server->response_q,
923 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
924 ((ses->server->tcpStatus != CifsGood) &&
925 (ses->server->tcpStatus != CifsNew)));
927 /* Were we interrupted by a signal ? */
928 if ((rc == -ERESTARTSYS) &&
929 (midQ->midState == MID_REQUEST_SUBMITTED) &&
930 ((ses->server->tcpStatus == CifsGood) ||
931 (ses->server->tcpStatus == CifsNew))) {
933 if (in_buf->Command == SMB_COM_TRANSACTION2) {
934 /* POSIX lock. We send a NT_CANCEL SMB to cause the
935 blocking lock to return. */
937 rc = send_nt_cancel(tcon, in_buf, midQ);
938 if (rc) {
939 DeleteMidQEntry(midQ);
940 return rc;
942 } else {
943 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
944 to cause the blocking lock to return. */
946 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
948 /* If we get -ENOLCK back the lock may have
949 already been removed. Don't exit in this case. */
950 if (rc && rc != -ENOLCK) {
951 DeleteMidQEntry(midQ);
952 return rc;
956 /* Wait 5 seconds for the response. */
957 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
958 /* We got the response - restart system call. */
959 rstart = 1;
963 spin_lock(&GlobalMid_Lock);
964 if (midQ->resp_buf) {
965 spin_unlock(&GlobalMid_Lock);
966 receive_len = midQ->resp_buf->smb_buf_length;
967 } else {
968 cERROR(1, ("No response for cmd %d mid %d",
969 midQ->command, midQ->mid));
970 if (midQ->midState == MID_REQUEST_SUBMITTED) {
971 if (ses->server->tcpStatus == CifsExiting)
972 rc = -EHOSTDOWN;
973 else {
974 ses->server->tcpStatus = CifsNeedReconnect;
975 midQ->midState = MID_RETRY_NEEDED;
979 if (rc != -EHOSTDOWN) {
980 if (midQ->midState == MID_RETRY_NEEDED) {
981 rc = -EAGAIN;
982 cFYI(1, ("marking request for retry"));
983 } else {
984 rc = -EIO;
987 spin_unlock(&GlobalMid_Lock);
988 DeleteMidQEntry(midQ);
989 return rc;
992 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
993 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
994 receive_len, xid));
995 rc = -EIO;
996 goto out;
999 /* rcvd frame is ok */
1001 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
1002 rc = -EIO;
1003 cERROR(1, ("Bad MID state?"));
1004 goto out;
1007 out_buf->smb_buf_length = receive_len;
1008 memcpy((char *)out_buf + 4,
1009 (char *)midQ->resp_buf + 4,
1010 receive_len);
1012 dump_smb(out_buf, 92);
1013 /* convert the length into a more usable form */
1014 if ((receive_len > 24) &&
1015 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1016 SECMODE_SIGN_ENABLED))) {
1017 rc = cifs_verify_signature(out_buf,
1018 &ses->server->mac_signing_key,
1019 midQ->sequence_number+1);
1020 if (rc) {
1021 cERROR(1, ("Unexpected SMB signature"));
1022 /* BB FIXME add code to kill session */
1026 *pbytes_returned = out_buf->smb_buf_length;
1028 /* BB special case reconnect tid and uid here? */
1029 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
1031 /* convert ByteCount if necessary */
1032 if (receive_len >= sizeof(struct smb_hdr) - 4
1033 /* do not count RFC1001 header */ +
1034 (2 * out_buf->WordCount) + 2 /* bcc */ )
1035 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1037 out:
1038 DeleteMidQEntry(midQ);
1039 if (rstart && rc == -EACCES)
1040 return -ERESTARTSYS;
1041 return rc;