1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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"
35
36extern mempool_t *cifs_mid_poolp;
37extern struct kmem_cache *cifs_oplock_cachep;
38
39static struct mid_q_entry *
40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses)
41{
42 struct mid_q_entry *temp;
43
44 if (ses == NULL) {
45 cERROR(1, ("Null session passed in to AllocMidQEntry"));
46 return NULL;
47 }
48 if (ses->server == NULL) {
49 cERROR(1, ("Null TCP session in AllocMidQEntry"));
50 return NULL;
51 }
52
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;
60 temp->pid = current->pid;
61 temp->command = smb_buffer->Command;
62 cFYI(1, ("For smb_command %d", temp->command));
63
64
65 temp->when_alloc = jiffies;
66 temp->ses = ses;
67 temp->tsk = current;
68 }
69
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;
76}
77
78static void
79DeleteMidQEntry(struct mid_q_entry *midEntry)
80{
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
96
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);
106 }
107 }
108#endif
109 mempool_free(midEntry, cifs_mid_poolp);
110}
111
112struct oplock_q_entry *
113AllocOplockQEntry(struct inode *pinode, __u16 fid, struct cifsTconInfo *tcon)
114{
115 struct oplock_q_entry *temp;
116 if ((pinode == NULL) || (tcon == NULL)) {
117 cERROR(1, ("Null parms passed to AllocOplockQEntry"));
118 return NULL;
119 }
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);
131 }
132 return temp;
133
134}
135
136void DeleteOplockQEntry(struct oplock_q_entry *oplockEntry)
137{
138 spin_lock(&GlobalMid_Lock);
139
140 list_del(&oplockEntry->qhead);
141 spin_unlock(&GlobalMid_Lock);
142 kmem_cache_free(cifs_oplock_cachep, oplockEntry);
143}
144
145int
146smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
147 unsigned int smb_buf_length, struct sockaddr *sin)
148{
149 int rc = 0;
150 int i = 0;
151 struct msghdr smb_msg;
152 struct kvec iov;
153 unsigned len = smb_buf_length + 4;
154
155 if (ssocket == NULL)
156 return -ENOTSOCK;
157 iov.iov_base = smb_buffer;
158 iov.iov_len = len;
159
160 smb_msg.msg_name = sin;
161 smb_msg.msg_namelen = sizeof(struct sockaddr);
162 smb_msg.msg_control = NULL;
163 smb_msg.msg_controllen = 0;
164 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
165
166
167
168
169
170
171 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
172 cFYI(1, ("Sending smb of length %d", smb_buf_length));
173 dump_smb(smb_buffer, len);
174
175 while (len > 0) {
176 rc = kernel_sendmsg(ssocket, &smb_msg, &iov, 1, len);
177 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
178 i++;
179
180
181
182 if (i > 12) {
183 cERROR(1,
184 ("sends on sock %p stuck for 7 seconds",
185 ssocket));
186 rc = -EAGAIN;
187 break;
188 }
189 msleep(1 << i);
190 continue;
191 }
192 if (rc < 0)
193 break;
194 else
195 i = 0;
196 iov.iov_base += rc;
197 iov.iov_len -= rc;
198 len -= rc;
199 }
200
201 if (rc < 0) {
202 cERROR(1, ("Error %d sending data on socket to server", rc));
203 } else {
204 rc = 0;
205 }
206
207
208
209 smb_buffer->smb_buf_length = smb_buf_length;
210
211 return rc;
212}
213
214static int
215smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec,
216 struct sockaddr *sin)
217{
218 int rc = 0;
219 int i = 0;
220 struct msghdr smb_msg;
221 struct smb_hdr *smb_buffer = iov[0].iov_base;
222 unsigned int len = iov[0].iov_len;
223 unsigned int total_len;
224 int first_vec = 0;
225 unsigned int smb_buf_length = smb_buffer->smb_buf_length;
226
227 if (ssocket == NULL)
228 return -ENOTSOCK;
229
230 smb_msg.msg_name = sin;
231 smb_msg.msg_namelen = sizeof(struct sockaddr);
232 smb_msg.msg_control = NULL;
233 smb_msg.msg_controllen = 0;
234 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
235
236
237
238
239
240
241
242 total_len = 0;
243 for (i = 0; i < n_vec; i++)
244 total_len += iov[i].iov_len;
245
246 smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
247 cFYI(1, ("Sending smb: total_len %d", total_len));
248 dump_smb(smb_buffer, len);
249
250 while (total_len) {
251 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
252 n_vec - first_vec, total_len);
253 if ((rc == -ENOSPC) || (rc == -EAGAIN)) {
254 i++;
255 if (i >= 14) {
256 cERROR(1,
257 ("sends on sock %p stuck for 15 seconds",
258 ssocket));
259 rc = -EAGAIN;
260 break;
261 }
262 msleep(1 << i);
263 continue;
264 }
265 if (rc < 0)
266 break;
267
268 if (rc >= total_len) {
269 WARN_ON(rc > total_len);
270 break;
271 }
272 if (rc == 0) {
273
274
275 cERROR(1, ("tcp sent no data"));
276 msleep(500);
277 continue;
278 }
279 total_len -= rc;
280
281 for (i = first_vec; i < n_vec; i++) {
282 if (iov[i].iov_len) {
283 if (rc > iov[i].iov_len) {
284 rc -= iov[i].iov_len;
285 iov[i].iov_len = 0;
286 } else {
287 iov[i].iov_base += rc;
288 iov[i].iov_len -= rc;
289 first_vec = i;
290 break;
291 }
292 }
293 }
294 i = 0;
295 }
296
297 if (rc < 0) {
298 cERROR(1, ("Error %d sending data on socket to server", rc));
299 } else
300 rc = 0;
301
302
303
304 smb_buffer->smb_buf_length = smb_buf_length;
305
306 return rc;
307}
308
309static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
310{
311 if (long_op == CIFS_ASYNC_OP) {
312
313 atomic_inc(&ses->server->inFlight);
314 } else {
315 spin_lock(&GlobalMid_Lock);
316 while (1) {
317 if (atomic_read(&ses->server->inFlight) >=
318 cifs_max_pending){
319 spin_unlock(&GlobalMid_Lock);
320#ifdef CONFIG_CIFS_STATS2
321 atomic_inc(&ses->server->num_waiters);
322#endif
323 wait_event(ses->server->request_q,
324 atomic_read(&ses->server->inFlight)
325 < cifs_max_pending);
326#ifdef CONFIG_CIFS_STATS2
327 atomic_dec(&ses->server->num_waiters);
328#endif
329 spin_lock(&GlobalMid_Lock);
330 } else {
331 if (ses->server->tcpStatus == CifsExiting) {
332 spin_unlock(&GlobalMid_Lock);
333 return -ENOENT;
334 }
335
336
337
338
339
340 if (long_op != CIFS_BLOCKING_OP)
341 atomic_inc(&ses->server->inFlight);
342 spin_unlock(&GlobalMid_Lock);
343 break;
344 }
345 }
346 }
347 return 0;
348}
349
350static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
351 struct mid_q_entry **ppmidQ)
352{
353 if (ses->server->tcpStatus == CifsExiting) {
354 return -ENOENT;
355 } else if (ses->server->tcpStatus == CifsNeedReconnect) {
356 cFYI(1, ("tcp session dead - return to caller to retry"));
357 return -EAGAIN;
358 } else if (ses->status != CifsGood) {
359
360 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
361 (in_buf->Command != SMB_COM_NEGOTIATE)) {
362 return -EAGAIN;
363 }
364 }
365 *ppmidQ = AllocMidQEntry(in_buf, ses);
366 if (*ppmidQ == NULL)
367 return -ENOMEM;
368 return 0;
369}
370
371static int wait_for_response(struct cifsSesInfo *ses,
372 struct mid_q_entry *midQ,
373 unsigned long timeout,
374 unsigned long time_to_wait)
375{
376 unsigned long curr_timeout;
377
378 for (;;) {
379 curr_timeout = timeout + jiffies;
380 wait_event(ses->server->response_q,
381 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
382 time_after(jiffies, curr_timeout) ||
383 ((ses->server->tcpStatus != CifsGood) &&
384 (ses->server->tcpStatus != CifsNew)));
385
386 if (time_after(jiffies, curr_timeout) &&
387 (midQ->midState == MID_REQUEST_SUBMITTED) &&
388 ((ses->server->tcpStatus == CifsGood) ||
389 (ses->server->tcpStatus == CifsNew))) {
390
391 unsigned long lrt;
392
393
394
395 spin_lock(&GlobalMid_Lock);
396 lrt = ses->server->lstrp;
397 spin_unlock(&GlobalMid_Lock);
398
399
400
401
402
403
404
405
406 lrt += time_to_wait;
407 if (time_after(jiffies, lrt)) {
408
409 cERROR(1, ("server not responding"));
410 return -1;
411 }
412 } else {
413 return 0;
414 }
415 }
416}
417
418
419
420
421
422
423
424
425
426
427
428int
429SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
430 struct smb_hdr *in_buf, int flags)
431{
432 int rc;
433 struct kvec iov[1];
434 int resp_buf_type;
435
436 iov[0].iov_base = (char *)in_buf;
437 iov[0].iov_len = in_buf->smb_buf_length + 4;
438 flags |= CIFS_NO_RESP;
439 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
440#ifdef CONFIG_CIFS_DEBUG2
441 cFYI(1, ("SendRcvNoR flags %d rc %d", flags, rc));
442#endif
443 return rc;
444}
445
446int
447SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
448 struct kvec *iov, int n_vec, int *pRespBufType ,
449 const int flags)
450{
451 int rc = 0;
452 int long_op;
453 unsigned int receive_len;
454 unsigned long timeout;
455 struct mid_q_entry *midQ;
456 struct smb_hdr *in_buf = iov[0].iov_base;
457
458 long_op = flags & CIFS_TIMEOUT_MASK;
459
460 *pRespBufType = CIFS_NO_BUFFER;
461
462 if ((ses == NULL) || (ses->server == NULL)) {
463 cifs_small_buf_release(in_buf);
464 cERROR(1, ("Null session"));
465 return -EIO;
466 }
467
468 if (ses->server->tcpStatus == CifsExiting) {
469 cifs_small_buf_release(in_buf);
470 return -ENOENT;
471 }
472
473
474
475
476
477 rc = wait_for_free_request(ses, long_op);
478 if (rc) {
479 cifs_small_buf_release(in_buf);
480 return rc;
481 }
482
483
484
485
486
487 down(&ses->server->tcpSem);
488
489 rc = allocate_mid(ses, in_buf, &midQ);
490 if (rc) {
491 up(&ses->server->tcpSem);
492 cifs_small_buf_release(in_buf);
493
494 atomic_dec(&ses->server->inFlight);
495 wake_up(&ses->server->request_q);
496 return rc;
497 }
498 rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number);
499
500 midQ->midState = MID_REQUEST_SUBMITTED;
501#ifdef CONFIG_CIFS_STATS2
502 atomic_inc(&ses->server->inSend);
503#endif
504 rc = smb_send2(ses->server->ssocket, iov, n_vec,
505 (struct sockaddr *) &(ses->server->addr.sockAddr));
506#ifdef CONFIG_CIFS_STATS2
507 atomic_dec(&ses->server->inSend);
508 midQ->when_sent = jiffies;
509#endif
510
511 up(&ses->server->tcpSem);
512 cifs_small_buf_release(in_buf);
513
514 if (rc < 0)
515 goto out;
516
517 if (long_op == CIFS_STD_OP)
518 timeout = 15 * HZ;
519 else if (long_op == CIFS_VLONG_OP)
520 timeout = 180 * HZ;
521 else if (long_op == CIFS_LONG_OP)
522 timeout = 45 * HZ;
523
524 else if (long_op == CIFS_ASYNC_OP)
525 goto out;
526 else if (long_op == CIFS_BLOCKING_OP)
527 timeout = 0x7FFFFFFF;
528 else {
529 cERROR(1, ("unknown timeout flag %d", long_op));
530 rc = -EIO;
531 goto out;
532 }
533
534
535
536 if (signal_pending(current)) {
537
538
539 timeout = 2 * HZ;
540 }
541
542
543 wait_for_response(ses, midQ, timeout, 10 * HZ);
544
545 spin_lock(&GlobalMid_Lock);
546 if (midQ->resp_buf) {
547 spin_unlock(&GlobalMid_Lock);
548 receive_len = midQ->resp_buf->smb_buf_length;
549 } else {
550 cERROR(1, ("No response to cmd %d mid %d",
551 midQ->command, midQ->mid));
552 if (midQ->midState == MID_REQUEST_SUBMITTED) {
553 if (ses->server->tcpStatus == CifsExiting)
554 rc = -EHOSTDOWN;
555 else {
556 ses->server->tcpStatus = CifsNeedReconnect;
557 midQ->midState = MID_RETRY_NEEDED;
558 }
559 }
560
561 if (rc != -EHOSTDOWN) {
562 if (midQ->midState == MID_RETRY_NEEDED) {
563 rc = -EAGAIN;
564 cFYI(1, ("marking request for retry"));
565 } else {
566 rc = -EIO;
567 }
568 }
569 spin_unlock(&GlobalMid_Lock);
570 DeleteMidQEntry(midQ);
571
572 atomic_dec(&ses->server->inFlight);
573 wake_up(&ses->server->request_q);
574 return rc;
575 }
576
577 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
578 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
579 receive_len, xid));
580 rc = -EIO;
581 } else {
582 if (midQ->resp_buf &&
583 (midQ->midState == MID_RESPONSE_RECEIVED)) {
584
585 iov[0].iov_base = (char *)midQ->resp_buf;
586 if (midQ->largeBuf)
587 *pRespBufType = CIFS_LARGE_BUFFER;
588 else
589 *pRespBufType = CIFS_SMALL_BUFFER;
590 iov[0].iov_len = receive_len + 4;
591
592 dump_smb(midQ->resp_buf, 80);
593
594 if ((receive_len > 24) &&
595 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
596 SECMODE_SIGN_ENABLED))) {
597 rc = cifs_verify_signature(midQ->resp_buf,
598 &ses->server->mac_signing_key,
599 midQ->sequence_number+1);
600 if (rc) {
601 cERROR(1, ("Unexpected SMB signature"));
602
603 }
604 }
605
606
607 rc = map_smb_to_linux_error(midQ->resp_buf,
608 flags & CIFS_LOG_ERROR);
609
610
611 if (receive_len >= sizeof(struct smb_hdr) - 4
612 +
613 (2 * midQ->resp_buf->WordCount) + 2 )
614 BCC(midQ->resp_buf) =
615 le16_to_cpu(BCC_LE(midQ->resp_buf));
616 if ((flags & CIFS_NO_RESP) == 0)
617 midQ->resp_buf = NULL;
618
619
620 } else {
621 rc = -EIO;
622 cFYI(1, ("Bad MID state?"));
623 }
624 }
625
626out:
627 DeleteMidQEntry(midQ);
628 atomic_dec(&ses->server->inFlight);
629 wake_up(&ses->server->request_q);
630
631 return rc;
632}
633
634int
635SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
636 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
637 int *pbytes_returned, const int long_op)
638{
639 int rc = 0;
640 unsigned int receive_len;
641 unsigned long timeout;
642 struct mid_q_entry *midQ;
643
644 if (ses == NULL) {
645 cERROR(1, ("Null smb session"));
646 return -EIO;
647 }
648 if (ses->server == NULL) {
649 cERROR(1, ("Null tcp session"));
650 return -EIO;
651 }
652
653 if (ses->server->tcpStatus == CifsExiting)
654 return -ENOENT;
655
656
657
658
659
660 rc = wait_for_free_request(ses, long_op);
661 if (rc)
662 return rc;
663
664
665
666
667
668 down(&ses->server->tcpSem);
669
670 rc = allocate_mid(ses, in_buf, &midQ);
671 if (rc) {
672 up(&ses->server->tcpSem);
673
674 atomic_dec(&ses->server->inFlight);
675 wake_up(&ses->server->request_q);
676 return rc;
677 }
678
679 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
680 cERROR(1, ("Illegal length, greater than maximum frame, %d",
681 in_buf->smb_buf_length));
682 DeleteMidQEntry(midQ);
683 up(&ses->server->tcpSem);
684
685 atomic_dec(&ses->server->inFlight);
686 wake_up(&ses->server->request_q);
687 return -EIO;
688 }
689
690 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
691
692 midQ->midState = MID_REQUEST_SUBMITTED;
693#ifdef CONFIG_CIFS_STATS2
694 atomic_inc(&ses->server->inSend);
695#endif
696 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
697 (struct sockaddr *) &(ses->server->addr.sockAddr));
698#ifdef CONFIG_CIFS_STATS2
699 atomic_dec(&ses->server->inSend);
700 midQ->when_sent = jiffies;
701#endif
702 up(&ses->server->tcpSem);
703
704 if (rc < 0)
705 goto out;
706
707 if (long_op == CIFS_STD_OP)
708 timeout = 15 * HZ;
709
710
711 else if (long_op == CIFS_ASYNC_OP)
712 goto out;
713 else if (long_op == CIFS_VLONG_OP)
714 timeout = 180 * HZ;
715 else if (long_op == CIFS_LONG_OP)
716 timeout = 45 * HZ;
717
718 else if (long_op == CIFS_BLOCKING_OP)
719 timeout = 0x7FFFFFFF;
720 else {
721 cERROR(1, ("unknown timeout flag %d", long_op));
722 rc = -EIO;
723 goto out;
724 }
725
726 if (signal_pending(current)) {
727
728
729 timeout = 2 * HZ;
730 }
731
732
733 wait_for_response(ses, midQ, timeout, 10 * HZ);
734
735 spin_lock(&GlobalMid_Lock);
736 if (midQ->resp_buf) {
737 spin_unlock(&GlobalMid_Lock);
738 receive_len = midQ->resp_buf->smb_buf_length;
739 } else {
740 cERROR(1, ("No response for cmd %d mid %d",
741 midQ->command, midQ->mid));
742 if (midQ->midState == MID_REQUEST_SUBMITTED) {
743 if (ses->server->tcpStatus == CifsExiting)
744 rc = -EHOSTDOWN;
745 else {
746 ses->server->tcpStatus = CifsNeedReconnect;
747 midQ->midState = MID_RETRY_NEEDED;
748 }
749 }
750
751 if (rc != -EHOSTDOWN) {
752 if (midQ->midState == MID_RETRY_NEEDED) {
753 rc = -EAGAIN;
754 cFYI(1, ("marking request for retry"));
755 } else {
756 rc = -EIO;
757 }
758 }
759 spin_unlock(&GlobalMid_Lock);
760 DeleteMidQEntry(midQ);
761
762 atomic_dec(&ses->server->inFlight);
763 wake_up(&ses->server->request_q);
764 return rc;
765 }
766
767 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
768 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
769 receive_len, xid));
770 rc = -EIO;
771 } else {
772
773 if (midQ->resp_buf && out_buf
774 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
775 out_buf->smb_buf_length = receive_len;
776 memcpy((char *)out_buf + 4,
777 (char *)midQ->resp_buf + 4,
778 receive_len);
779
780 dump_smb(out_buf, 92);
781
782 if ((receive_len > 24) &&
783 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
784 SECMODE_SIGN_ENABLED))) {
785 rc = cifs_verify_signature(out_buf,
786 &ses->server->mac_signing_key,
787 midQ->sequence_number+1);
788 if (rc) {
789 cERROR(1, ("Unexpected SMB signature"));
790
791 }
792 }
793
794 *pbytes_returned = out_buf->smb_buf_length;
795
796
797 rc = map_smb_to_linux_error(out_buf, 0 );
798
799
800 if (receive_len >= sizeof(struct smb_hdr) - 4
801 +
802 (2 * out_buf->WordCount) + 2 )
803 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
804 } else {
805 rc = -EIO;
806 cERROR(1, ("Bad MID state?"));
807 }
808 }
809
810out:
811 DeleteMidQEntry(midQ);
812 atomic_dec(&ses->server->inFlight);
813 wake_up(&ses->server->request_q);
814
815 return rc;
816}
817
818
819
820static int
821send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
822 struct mid_q_entry *midQ)
823{
824 int rc = 0;
825 struct cifsSesInfo *ses = tcon->ses;
826 __u16 mid = in_buf->Mid;
827
828 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
829 in_buf->Mid = mid;
830 down(&ses->server->tcpSem);
831 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
832 if (rc) {
833 up(&ses->server->tcpSem);
834 return rc;
835 }
836 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
837 (struct sockaddr *) &(ses->server->addr.sockAddr));
838 up(&ses->server->tcpSem);
839 return rc;
840}
841
842
843
844
845static int
846send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
847 struct smb_hdr *in_buf,
848 struct smb_hdr *out_buf)
849{
850 int bytes_returned;
851 struct cifsSesInfo *ses = tcon->ses;
852 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
853
854
855
856
857
858
859 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
860 pSMB->Timeout = 0;
861 pSMB->hdr.Mid = GetNextMid(ses->server);
862
863 return SendReceive(xid, ses, in_buf, out_buf,
864 &bytes_returned, CIFS_STD_OP);
865}
866
867int
868SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
869 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
870 int *pbytes_returned)
871{
872 int rc = 0;
873 int rstart = 0;
874 unsigned int receive_len;
875 struct mid_q_entry *midQ;
876 struct cifsSesInfo *ses;
877
878 if (tcon == NULL || tcon->ses == NULL) {
879 cERROR(1, ("Null smb session"));
880 return -EIO;
881 }
882 ses = tcon->ses;
883
884 if (ses->server == NULL) {
885 cERROR(1, ("Null tcp session"));
886 return -EIO;
887 }
888
889 if (ses->server->tcpStatus == CifsExiting)
890 return -ENOENT;
891
892
893
894
895
896 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP);
897 if (rc)
898 return rc;
899
900
901
902
903
904 down(&ses->server->tcpSem);
905
906 rc = allocate_mid(ses, in_buf, &midQ);
907 if (rc) {
908 up(&ses->server->tcpSem);
909 return rc;
910 }
911
912 if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
913 up(&ses->server->tcpSem);
914 cERROR(1, ("Illegal length, greater than maximum frame, %d",
915 in_buf->smb_buf_length));
916 DeleteMidQEntry(midQ);
917 return -EIO;
918 }
919
920 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
921
922 midQ->midState = MID_REQUEST_SUBMITTED;
923#ifdef CONFIG_CIFS_STATS2
924 atomic_inc(&ses->server->inSend);
925#endif
926 rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
927 (struct sockaddr *) &(ses->server->addr.sockAddr));
928#ifdef CONFIG_CIFS_STATS2
929 atomic_dec(&ses->server->inSend);
930 midQ->when_sent = jiffies;
931#endif
932 up(&ses->server->tcpSem);
933
934 if (rc < 0) {
935 DeleteMidQEntry(midQ);
936 return rc;
937 }
938
939
940 rc = wait_event_interruptible(ses->server->response_q,
941 (!(midQ->midState == MID_REQUEST_SUBMITTED)) ||
942 ((ses->server->tcpStatus != CifsGood) &&
943 (ses->server->tcpStatus != CifsNew)));
944
945
946 if ((rc == -ERESTARTSYS) &&
947 (midQ->midState == MID_REQUEST_SUBMITTED) &&
948 ((ses->server->tcpStatus == CifsGood) ||
949 (ses->server->tcpStatus == CifsNew))) {
950
951 if (in_buf->Command == SMB_COM_TRANSACTION2) {
952
953
954
955 rc = send_nt_cancel(tcon, in_buf, midQ);
956 if (rc) {
957 DeleteMidQEntry(midQ);
958 return rc;
959 }
960 } else {
961
962
963
964 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
965
966
967
968 if (rc && rc != -ENOLCK) {
969 DeleteMidQEntry(midQ);
970 return rc;
971 }
972 }
973
974
975 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
976
977 rstart = 1;
978 }
979 }
980
981 spin_lock(&GlobalMid_Lock);
982 if (midQ->resp_buf) {
983 spin_unlock(&GlobalMid_Lock);
984 receive_len = midQ->resp_buf->smb_buf_length;
985 } else {
986 cERROR(1, ("No response for cmd %d mid %d",
987 midQ->command, midQ->mid));
988 if (midQ->midState == MID_REQUEST_SUBMITTED) {
989 if (ses->server->tcpStatus == CifsExiting)
990 rc = -EHOSTDOWN;
991 else {
992 ses->server->tcpStatus = CifsNeedReconnect;
993 midQ->midState = MID_RETRY_NEEDED;
994 }
995 }
996
997 if (rc != -EHOSTDOWN) {
998 if (midQ->midState == MID_RETRY_NEEDED) {
999 rc = -EAGAIN;
1000 cFYI(1, ("marking request for retry"));
1001 } else {
1002 rc = -EIO;
1003 }
1004 }
1005 spin_unlock(&GlobalMid_Lock);
1006 DeleteMidQEntry(midQ);
1007 return rc;
1008 }
1009
1010 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
1011 cERROR(1, ("Frame too large received. Length: %d Xid: %d",
1012 receive_len, xid));
1013 rc = -EIO;
1014 } else {
1015
1016 if (midQ->resp_buf && out_buf
1017 && (midQ->midState == MID_RESPONSE_RECEIVED)) {
1018 out_buf->smb_buf_length = receive_len;
1019 memcpy((char *)out_buf + 4,
1020 (char *)midQ->resp_buf + 4,
1021 receive_len);
1022
1023 dump_smb(out_buf, 92);
1024
1025 if ((receive_len > 24) &&
1026 (ses->server->secMode & (SECMODE_SIGN_REQUIRED |
1027 SECMODE_SIGN_ENABLED))) {
1028 rc = cifs_verify_signature(out_buf,
1029 &ses->server->mac_signing_key,
1030 midQ->sequence_number+1);
1031 if (rc) {
1032 cERROR(1, ("Unexpected SMB signature"));
1033
1034 }
1035 }
1036
1037 *pbytes_returned = out_buf->smb_buf_length;
1038
1039
1040 rc = map_smb_to_linux_error(out_buf, 0 );
1041
1042
1043 if (receive_len >= sizeof(struct smb_hdr) - 4
1044 +
1045 (2 * out_buf->WordCount) + 2 )
1046 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf));
1047 } else {
1048 rc = -EIO;
1049 cERROR(1, ("Bad MID state?"));
1050 }
1051 }
1052 DeleteMidQEntry(midQ);
1053 if (rstart && rc == -EACCES)
1054 return -ERESTARTSYS;
1055 return rc;
1056}
1057