6abd1445c983cd8d281511d855b2a34b52a6de72
[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 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
367 mid->mid, mid->midState);
368
369 spin_lock(&GlobalMid_Lock);
370 switch (mid->midState) {
371 case MID_RESPONSE_RECEIVED:
372 spin_unlock(&GlobalMid_Lock);
373 return rc;
374 case MID_REQUEST_SUBMITTED:
375 /* socket is going down, reject all calls */
376 if (server->tcpStatus == CifsExiting) {
377 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
378 __func__, mid->mid, mid->command, mid->midState);
379 rc = -EHOSTDOWN;
380 break;
381 }
382 case MID_RETRY_NEEDED:
383 rc = -EAGAIN;
384 break;
385 default:
386 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
387 mid->mid, mid->midState);
388 rc = -EIO;
389 }
390 spin_unlock(&GlobalMid_Lock);
391
392 delete_mid(mid);
393 return rc;
394 }
395
396 int
397 SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
398 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
399 const int flags)
400 {
401 int rc = 0;
402 int long_op;
403 unsigned int receive_len;
404 struct mid_q_entry *midQ;
405 struct smb_hdr *in_buf = iov[0].iov_base;
406
407 long_op = flags & CIFS_TIMEOUT_MASK;
408
409 *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */
410
411 if ((ses == NULL) || (ses->server == NULL)) {
412 cifs_small_buf_release(in_buf);
413 cERROR(1, "Null session");
414 return -EIO;
415 }
416
417 if (ses->server->tcpStatus == CifsExiting) {
418 cifs_small_buf_release(in_buf);
419 return -ENOENT;
420 }
421
422 /* Ensure that we do not send more than 50 overlapping requests
423 to the same server. We may make this configurable later or
424 use ses->maxReq */
425
426 rc = wait_for_free_request(ses->server, long_op);
427 if (rc) {
428 cifs_small_buf_release(in_buf);
429 return rc;
430 }
431
432 /* make sure that we sign in the same order that we send on this socket
433 and avoid races inside tcp sendmsg code that could cause corruption
434 of smb data */
435
436 mutex_lock(&ses->server->srv_mutex);
437
438 rc = allocate_mid(ses, in_buf, &midQ);
439 if (rc) {
440 mutex_unlock(&ses->server->srv_mutex);
441 cifs_small_buf_release(in_buf);
442 /* Update # of requests on wire to server */
443 atomic_dec(&ses->server->inFlight);
444 wake_up(&ses->server->request_q);
445 return rc;
446 }
447 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
448 if (rc) {
449 mutex_unlock(&ses->server->srv_mutex);
450 cifs_small_buf_release(in_buf);
451 goto out;
452 }
453
454 midQ->midState = MID_REQUEST_SUBMITTED;
455 #ifdef CONFIG_CIFS_STATS2
456 atomic_inc(&ses->server->inSend);
457 #endif
458 rc = smb_sendv(ses->server, iov, n_vec);
459 #ifdef CONFIG_CIFS_STATS2
460 atomic_dec(&ses->server->inSend);
461 midQ->when_sent = jiffies;
462 #endif
463
464 mutex_unlock(&ses->server->srv_mutex);
465 cifs_small_buf_release(in_buf);
466
467 if (rc < 0)
468 goto out;
469
470 if (long_op == CIFS_ASYNC_OP)
471 goto out;
472
473 rc = wait_for_response(ses->server, midQ);
474 if (rc != 0)
475 goto out;
476
477 rc = sync_mid_result(midQ, ses->server);
478 if (rc != 0) {
479 atomic_dec(&ses->server->inFlight);
480 wake_up(&ses->server->request_q);
481 return rc;
482 }
483
484 receive_len = midQ->resp_buf->smb_buf_length;
485
486 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
487 cERROR(1, "Frame too large received. Length: %d Xid: %d",
488 receive_len, xid);
489 rc = -EIO;
490 goto out;
491 }
492
493 /* rcvd frame is ok */
494
495 if (midQ->resp_buf &&
496 (midQ->midState == MID_RESPONSE_RECEIVED)) {
497
498 iov[0].iov_base = (char *)midQ->resp_buf;
499 if (midQ->largeBuf)
500 *pRespBufType = CIFS_LARGE_BUFFER;
501 else
502 *pRespBufType = CIFS_SMALL_BUFFER;
503 iov[0].iov_len = receive_len + 4;
504
505 dump_smb(midQ->resp_buf, 80);
506 /* convert the length into a more usable form */
507 if ((receive_len > 24) &&
508 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
509 SECMODE_SIGN_ENABLED))) {
510 rc = cifs_verify_signature(midQ->resp_buf,
511 ses->server,
512 midQ->sequence_number+1);
513 if (rc) {
514 cERROR(1, "Unexpected SMB signature");
515 /* BB FIXME add code to kill session */
516 }
517 }
518
519 /* BB special case reconnect tid and uid here? */
520 rc = map_smb_to_linux_error(midQ->resp_buf,
521 flags & CIFS_LOG_ERROR);
522
523 /* convert ByteCount if necessary */
524 if (receive_len >= sizeof(struct smb_hdr) - 4
525 /* do not count RFC1001 header */ +
526 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
527 BCC(midQ->resp_buf) =
528 le16_to_cpu(BCC_LE(midQ->resp_buf));
529 if ((flags & CIFS_NO_RESP) == 0)
530 midQ->resp_buf = NULL; /* mark it so buf will
531 not be freed by
532 delete_mid */
533 } else {
534 rc = -EIO;
535 cFYI(1, "Bad MID state?");
536 }
537
538 out:
539 delete_mid(midQ);
540 atomic_dec(&ses->server->inFlight);
541 wake_up(&ses->server->request_q);
542
543 return rc;
544 }
545
546 int
547 SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
548 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
549 int *pbytes_returned, const int long_op)
550 {
551 int rc = 0;
552 unsigned int receive_len;
553 struct mid_q_entry *midQ;
554
555 if (ses == NULL) {
556 cERROR(1, "Null smb session");
557 return -EIO;
558 }
559 if (ses->server == NULL) {
560 cERROR(1, "Null tcp session");
561 return -EIO;
562 }
563
564 if (ses->server->tcpStatus == CifsExiting)
565 return -ENOENT;
566
567 /* Ensure that we do not send more than 50 overlapping requests
568 to the same server. We may make this configurable later or
569 use ses->maxReq */
570
571 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
572 cERROR(1, "Illegal length, greater than maximum frame, %d",
573 in_buf->smb_buf_length);
574 return -EIO;
575 }
576
577 rc = wait_for_free_request(ses->server, long_op);
578 if (rc)
579 return rc;
580
581 /* make sure that we sign in the same order that we send on this socket
582 and avoid races inside tcp sendmsg code that could cause corruption
583 of smb data */
584
585 mutex_lock(&ses->server->srv_mutex);
586
587 rc = allocate_mid(ses, in_buf, &midQ);
588 if (rc) {
589 mutex_unlock(&ses->server->srv_mutex);
590 /* Update # of requests on wire to server */
591 atomic_dec(&ses->server->inFlight);
592 wake_up(&ses->server->request_q);
593 return rc;
594 }
595
596 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
597 if (rc) {
598 mutex_unlock(&ses->server->srv_mutex);
599 goto out;
600 }
601
602 midQ->midState = MID_REQUEST_SUBMITTED;
603 #ifdef CONFIG_CIFS_STATS2
604 atomic_inc(&ses->server->inSend);
605 #endif
606 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
607 #ifdef CONFIG_CIFS_STATS2
608 atomic_dec(&ses->server->inSend);
609 midQ->when_sent = jiffies;
610 #endif
611 mutex_unlock(&ses->server->srv_mutex);
612
613 if (rc < 0)
614 goto out;
615
616 if (long_op == CIFS_ASYNC_OP)
617 goto out;
618
619 rc = wait_for_response(ses->server, midQ);
620 if (rc != 0)
621 goto out;
622
623 rc = sync_mid_result(midQ, ses->server);
624 if (rc != 0) {
625 atomic_dec(&ses->server->inFlight);
626 wake_up(&ses->server->request_q);
627 return rc;
628 }
629
630 receive_len = midQ->resp_buf->smb_buf_length;
631
632 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
633 cERROR(1, "Frame too large received. Length: %d Xid: %d",
634 receive_len, xid);
635 rc = -EIO;
636 goto out;
637 }
638
639 /* rcvd frame is ok */
640
641 if (midQ->resp_buf && out_buf
642 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
643 out_buf->smb_buf_length = receive_len;
644 memcpy((char *)out_buf + 4,
645 (char *)midQ->resp_buf + 4,
646 receive_len);
647
648 dump_smb(out_buf, 92);
649 /* convert the length into a more usable form */
650 if ((receive_len > 24) &&
651 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
652 SECMODE_SIGN_ENABLED))) {
653 rc = cifs_verify_signature(out_buf,
654 ses->server,
655 midQ->sequence_number+1);
656 if (rc) {
657 cERROR(1, "Unexpected SMB signature");
658 /* BB FIXME add code to kill session */
659 }
660 }
661
662 *pbytes_returned = out_buf->smb_buf_length;
663
664 /* BB special case reconnect tid and uid here? */
665 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
666
667 /* convert ByteCount if necessary */
668 if (receive_len >= sizeof(struct smb_hdr) - 4
669 /* do not count RFC1001 header */ +
670 (2 * out_buf->WordCount) + 2 /* bcc */ )
671 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
672 } else {
673 rc = -EIO;
674 cERROR(1, "Bad MID state?");
675 }
676
677 out:
678 delete_mid(midQ);
679 atomic_dec(&ses->server->inFlight);
680 wake_up(&ses->server->request_q);
681
682 return rc;
683 }
684
685 /* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
686
687 static int
688 send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
689 struct mid_q_entry *midQ)
690 {
691 int rc = 0;
692 struct cifsSesInfo *ses = tcon->ses;
693 __u16 mid = in_buf->Mid;
694
695 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
696 in_buf->Mid = mid;
697 mutex_lock(&ses->server->srv_mutex);
698 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
699 if (rc) {
700 mutex_unlock(&ses->server->srv_mutex);
701 return rc;
702 }
703 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
704 mutex_unlock(&ses->server->srv_mutex);
705 return rc;
706 }
707
708 /* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
709 blocking lock to return. */
710
711 static int
712 send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
713 struct smb_hdr *in_buf,
714 struct smb_hdr *out_buf)
715 {
716 int bytes_returned;
717 struct cifsSesInfo *ses = tcon->ses;
718 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
719
720 /* We just modify the current in_buf to change
721 the type of lock from LOCKING_ANDX_SHARED_LOCK
722 or LOCKING_ANDX_EXCLUSIVE_LOCK to
723 LOCKING_ANDX_CANCEL_LOCK. */
724
725 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
726 pSMB->Timeout = 0;
727 pSMB->hdr.Mid = GetNextMid(ses->server);
728
729 return SendReceive(xid, ses, in_buf, out_buf,
730 &bytes_returned, CIFS_STD_OP);
731 }
732
733 int
734 SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
735 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
736 int *pbytes_returned)
737 {
738 int rc = 0;
739 int rstart = 0;
740 unsigned int receive_len;
741 struct mid_q_entry *midQ;
742 struct cifsSesInfo *ses;
743
744 if (tcon == NULL || tcon->ses == NULL) {
745 cERROR(1, "Null smb session");
746 return -EIO;
747 }
748 ses = tcon->ses;
749
750 if (ses->server == NULL) {
751 cERROR(1, "Null tcp session");
752 return -EIO;
753 }
754
755 if (ses->server->tcpStatus == CifsExiting)
756 return -ENOENT;
757
758 /* Ensure that we do not send more than 50 overlapping requests
759 to the same server. We may make this configurable later or
760 use ses->maxReq */
761
762 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
763 cERROR(1, "Illegal length, greater than maximum frame, %d",
764 in_buf->smb_buf_length);
765 return -EIO;
766 }
767
768 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
769 if (rc)
770 return rc;
771
772 /* make sure that we sign in the same order that we send on this socket
773 and avoid races inside tcp sendmsg code that could cause corruption
774 of smb data */
775
776 mutex_lock(&ses->server->srv_mutex);
777
778 rc = allocate_mid(ses, in_buf, &midQ);
779 if (rc) {
780 mutex_unlock(&ses->server->srv_mutex);
781 return rc;
782 }
783
784 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
785 if (rc) {
786 delete_mid(midQ);
787 mutex_unlock(&ses->server->srv_mutex);
788 return rc;
789 }
790
791 midQ->midState = MID_REQUEST_SUBMITTED;
792 #ifdef CONFIG_CIFS_STATS2
793 atomic_inc(&ses->server->inSend);
794 #endif
795 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
796 #ifdef CONFIG_CIFS_STATS2
797 atomic_dec(&ses->server->inSend);
798 midQ->when_sent = jiffies;
799 #endif
800 mutex_unlock(&ses->server->srv_mutex);
801
802 if (rc < 0) {
803 delete_mid(midQ);
804 return rc;
805 }
806
807 /* Wait for a reply - allow signals to interrupt. */
808 rc = wait_event_interruptible(ses->server->response_q,
809 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
810 ((ses->server->tcpStatus != CifsGood) &&
811 (ses->server->tcpStatus != CifsNew)));
812
813 /* Were we interrupted by a signal ? */
814 if ((rc == -ERESTARTSYS) &&
815 (midQ->midState == MID_REQUEST_SUBMITTED) &&
816 ((ses->server->tcpStatus == CifsGood) ||
817 (ses->server->tcpStatus == CifsNew))) {
818
819 if (in_buf->Command == SMB_COM_TRANSACTION2) {
820 /* POSIX lock. We send a NT_CANCEL SMB to cause the
821 blocking lock to return. */
822
823 rc = send_nt_cancel(tcon, in_buf, midQ);
824 if (rc) {
825 delete_mid(midQ);
826 return rc;
827 }
828 } else {
829 /* Windows lock. We send a LOCKINGX_CANCEL_LOCK
830 to cause the blocking lock to return. */
831
832 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
833
834 /* If we get -ENOLCK back the lock may have
835 already been removed. Don't exit in this case. */
836 if (rc && rc != -ENOLCK) {
837 delete_mid(midQ);
838 return rc;
839 }
840 }
841
842 if (wait_for_response(ses->server, midQ) == 0) {
843 /* We got the response - restart system call. */
844 rstart = 1;
845 }
846 }
847
848 rc = sync_mid_result(midQ, ses->server);
849 if (rc != 0)
850 return rc;
851
852 receive_len = midQ->resp_buf->smb_buf_length;
853 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
854 cERROR(1, "Frame too large received. Length: %d Xid: %d",
855 receive_len, xid);
856 rc = -EIO;
857 goto out;
858 }
859
860 /* rcvd frame is ok */
861
862 if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) {
863 rc = -EIO;
864 cERROR(1, "Bad MID state?");
865 goto out;
866 }
867
868 out_buf->smb_buf_length = receive_len;
869 memcpy((char *)out_buf + 4,
870 (char *)midQ->resp_buf + 4,
871 receive_len);
872
873 dump_smb(out_buf, 92);
874 /* convert the length into a more usable form */
875 if ((receive_len > 24) &&
876 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
877 SECMODE_SIGN_ENABLED))) {
878 rc = cifs_verify_signature(out_buf,
879 ses->server,
880 midQ->sequence_number+1);
881 if (rc) {
882 cERROR(1, "Unexpected SMB signature");
883 /* BB FIXME add code to kill session */
884 }
885 }
886
887 *pbytes_returned = out_buf->smb_buf_length;
888
889 /* BB special case reconnect tid and uid here? */
890 rc = map_smb_to_linux_error(out_buf, 0 /* no log */ );
891
892 /* convert ByteCount if necessary */
893 if (receive_len >= sizeof(struct smb_hdr) - 4
894 /* do not count RFC1001 header */ +
895 (2 * out_buf->WordCount) + 2 /* bcc */ )
896 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
897
898 out:
899 delete_mid(midQ);
900 if (rstart && rc == -EACCES)
901 return -ERESTARTSYS;
902 return rc;
903 }
This page took 0.048395 seconds and 4 git commands to generate.