cifs: don't reconnect server when we don't get a response
[deliverable/linux.git] / fs / cifs / transport.c
1 /*
2 * fs/cifs/transport.c
3 *
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.
7 *
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.
12 *
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.
17 *
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
21 */
22
23 #include <linux/fs.h>
24 #include <linux/list.h>
25 #include <linux/gfp.h>
26 #include <linux/wait.h>
27 #include <linux/net.h>
28 #include <linux/delay.h>
29 #include <asm/uaccess.h>
30 #include <asm/processor.h>
31 #include <linux/mempool.h>
32 #include "cifspdu.h"
33 #include "cifsglob.h"
34 #include "cifsproto.h"
35 #include "cifs_debug.h"
36
37 extern mempool_t *cifs_mid_poolp;
38
39 static struct mid_q_entry *
40 AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
41 {
42 struct mid_q_entry *temp;
43
44 if (server == NULL) {
45 cERROR(1, "Null TCP session in AllocMidQEntry");
46 return NULL;
47 }
48
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;
62 }
63
64 atomic_inc(&midCount);
65 temp->midState = MID_REQUEST_ALLOCATED;
66 return temp;
67 }
68
69 static void
70 DeleteMidQEntry(struct mid_q_entry *midEntry)
71 {
72 #ifdef CONFIG_CIFS_STATS2
73 unsigned long now;
74 #endif
75 midEntry->midState = MID_FREE;
76 atomic_dec(&midCount);
77 if (midEntry->largeBuf)
78 cifs_buf_release(midEntry->resp_buf);
79 else
80 cifs_small_buf_release(midEntry->resp_buf);
81 #ifdef CONFIG_CIFS_STATS2
82 now = jiffies;
83 /* commands taking longer than one second are indications that
84 something is wrong, unless it is quite a slow link or server */
85 if ((now - midEntry->when_alloc) > HZ) {
86 if ((cifsFYI & CIFS_TIMER) &&
87 (midEntry->command != SMB_COM_LOCKING_ANDX)) {
88 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d",
89 midEntry->command, midEntry->mid);
90 printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
91 now - midEntry->when_alloc,
92 now - midEntry->when_sent,
93 now - midEntry->when_received);
94 }
95 }
96 #endif
97 mempool_free(midEntry, cifs_mid_poolp);
98 }
99
100 static void
101 delete_mid(struct mid_q_entry *mid)
102 {
103 spin_lock(&GlobalMid_Lock);
104 list_del(&mid->qhead);
105 spin_unlock(&GlobalMid_Lock);
106
107 DeleteMidQEntry(mid);
108 }
109
110 static int
111 smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
112 {
113 int rc = 0;
114 int i = 0;
115 struct msghdr smb_msg;
116 struct smb_hdr *smb_buffer = iov[0].iov_base;
117 unsigned int len = iov[0].iov_len;
118 unsigned int total_len;
119 int first_vec = 0;
120 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
121 struct socket *ssocket = server->ssocket;
122
123 if (ssocket == NULL)
124 return -ENOTSOCK; /* BB eventually add reconnect code here */
125
126 smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
127 smb_msg.msg_namelen = sizeof(struct sockaddr);
128 smb_msg.msg_control = NULL;
129 smb_msg.msg_controllen = 0;
130 if (server->noblocksnd)
131 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
132 else
133 smb_msg.msg_flags = MSG_NOSIGNAL;
134
135 /* smb header is converted in header_assemble. bcc and rest of SMB word
136 area, and byte area if necessary, is converted to littleendian in
137 cifssmb.c and RFC1001 len is converted to bigendian in smb_send
138 Flags2 is converted in SendReceive */
139
140
141 total_len = 0;
142 for (i = 0; i < n_vec; i++)
143 total_len += iov[i].iov_len;
144
145 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
146 cFYI(1, "Sending smb: total_len %d", total_len);
147 dump_smb(smb_buffer, len);
148
149 i = 0;
150 while (total_len) {
151 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
152 n_vec - first_vec, total_len);
153 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
154 i++;
155 /* if blocking send we try 3 times, since each can block
156 for 5 seconds. For nonblocking we have to try more
157 but wait increasing amounts of time allowing time for
158 socket to clear. The overall time we wait in either
159 case to send on the socket is about 15 seconds.
160 Similarly we wait for 15 seconds for
161 a response from the server in SendReceive[2]
162 for the server to send a response back for
163 most types of requests (except SMB Write
164 past end of file which can be slow, and
165 blocking lock operations). NFS waits slightly longer
166 than CIFS, but this can make it take longer for
167 nonresponsive servers to be detected and 15 seconds
168 is more than enough time for modern networks to
169 send a packet. In most cases if we fail to send
170 after the retries we will kill the socket and
171 reconnect which may clear the network problem.
172 */
173 if ((i >= 14) || (!server->noblocksnd && (i > 2))) {
174 cERROR(1, "sends on sock %p stuck for 15 seconds",
175 ssocket);
176 rc = -EAGAIN;
177 break;
178 }
179 msleep(1 << i);
180 continue;
181 }
182 if (rc < 0)
183 break;
184
185 if (rc == total_len) {
186 total_len = 0;
187 break;
188 } else if (rc > total_len) {
189 cERROR(1, "sent %d requested %d", rc, total_len);
190 break;
191 }
192 if (rc == 0) {
193 /* should never happen, letting socket clear before
194 retrying is our only obvious option here */
195 cERROR(1, "tcp sent no data");
196 msleep(500);
197 continue;
198 }
199 total_len -= rc;
200 /* the line below resets i */
201 for (i = first_vec; i < n_vec; i++) {
202 if (iov[i].iov_len) {
203 if (rc > iov[i].iov_len) {
204 rc -= iov[i].iov_len;
205 iov[i].iov_len = 0;
206 } else {
207 iov[i].iov_base += rc;
208 iov[i].iov_len -= rc;
209 first_vec = i;
210 break;
211 }
212 }
213 }
214 i = 0; /* in case we get ENOSPC on the next send */
215 }
216
217 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
218 cFYI(1, "partial send (%d remaining), terminating session",
219 total_len);
220 /* If we have only sent part of an SMB then the next SMB
221 could be taken as the remainder of this one. We need
222 to kill the socket so the server throws away the partial
223 SMB */
224 server->tcpStatus = CifsNeedReconnect;
225 }
226
227 if (rc < 0) {
228 cERROR(1, "Error %d sending data on socket to server", rc);
229 } else
230 rc = 0;
231
232 /* Don't want to modify the buffer as a
233 side effect of this call. */
234 smb_buffer->smb_buf_length = smb_buf_length;
235
236 return rc;
237 }
238
239 int
240 smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
241 unsigned int smb_buf_length)
242 {
243 struct kvec iov;
244
245 iov.iov_base = smb_buffer;
246 iov.iov_len = smb_buf_length + 4;
247
248 return smb_sendv(server, &iov, 1);
249 }
250
251 static int wait_for_free_request(struct TCP_Server_Info *server,
252 const int long_op)
253 {
254 if (long_op == CIFS_ASYNC_OP) {
255 /* oplock breaks must not be held up */
256 atomic_inc(&server->inFlight);
257 return 0;
258 }
259
260 spin_lock(&GlobalMid_Lock);
261 while (1) {
262 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
263 spin_unlock(&GlobalMid_Lock);
264 #ifdef CONFIG_CIFS_STATS2
265 atomic_inc(&server->num_waiters);
266 #endif
267 wait_event(server->request_q,
268 atomic_read(&server->inFlight)
269 < cifs_max_pending);
270 #ifdef CONFIG_CIFS_STATS2
271 atomic_dec(&server->num_waiters);
272 #endif
273 spin_lock(&GlobalMid_Lock);
274 } else {
275 if (server->tcpStatus == CifsExiting) {
276 spin_unlock(&GlobalMid_Lock);
277 return -ENOENT;
278 }
279
280 /* can not count locking commands against total
281 as they are allowed to block on server */
282
283 /* update # of requests on the wire to server */
284 if (long_op != CIFS_BLOCKING_OP)
285 atomic_inc(&server->inFlight);
286 spin_unlock(&GlobalMid_Lock);
287 break;
288 }
289 }
290 return 0;
291 }
292
293 static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
294 struct mid_q_entry **ppmidQ)
295 {
296 if (ses->server->tcpStatus == CifsExiting) {
297 return -ENOENT;
298 }
299
300 if (ses->server->tcpStatus == CifsNeedReconnect) {
301 cFYI(1, "tcp session dead - return to caller to retry");
302 return -EAGAIN;
303 }
304
305 if (ses->status != CifsGood) {
306 /* check if SMB session is bad because we are setting it up */
307 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
308 (in_buf->Command != SMB_COM_NEGOTIATE))
309 return -EAGAIN;
310 /* else ok - we are setting up session */
311 }
312 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
313 if (*ppmidQ == NULL)
314 return -ENOMEM;
315 spin_lock(&GlobalMid_Lock);
316 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
317 spin_unlock(&GlobalMid_Lock);
318 return 0;
319 }
320
321 static int
322 wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
323 {
324 int error;
325
326 error = wait_event_killable(server->response_q,
327 midQ->midState != MID_REQUEST_SUBMITTED);
328 if (error < 0)
329 return -ERESTARTSYS;
330
331 return 0;
332 }
333
334
335 /*
336 *
337 * Send an SMB Request. No response info (other than return code)
338 * needs to be parsed.
339 *
340 * flags indicate the type of request buffer and how long to wait
341 * and whether to log NT STATUS code (error) before mapping it to POSIX error
342 *
343 */
344 int
345 SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
346 struct smb_hdr *in_buf, int flags)
347 {
348 int rc;
349 struct kvec iov[1];
350 int resp_buf_type;
351
352 iov[0].iov_base = (char *)in_buf;
353 iov[0].iov_len = in_buf->smb_buf_length + 4;
354 flags |= CIFS_NO_RESP;
355 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
356 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
357
358 return rc;
359 }
360
361 static int
362 sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
363 {
364 int rc = 0;
365
366 spin_lock(&GlobalMid_Lock);
367
368 if (mid->resp_buf) {
369 spin_unlock(&GlobalMid_Lock);
370 return rc;
371 }
372
373 cERROR(1, "No response to cmd %d mid %d", mid->command, mid->mid);
374 if (mid->midState == MID_REQUEST_SUBMITTED) {
375 if (server->tcpStatus == CifsExiting)
376 rc = -EHOSTDOWN;
377 else
378 mid->midState = MID_RETRY_NEEDED;
379 }
380
381 if (rc != -EHOSTDOWN) {
382 if (mid->midState == MID_RETRY_NEEDED) {
383 rc = -EAGAIN;
384 cFYI(1, "marking request for retry");
385 } else {
386 rc = -EIO;
387 }
388 }
389 spin_unlock(&GlobalMid_Lock);
390
391 delete_mid(mid);
392 return rc;
393 }
394
395 int
396 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
397 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
398 const int flags)
399 {
400 int rc = 0;
401 int long_op;
402 unsigned int receive_len;
403 struct mid_q_entry *midQ;
404 struct smb_hdr *in_buf = iov[0].iov_base;
405
406 long_op = flags & CIFS_TIMEOUT_MASK;
407
408 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
409
410 if ((ses == NULL) || (ses->server == NULL)) {
411 cifs_small_buf_release(in_buf);
412 cERROR(1, "Null session");
413 return -EIO;
414 }
415
416 if (ses->server->tcpStatus == CifsExiting) {
417 cifs_small_buf_release(in_buf);
418 return -ENOENT;
419 }
420
421 /* Ensure that we do not send more than 50 overlapping requests
422 to the same server. We may make this configurable later or
423 use ses->maxReq */
424
425 rc = wait_for_free_request(ses->server, long_op);
426 if (rc) {
427 cifs_small_buf_release(in_buf);
428 return rc;
429 }
430
431 /* make sure that we sign in the same order that we send on this socket
432 and avoid races inside tcp sendmsg code that could cause corruption
433 of smb data */
434
435 mutex_lock(&ses->server->srv_mutex);
436
437 rc = allocate_mid(ses, in_buf, &midQ);
438 if (rc) {
439 mutex_unlock(&ses->server->srv_mutex);
440 cifs_small_buf_release(in_buf);
441 /* Update # of requests on wire to server */
442 atomic_dec(&ses->server->inFlight);
443 wake_up(&ses->server->request_q);
444 return rc;
445 }
446 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
447 if (rc) {
448 mutex_unlock(&ses->server->srv_mutex);
449 cifs_small_buf_release(in_buf);
450 goto out;
451 }
452
453 midQ->midState = MID_REQUEST_SUBMITTED;
454 #ifdef CONFIG_CIFS_STATS2
455 atomic_inc(&ses->server->inSend);
456 #endif
457 rc = smb_sendv(ses->server, iov, n_vec);
458 #ifdef CONFIG_CIFS_STATS2
459 atomic_dec(&ses->server->inSend);
460 midQ->when_sent = jiffies;
461 #endif
462
463 mutex_unlock(&ses->server->srv_mutex);
464 cifs_small_buf_release(in_buf);
465
466 if (rc < 0)
467 goto out;
468
469 if (long_op == CIFS_ASYNC_OP)
470 goto out;
471
472 rc = wait_for_response(ses->server, midQ);
473 if (rc != 0)
474 goto out;
475
476 rc = sync_mid_result(midQ, ses->server);
477 if (rc != 0) {
478 atomic_dec(&ses->server->inFlight);
479 wake_up(&ses->server->request_q);
480 return rc;
481 }
482
483 receive_len = midQ->resp_buf->smb_buf_length;
484
485 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
486 cERROR(1, "Frame too large received. Length: %d Xid: %d",
487 receive_len, xid);
488 rc = -EIO;
489 goto out;
490 }
491
492 /* rcvd frame is ok */
493
494 if (midQ->resp_buf &&
495 (midQ->midState == MID_RESPONSE_RECEIVED)) {
496
497 iov[0].iov_base = (char *)midQ->resp_buf;
498 if (midQ->largeBuf)
499 *pRespBufType = CIFS_LARGE_BUFFER;
500 else
501 *pRespBufType = CIFS_SMALL_BUFFER;
502 iov[0].iov_len = receive_len + 4;
503
504 dump_smb(midQ->resp_buf, 80);
505 /* convert the length into a more usable form */
506 if ((receive_len > 24) &&
507 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
508 SECMODE_SIGN_ENABLED))) {
509 rc = cifs_verify_signature(midQ->resp_buf,
510 ses->server,
511 midQ->sequence_number+1);
512 if (rc) {
513 cERROR(1, "Unexpected SMB signature");
514 /* BB FIXME add code to kill session */
515 }
516 }
517
518 /* BB special case reconnect tid and uid here? */
519 rc = map_smb_to_linux_error(midQ->resp_buf,
520 flags & CIFS_LOG_ERROR);
521
522 /* convert ByteCount if necessary */
523 if (receive_len >= sizeof(struct smb_hdr) - 4
524 /* do not count RFC1001 header */ +
525 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
526 BCC(midQ->resp_buf) =
527 le16_to_cpu(BCC_LE(midQ->resp_buf));
528 if ((flags & CIFS_NO_RESP) == 0)
529 midQ->resp_buf = NULL; /* mark it so buf will
530 not be freed by
531 delete_mid */
532 } else {
533 rc = -EIO;
534 cFYI(1, "Bad MID state?");
535 }
536
537 out:
538 delete_mid(midQ);
539 atomic_dec(&ses->server->inFlight);
540 wake_up(&ses->server->request_q);
541
542 return rc;
543 }
544
545 int
546 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
547 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
548 int *pbytes_returned, const int long_op)
549 {
550 int rc = 0;
551 unsigned int receive_len;
552 struct mid_q_entry *midQ;
553
554 if (ses == NULL) {
555 cERROR(1, "Null smb session");
556 return -EIO;
557 }
558 if (ses->server == NULL) {
559 cERROR(1, "Null tcp session");
560 return -EIO;
561 }
562
563 if (ses->server->tcpStatus == CifsExiting)
564 return -ENOENT;
565
566 /* Ensure that we do not send more than 50 overlapping requests
567 to the same server. We may make this configurable later or
568 use ses->maxReq */
569
570 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
571 cERROR(1, "Illegal length, greater than maximum frame, %d",
572 in_buf->smb_buf_length);
573 return -EIO;
574 }
575
576 rc = wait_for_free_request(ses->server, long_op);
577 if (rc)
578 return rc;
579
580 /* make sure that we sign in the same order that we send on this socket
581 and avoid races inside tcp sendmsg code that could cause corruption
582 of smb data */
583
584 mutex_lock(&ses->server->srv_mutex);
585
586 rc = allocate_mid(ses, in_buf, &midQ);
587 if (rc) {
588 mutex_unlock(&ses->server->srv_mutex);
589 /* Update # of requests on wire to server */
590 atomic_dec(&ses->server->inFlight);
591 wake_up(&ses->server->request_q);
592 return rc;
593 }
594
595 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
596 if (rc) {
597 mutex_unlock(&ses->server->srv_mutex);
598 goto out;
599 }
600
601 midQ->midState = MID_REQUEST_SUBMITTED;
602 #ifdef CONFIG_CIFS_STATS2
603 atomic_inc(&ses->server->inSend);
604 #endif
605 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
606 #ifdef CONFIG_CIFS_STATS2
607 atomic_dec(&ses->server->inSend);
608 midQ->when_sent = jiffies;
609 #endif
610 mutex_unlock(&ses->server->srv_mutex);
611
612 if (rc < 0)
613 goto out;
614
615 if (long_op == CIFS_ASYNC_OP)
616 goto out;
617
618 rc = wait_for_response(ses->server, midQ);
619 if (rc != 0)
620 goto out;
621
622 rc = sync_mid_result(midQ, ses->server);
623 if (rc != 0) {
624 atomic_dec(&ses->server->inFlight);
625 wake_up(&ses->server->request_q);
626 return rc;
627 }
628
629 receive_len = midQ->resp_buf->smb_buf_length;
630
631 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
632 cERROR(1, "Frame too large received. Length: %d Xid: %d",
633 receive_len, xid);
634 rc = -EIO;
635 goto out;
636 }
637
638 /* rcvd frame is ok */
639
640 if (midQ->resp_buf && out_buf
641 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
642 out_buf->smb_buf_length = receive_len;
643 memcpy((char *)out_buf + 4,
644 (char *)midQ->resp_buf + 4,
645 receive_len);
646
647 dump_smb(out_buf, 92);
648 /* convert the length into a more usable form */
649 if ((receive_len > 24) &&
650 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
651 SECMODE_SIGN_ENABLED))) {
652 rc = cifs_verify_signature(out_buf,
653 ses->server,
654 midQ->sequence_number+1);
655 if (rc) {
656 cERROR(1, "Unexpected SMB signature");
657 /* BB FIXME add code to kill session */
658 }
659 }
660
661 *pbytes_returned = out_buf->smb_buf_length;
662
663 /* BB special case reconnect tid and uid here? */
664 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
665
666 /* convert ByteCount if necessary */
667 if (receive_len >= sizeof(struct smb_hdr) - 4
668 /* do not count RFC1001 header */ +
669 (2 * out_buf->WordCount) + 2 /* bcc */ )
670 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
671 } else {
672 rc = -EIO;
673 cERROR(1, "Bad MID state?");
674 }
675
676 out:
677 delete_mid(midQ);
678 atomic_dec(&ses->server->inFlight);
679 wake_up(&ses->server->request_q);
680
681 return rc;
682 }
683
684 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
685
686 static int
687 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
688 struct mid_q_entry *midQ)
689 {
690 int rc = 0;
691 struct cifsSesInfo *ses = tcon->ses;
692 __u16 mid = in_buf->Mid;
693
694 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
695 in_buf->Mid = mid;
696 mutex_lock(&ses->server->srv_mutex);
697 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
698 if (rc) {
699 mutex_unlock(&ses->server->srv_mutex);
700 return rc;
701 }
702 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
703 mutex_unlock(&ses->server->srv_mutex);
704 return rc;
705 }
706
707 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
708 blocking lock to return. */
709
710 static int
711 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
712 struct smb_hdr *in_buf,
713 struct smb_hdr *out_buf)
714 {
715 int bytes_returned;
716 struct cifsSesInfo *ses = tcon->ses;
717 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
718
719 /* We just modify the current in_buf to change
720 the type of lock from LOCKING_ANDX_SHARED_LOCK
721 or LOCKING_ANDX_EXCLUSIVE_LOCK to
722 LOCKING_ANDX_CANCEL_LOCK. */
723
724 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
725 pSMB->Timeout = 0;
726 pSMB->hdr.Mid = GetNextMid(ses->server);
727
728 return SendReceive(xid, ses, in_buf, out_buf,
729 &bytes_returned, CIFS_STD_OP);
730 }
731
732 int
733 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
734 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
735 int *pbytes_returned)
736 {
737 int rc = 0;
738 int rstart = 0;
739 unsigned int receive_len;
740 struct mid_q_entry *midQ;
741 struct cifsSesInfo *ses;
742
743 if (tcon == NULL || tcon->ses == NULL) {
744 cERROR(1, "Null smb session");
745 return -EIO;
746 }
747 ses = tcon->ses;
748
749 if (ses->server == NULL) {
750 cERROR(1, "Null tcp session");
751 return -EIO;
752 }
753
754 if (ses->server->tcpStatus == CifsExiting)
755 return -ENOENT;
756
757 /* Ensure that we do not send more than 50 overlapping requests
758 to the same server. We may make this configurable later or
759 use ses->maxReq */
760
761 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
762 cERROR(1, "Illegal length, greater than maximum frame, %d",
763 in_buf->smb_buf_length);
764 return -EIO;
765 }
766
767 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
768 if (rc)
769 return rc;
770
771 /* make sure that we sign in the same order that we send on this socket
772 and avoid races inside tcp sendmsg code that could cause corruption
773 of smb data */
774
775 mutex_lock(&ses->server->srv_mutex);
776
777 rc = allocate_mid(ses, in_buf, &midQ);
778 if (rc) {
779 mutex_unlock(&ses->server->srv_mutex);
780 return rc;
781 }
782
783 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
784 if (rc) {
785 delete_mid(midQ);
786 mutex_unlock(&ses->server->srv_mutex);
787 return rc;
788 }
789
790 midQ->midState = MID_REQUEST_SUBMITTED;
791 #ifdef CONFIG_CIFS_STATS2
792 atomic_inc(&ses->server->inSend);
793 #endif
794 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
795 #ifdef CONFIG_CIFS_STATS2
796 atomic_dec(&ses->server->inSend);
797 midQ->when_sent = jiffies;
798 #endif
799 mutex_unlock(&ses->server->srv_mutex);
800
801 if (rc < 0) {
802 delete_mid(midQ);
803 return rc;
804 }
805
806 /* Wait for a reply - allow signals to interrupt. */
807 rc = wait_event_interruptible(ses->server->response_q,
808 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
809 ((ses->server->tcpStatus != CifsGood) &&
810 (ses->server->tcpStatus != CifsNew)));
811
812 /* Were we interrupted by a signal ? */
813 if ((rc == -ERESTARTSYS) &&
814 (midQ->midState == MID_REQUEST_SUBMITTED) &&
815 ((ses->server->tcpStatus == CifsGood) ||
816 (ses->server->tcpStatus == CifsNew))) {
817
818 if (in_buf->Command == SMB_COM_TRANSACTION2) {
819 /* POSIX lock. We send a NT_CANCEL SMB to cause the
820 blocking lock to return. */
821
822 rc = send_nt_cancel(tcon, in_buf, midQ);
823 if (rc) {
824 delete_mid(midQ);
825 return rc;
826 }
827 } else {
828 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
829 to cause the blocking lock to return. */
830
831 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
832
833 /* If we get -ENOLCK back the lock may have
834 already been removed. Don't exit in this case. */
835 if (rc && rc != -ENOLCK) {
836 delete_mid(midQ);
837 return rc;
838 }
839 }
840
841 if (wait_for_response(ses->server, midQ) == 0) {
842 /* We got the response - restart system call. */
843 rstart = 1;
844 }
845 }
846
847 rc = sync_mid_result(midQ, ses->server);
848 if (rc != 0)
849 return rc;
850
851 receive_len = midQ->resp_buf->smb_buf_length;
852 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
853 cERROR(1, "Frame too large received. Length: %d Xid: %d",
854 receive_len, xid);
855 rc = -EIO;
856 goto out;
857 }
858
859 /* rcvd frame is ok */
860
861 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
862 rc = -EIO;
863 cERROR(1, "Bad MID state?");
864 goto out;
865 }
866
867 out_buf->smb_buf_length = receive_len;
868 memcpy((char *)out_buf + 4,
869 (char *)midQ->resp_buf + 4,
870 receive_len);
871
872 dump_smb(out_buf, 92);
873 /* convert the length into a more usable form */
874 if ((receive_len > 24) &&
875 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
876 SECMODE_SIGN_ENABLED))) {
877 rc = cifs_verify_signature(out_buf,
878 ses->server,
879 midQ->sequence_number+1);
880 if (rc) {
881 cERROR(1, "Unexpected SMB signature");
882 /* BB FIXME add code to kill session */
883 }
884 }
885
886 *pbytes_returned = out_buf->smb_buf_length;
887
888 /* BB special case reconnect tid and uid here? */
889 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
890
891 /* convert ByteCount if necessary */
892 if (receive_len >= sizeof(struct smb_hdr) - 4
893 /* do not count RFC1001 header */ +
894 (2 * out_buf->WordCount) + 2 /* bcc */ )
895 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
896
897 out:
898 delete_mid(midQ);
899 if (rstart && rc == -EACCES)
900 return -ERESTARTSYS;
901 return rc;
902 }
This page took 0.050689 seconds and 6 git commands to generate.