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/gfp.h>
26#include <linux/wait.h>
27#include <linux/net.h>
28#include <linux/delay.h>
29#include <linux/freezer.h>
30#include <linux/tcp.h>
31#include <linux/highmem.h>
32#include <asm/uaccess.h>
33#include <asm/processor.h>
34#include <linux/mempool.h>
35#include "cifspdu.h"
36#include "cifsglob.h"
37#include "cifsproto.h"
38#include "cifs_debug.h"
39
40void
41cifs_wake_up_task(struct mid_q_entry *mid)
42{
43 wake_up_process(mid->callback_data);
44}
45
46struct mid_q_entry *
47AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
48{
49 struct mid_q_entry *temp;
50
51 if (server == NULL) {
52 cifs_dbg(VFS, "Null TCP session in AllocMidQEntry\n");
53 return NULL;
54 }
55
56 temp = mempool_alloc(cifs_mid_poolp, GFP_NOFS);
57 if (temp == NULL)
58 return temp;
59 else {
60 memset(temp, 0, sizeof(struct mid_q_entry));
61 temp->mid = get_mid(smb_buffer);
62 temp->pid = current->pid;
63 temp->command = cpu_to_le16(smb_buffer->Command);
64 cifs_dbg(FYI, "For smb_command %d\n", smb_buffer->Command);
65
66
67 temp->when_alloc = jiffies;
68 temp->server = server;
69
70
71
72
73
74 temp->callback = cifs_wake_up_task;
75 temp->callback_data = current;
76 }
77
78 atomic_inc(&midCount);
79 temp->mid_state = MID_REQUEST_ALLOCATED;
80 return temp;
81}
82
83void
84DeleteMidQEntry(struct mid_q_entry *midEntry)
85{
86#ifdef CONFIG_CIFS_STATS2
87 __le16 command = midEntry->server->vals->lock_cmd;
88 unsigned long now;
89#endif
90 midEntry->mid_state = MID_FREE;
91 atomic_dec(&midCount);
92 if (midEntry->large_buf)
93 cifs_buf_release(midEntry->resp_buf);
94 else
95 cifs_small_buf_release(midEntry->resp_buf);
96#ifdef CONFIG_CIFS_STATS2
97 now = jiffies;
98
99
100 if ((now - midEntry->when_alloc) > HZ) {
101 if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
102 pr_debug(" CIFS slow rsp: cmd %d mid %llu",
103 midEntry->command, midEntry->mid);
104 pr_info(" A: 0x%lx S: 0x%lx R: 0x%lx\n",
105 now - midEntry->when_alloc,
106 now - midEntry->when_sent,
107 now - midEntry->when_received);
108 }
109 }
110#endif
111 mempool_free(midEntry, cifs_mid_poolp);
112}
113
114void
115cifs_delete_mid(struct mid_q_entry *mid)
116{
117 spin_lock(&GlobalMid_Lock);
118 list_del(&mid->qhead);
119 spin_unlock(&GlobalMid_Lock);
120
121 DeleteMidQEntry(mid);
122}
123
124
125
126
127
128
129
130
131
132
133
134static int
135smb_send_kvec(struct TCP_Server_Info *server, struct kvec *iov, size_t n_vec,
136 size_t *sent)
137{
138 int rc = 0;
139 int i = 0;
140 struct msghdr smb_msg;
141 unsigned int remaining;
142 size_t first_vec = 0;
143 struct socket *ssocket = server->ssocket;
144
145 *sent = 0;
146
147 smb_msg.msg_name = (struct sockaddr *) &server->dstaddr;
148 smb_msg.msg_namelen = sizeof(struct sockaddr);
149 smb_msg.msg_control = NULL;
150 smb_msg.msg_controllen = 0;
151 if (server->noblocksnd)
152 smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL;
153 else
154 smb_msg.msg_flags = MSG_NOSIGNAL;
155
156 remaining = 0;
157 for (i = 0; i < n_vec; i++)
158 remaining += iov[i].iov_len;
159
160 i = 0;
161 while (remaining) {
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 rc = kernel_sendmsg(ssocket, &smb_msg, &iov[first_vec],
181 n_vec - first_vec, remaining);
182 if (rc == -EAGAIN) {
183 i++;
184 if (i >= 14 || (!server->noblocksnd && (i > 2))) {
185 cifs_dbg(VFS, "sends on sock %p stuck for 15 seconds\n",
186 ssocket);
187 rc = -EAGAIN;
188 break;
189 }
190 msleep(1 << i);
191 continue;
192 }
193
194 if (rc < 0)
195 break;
196
197
198 *sent += rc;
199
200 if (rc == remaining) {
201 remaining = 0;
202 break;
203 }
204
205 if (rc > remaining) {
206 cifs_dbg(VFS, "sent %d requested %d\n", rc, remaining);
207 break;
208 }
209
210 if (rc == 0) {
211
212
213 cifs_dbg(VFS, "tcp sent no data\n");
214 msleep(500);
215 continue;
216 }
217
218 remaining -= rc;
219
220
221 for (i = first_vec; i < n_vec; i++) {
222 if (iov[i].iov_len) {
223 if (rc > iov[i].iov_len) {
224 rc -= iov[i].iov_len;
225 iov[i].iov_len = 0;
226 } else {
227 iov[i].iov_base += rc;
228 iov[i].iov_len -= rc;
229 first_vec = i;
230 break;
231 }
232 }
233 }
234
235 i = 0;
236 rc = 0;
237 }
238 return rc;
239}
240
241
242
243
244
245
246
247
248
249
250
251void
252cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
253 struct kvec *iov)
254{
255
256
257
258
259
260
261
262
263
264 iov->iov_base = kmap(rqst->rq_pages[idx]);
265
266
267 if (idx == (rqst->rq_npages - 1))
268 iov->iov_len = rqst->rq_tailsz;
269 else
270 iov->iov_len = rqst->rq_pagesz;
271}
272
273static unsigned long
274rqst_len(struct smb_rqst *rqst)
275{
276 unsigned int i;
277 struct kvec *iov = rqst->rq_iov;
278 unsigned long buflen = 0;
279
280
281 for (i = 0; i < rqst->rq_nvec; i++)
282 buflen += iov[i].iov_len;
283
284
285 if (rqst->rq_npages) {
286 buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
287 buflen += rqst->rq_tailsz;
288 }
289
290 return buflen;
291}
292
293static int
294smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
295{
296 int rc;
297 struct kvec *iov = rqst->rq_iov;
298 int n_vec = rqst->rq_nvec;
299 unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
300 unsigned long send_length;
301 unsigned int i;
302 size_t total_len = 0, sent;
303 struct socket *ssocket = server->ssocket;
304 int val = 1;
305
306 if (ssocket == NULL)
307 return -ENOTSOCK;
308
309
310 send_length = rqst_len(rqst);
311 if (send_length != smb_buf_length + 4) {
312 WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
313 send_length, smb_buf_length);
314 return -EIO;
315 }
316
317 cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
318 dump_smb(iov[0].iov_base, iov[0].iov_len);
319
320
321 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
322 (char *)&val, sizeof(val));
323
324 rc = smb_send_kvec(server, iov, n_vec, &sent);
325 if (rc < 0)
326 goto uncork;
327
328 total_len += sent;
329
330
331 for (i = 0; i < rqst->rq_npages; i++) {
332 struct kvec p_iov;
333
334 cifs_rqst_page_to_kvec(rqst, i, &p_iov);
335 rc = smb_send_kvec(server, &p_iov, 1, &sent);
336 kunmap(rqst->rq_pages[i]);
337 if (rc < 0)
338 break;
339
340 total_len += sent;
341 }
342
343uncork:
344
345 val = 0;
346 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
347 (char *)&val, sizeof(val));
348
349 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
350 cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
351 smb_buf_length + 4, total_len);
352
353
354
355
356
357 server->tcpStatus = CifsNeedReconnect;
358 }
359
360 if (rc < 0 && rc != -EINTR)
361 cifs_dbg(VFS, "Error %d sending data on socket to server\n",
362 rc);
363 else
364 rc = 0;
365
366 return rc;
367}
368
369static int
370smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
371{
372 struct smb_rqst rqst = { .rq_iov = iov,
373 .rq_nvec = n_vec };
374
375 return smb_send_rqst(server, &rqst);
376}
377
378int
379smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
380 unsigned int smb_buf_length)
381{
382 struct kvec iov;
383
384 iov.iov_base = smb_buffer;
385 iov.iov_len = smb_buf_length + 4;
386
387 return smb_sendv(server, &iov, 1);
388}
389
390static int
391wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
392 int *credits)
393{
394 int rc;
395
396 spin_lock(&server->req_lock);
397 if (timeout == CIFS_ASYNC_OP) {
398
399 server->in_flight++;
400 *credits -= 1;
401 spin_unlock(&server->req_lock);
402 return 0;
403 }
404
405 while (1) {
406 if (*credits <= 0) {
407 spin_unlock(&server->req_lock);
408 cifs_num_waiters_inc(server);
409 rc = wait_event_killable(server->request_q,
410 has_credits(server, credits));
411 cifs_num_waiters_dec(server);
412 if (rc)
413 return rc;
414 spin_lock(&server->req_lock);
415 } else {
416 if (server->tcpStatus == CifsExiting) {
417 spin_unlock(&server->req_lock);
418 return -ENOENT;
419 }
420
421
422
423
424
425
426
427 if (timeout != CIFS_BLOCKING_OP) {
428 *credits -= 1;
429 server->in_flight++;
430 }
431 spin_unlock(&server->req_lock);
432 break;
433 }
434 }
435 return 0;
436}
437
438static int
439wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
440 const int optype)
441{
442 int *val;
443
444 val = server->ops->get_credits_field(server, optype);
445
446 if (*val <= 0 && optype == CIFS_ECHO_OP)
447 return -EAGAIN;
448 return wait_for_free_credits(server, timeout, val);
449}
450
451int
452cifs_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
453 unsigned int *num, unsigned int *credits)
454{
455 *num = size;
456 *credits = 0;
457 return 0;
458}
459
460static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
461 struct mid_q_entry **ppmidQ)
462{
463 if (ses->server->tcpStatus == CifsExiting) {
464 return -ENOENT;
465 }
466
467 if (ses->server->tcpStatus == CifsNeedReconnect) {
468 cifs_dbg(FYI, "tcp session dead - return to caller to retry\n");
469 return -EAGAIN;
470 }
471
472 if (ses->status == CifsNew) {
473 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
474 (in_buf->Command != SMB_COM_NEGOTIATE))
475 return -EAGAIN;
476
477 }
478
479 if (ses->status == CifsExiting) {
480
481 if (in_buf->Command != SMB_COM_LOGOFF_ANDX)
482 return -EAGAIN;
483
484 }
485
486 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
487 if (*ppmidQ == NULL)
488 return -ENOMEM;
489 spin_lock(&GlobalMid_Lock);
490 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
491 spin_unlock(&GlobalMid_Lock);
492 return 0;
493}
494
495static int
496wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
497{
498 int error;
499
500 error = wait_event_freezekillable_unsafe(server->response_q,
501 midQ->mid_state != MID_REQUEST_SUBMITTED);
502 if (error < 0)
503 return -ERESTARTSYS;
504
505 return 0;
506}
507
508struct mid_q_entry *
509cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
510{
511 int rc;
512 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
513 struct mid_q_entry *mid;
514
515
516 if (server->sign)
517 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
518
519 mid = AllocMidQEntry(hdr, server);
520 if (mid == NULL)
521 return ERR_PTR(-ENOMEM);
522
523 rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
524 if (rc) {
525 DeleteMidQEntry(mid);
526 return ERR_PTR(rc);
527 }
528
529 return mid;
530}
531
532
533
534
535
536int
537cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
538 mid_receive_t *receive, mid_callback_t *callback,
539 void *cbdata, const int flags)
540{
541 int rc, timeout, optype;
542 struct mid_q_entry *mid;
543 unsigned int credits = 0;
544
545 timeout = flags & CIFS_TIMEOUT_MASK;
546 optype = flags & CIFS_OP_MASK;
547
548 if ((flags & CIFS_HAS_CREDITS) == 0) {
549 rc = wait_for_free_request(server, timeout, optype);
550 if (rc)
551 return rc;
552 credits = 1;
553 }
554
555 mutex_lock(&server->srv_mutex);
556 mid = server->ops->setup_async_request(server, rqst);
557 if (IS_ERR(mid)) {
558 mutex_unlock(&server->srv_mutex);
559 add_credits_and_wake_if(server, credits, optype);
560 return PTR_ERR(mid);
561 }
562
563 mid->receive = receive;
564 mid->callback = callback;
565 mid->callback_data = cbdata;
566 mid->mid_state = MID_REQUEST_SUBMITTED;
567
568
569 spin_lock(&GlobalMid_Lock);
570 list_add_tail(&mid->qhead, &server->pending_mid_q);
571 spin_unlock(&GlobalMid_Lock);
572
573
574 cifs_in_send_inc(server);
575 rc = smb_send_rqst(server, rqst);
576 cifs_in_send_dec(server);
577 cifs_save_when_sent(mid);
578
579 if (rc < 0) {
580 server->sequence_number -= 2;
581 cifs_delete_mid(mid);
582 }
583
584 mutex_unlock(&server->srv_mutex);
585
586 if (rc == 0)
587 return 0;
588
589 add_credits_and_wake_if(server, credits, optype);
590 return rc;
591}
592
593
594
595
596
597
598
599
600
601
602int
603SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
604 char *in_buf, int flags)
605{
606 int rc;
607 struct kvec iov[1];
608 int resp_buf_type;
609
610 iov[0].iov_base = in_buf;
611 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
612 flags |= CIFS_NO_RESP;
613 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
614 cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
615
616 return rc;
617}
618
619static int
620cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
621{
622 int rc = 0;
623
624 cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
625 __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
626
627 spin_lock(&GlobalMid_Lock);
628 switch (mid->mid_state) {
629 case MID_RESPONSE_RECEIVED:
630 spin_unlock(&GlobalMid_Lock);
631 return rc;
632 case MID_RETRY_NEEDED:
633 rc = -EAGAIN;
634 break;
635 case MID_RESPONSE_MALFORMED:
636 rc = -EIO;
637 break;
638 case MID_SHUTDOWN:
639 rc = -EHOSTDOWN;
640 break;
641 default:
642 list_del_init(&mid->qhead);
643 cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
644 __func__, mid->mid, mid->mid_state);
645 rc = -EIO;
646 }
647 spin_unlock(&GlobalMid_Lock);
648
649 mutex_lock(&server->srv_mutex);
650 DeleteMidQEntry(mid);
651 mutex_unlock(&server->srv_mutex);
652 return rc;
653}
654
655static inline int
656send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
657{
658 return server->ops->send_cancel ?
659 server->ops->send_cancel(server, buf, mid) : 0;
660}
661
662int
663cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
664 bool log_error)
665{
666 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
667
668 dump_smb(mid->resp_buf, min_t(u32, 92, len));
669
670
671 if (server->sign) {
672 struct kvec iov;
673 int rc = 0;
674 struct smb_rqst rqst = { .rq_iov = &iov,
675 .rq_nvec = 1 };
676
677 iov.iov_base = mid->resp_buf;
678 iov.iov_len = len;
679
680 rc = cifs_verify_signature(&rqst, server,
681 mid->sequence_number);
682 if (rc)
683 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
684 rc);
685 }
686
687
688 return map_smb_to_linux_error(mid->resp_buf, log_error);
689}
690
691struct mid_q_entry *
692cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
693{
694 int rc;
695 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
696 struct mid_q_entry *mid;
697
698 rc = allocate_mid(ses, hdr, &mid);
699 if (rc)
700 return ERR_PTR(rc);
701 rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
702 if (rc) {
703 cifs_delete_mid(mid);
704 return ERR_PTR(rc);
705 }
706 return mid;
707}
708
709int
710SendReceive2(const unsigned int xid, struct cifs_ses *ses,
711 struct kvec *iov, int n_vec, int *resp_buf_type ,
712 const int flags)
713{
714 int rc = 0;
715 int timeout, optype;
716 struct mid_q_entry *midQ;
717 char *buf = iov[0].iov_base;
718 unsigned int credits = 1;
719 struct smb_rqst rqst = { .rq_iov = iov,
720 .rq_nvec = n_vec };
721
722 timeout = flags & CIFS_TIMEOUT_MASK;
723 optype = flags & CIFS_OP_MASK;
724
725 *resp_buf_type = CIFS_NO_BUFFER;
726
727 if ((ses == NULL) || (ses->server == NULL)) {
728 cifs_small_buf_release(buf);
729 cifs_dbg(VFS, "Null session\n");
730 return -EIO;
731 }
732
733 if (ses->server->tcpStatus == CifsExiting) {
734 cifs_small_buf_release(buf);
735 return -ENOENT;
736 }
737
738
739
740
741
742
743
744 rc = wait_for_free_request(ses->server, timeout, optype);
745 if (rc) {
746 cifs_small_buf_release(buf);
747 return rc;
748 }
749
750
751
752
753
754
755
756 mutex_lock(&ses->server->srv_mutex);
757
758 midQ = ses->server->ops->setup_request(ses, &rqst);
759 if (IS_ERR(midQ)) {
760 mutex_unlock(&ses->server->srv_mutex);
761 cifs_small_buf_release(buf);
762
763 add_credits(ses->server, 1, optype);
764 return PTR_ERR(midQ);
765 }
766
767 midQ->mid_state = MID_REQUEST_SUBMITTED;
768 cifs_in_send_inc(ses->server);
769 rc = smb_sendv(ses->server, iov, n_vec);
770 cifs_in_send_dec(ses->server);
771 cifs_save_when_sent(midQ);
772
773 if (rc < 0)
774 ses->server->sequence_number -= 2;
775 mutex_unlock(&ses->server->srv_mutex);
776
777 if (rc < 0) {
778 cifs_small_buf_release(buf);
779 goto out;
780 }
781
782 if (timeout == CIFS_ASYNC_OP) {
783 cifs_small_buf_release(buf);
784 goto out;
785 }
786
787 rc = wait_for_response(ses->server, midQ);
788 if (rc != 0) {
789 send_cancel(ses->server, buf, midQ);
790 spin_lock(&GlobalMid_Lock);
791 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
792 midQ->callback = DeleteMidQEntry;
793 spin_unlock(&GlobalMid_Lock);
794 cifs_small_buf_release(buf);
795 add_credits(ses->server, 1, optype);
796 return rc;
797 }
798 spin_unlock(&GlobalMid_Lock);
799 }
800
801 cifs_small_buf_release(buf);
802
803 rc = cifs_sync_mid_result(midQ, ses->server);
804 if (rc != 0) {
805 add_credits(ses->server, 1, optype);
806 return rc;
807 }
808
809 if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
810 rc = -EIO;
811 cifs_dbg(FYI, "Bad MID state?\n");
812 goto out;
813 }
814
815 buf = (char *)midQ->resp_buf;
816 iov[0].iov_base = buf;
817 iov[0].iov_len = get_rfc1002_length(buf) + 4;
818 if (midQ->large_buf)
819 *resp_buf_type = CIFS_LARGE_BUFFER;
820 else
821 *resp_buf_type = CIFS_SMALL_BUFFER;
822
823 credits = ses->server->ops->get_credits(midQ);
824
825 rc = ses->server->ops->check_receive(midQ, ses->server,
826 flags & CIFS_LOG_ERROR);
827
828
829 if ((flags & CIFS_NO_RESP) == 0)
830 midQ->resp_buf = NULL;
831out:
832 cifs_delete_mid(midQ);
833 add_credits(ses->server, credits, optype);
834
835 return rc;
836}
837
838int
839SendReceive(const unsigned int xid, struct cifs_ses *ses,
840 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
841 int *pbytes_returned, const int timeout)
842{
843 int rc = 0;
844 struct mid_q_entry *midQ;
845
846 if (ses == NULL) {
847 cifs_dbg(VFS, "Null smb session\n");
848 return -EIO;
849 }
850 if (ses->server == NULL) {
851 cifs_dbg(VFS, "Null tcp session\n");
852 return -EIO;
853 }
854
855 if (ses->server->tcpStatus == CifsExiting)
856 return -ENOENT;
857
858
859
860
861
862 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
863 MAX_CIFS_HDR_SIZE - 4) {
864 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
865 be32_to_cpu(in_buf->smb_buf_length));
866 return -EIO;
867 }
868
869 rc = wait_for_free_request(ses->server, timeout, 0);
870 if (rc)
871 return rc;
872
873
874
875
876
877 mutex_lock(&ses->server->srv_mutex);
878
879 rc = allocate_mid(ses, in_buf, &midQ);
880 if (rc) {
881 mutex_unlock(&ses->server->srv_mutex);
882
883 add_credits(ses->server, 1, 0);
884 return rc;
885 }
886
887 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
888 if (rc) {
889 mutex_unlock(&ses->server->srv_mutex);
890 goto out;
891 }
892
893 midQ->mid_state = MID_REQUEST_SUBMITTED;
894
895 cifs_in_send_inc(ses->server);
896 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
897 cifs_in_send_dec(ses->server);
898 cifs_save_when_sent(midQ);
899
900 if (rc < 0)
901 ses->server->sequence_number -= 2;
902
903 mutex_unlock(&ses->server->srv_mutex);
904
905 if (rc < 0)
906 goto out;
907
908 if (timeout == CIFS_ASYNC_OP)
909 goto out;
910
911 rc = wait_for_response(ses->server, midQ);
912 if (rc != 0) {
913 send_cancel(ses->server, in_buf, midQ);
914 spin_lock(&GlobalMid_Lock);
915 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
916
917 midQ->callback = DeleteMidQEntry;
918 spin_unlock(&GlobalMid_Lock);
919 add_credits(ses->server, 1, 0);
920 return rc;
921 }
922 spin_unlock(&GlobalMid_Lock);
923 }
924
925 rc = cifs_sync_mid_result(midQ, ses->server);
926 if (rc != 0) {
927 add_credits(ses->server, 1, 0);
928 return rc;
929 }
930
931 if (!midQ->resp_buf || !out_buf ||
932 midQ->mid_state != MID_RESPONSE_RECEIVED) {
933 rc = -EIO;
934 cifs_dbg(VFS, "Bad MID state?\n");
935 goto out;
936 }
937
938 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
939 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
940 rc = cifs_check_receive(midQ, ses->server, 0);
941out:
942 cifs_delete_mid(midQ);
943 add_credits(ses->server, 1, 0);
944
945 return rc;
946}
947
948
949
950
951static int
952send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
953 struct smb_hdr *in_buf,
954 struct smb_hdr *out_buf)
955{
956 int bytes_returned;
957 struct cifs_ses *ses = tcon->ses;
958 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
959
960
961
962
963
964
965 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
966 pSMB->Timeout = 0;
967 pSMB->hdr.Mid = get_next_mid(ses->server);
968
969 return SendReceive(xid, ses, in_buf, out_buf,
970 &bytes_returned, 0);
971}
972
973int
974SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
975 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
976 int *pbytes_returned)
977{
978 int rc = 0;
979 int rstart = 0;
980 struct mid_q_entry *midQ;
981 struct cifs_ses *ses;
982
983 if (tcon == NULL || tcon->ses == NULL) {
984 cifs_dbg(VFS, "Null smb session\n");
985 return -EIO;
986 }
987 ses = tcon->ses;
988
989 if (ses->server == NULL) {
990 cifs_dbg(VFS, "Null tcp session\n");
991 return -EIO;
992 }
993
994 if (ses->server->tcpStatus == CifsExiting)
995 return -ENOENT;
996
997
998
999
1000
1001 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
1002 MAX_CIFS_HDR_SIZE - 4) {
1003 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
1004 be32_to_cpu(in_buf->smb_buf_length));
1005 return -EIO;
1006 }
1007
1008 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
1009 if (rc)
1010 return rc;
1011
1012
1013
1014
1015
1016 mutex_lock(&ses->server->srv_mutex);
1017
1018 rc = allocate_mid(ses, in_buf, &midQ);
1019 if (rc) {
1020 mutex_unlock(&ses->server->srv_mutex);
1021 return rc;
1022 }
1023
1024 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1025 if (rc) {
1026 cifs_delete_mid(midQ);
1027 mutex_unlock(&ses->server->srv_mutex);
1028 return rc;
1029 }
1030
1031 midQ->mid_state = MID_REQUEST_SUBMITTED;
1032 cifs_in_send_inc(ses->server);
1033 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
1034 cifs_in_send_dec(ses->server);
1035 cifs_save_when_sent(midQ);
1036
1037 if (rc < 0)
1038 ses->server->sequence_number -= 2;
1039
1040 mutex_unlock(&ses->server->srv_mutex);
1041
1042 if (rc < 0) {
1043 cifs_delete_mid(midQ);
1044 return rc;
1045 }
1046
1047
1048 rc = wait_event_interruptible(ses->server->response_q,
1049 (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
1050 ((ses->server->tcpStatus != CifsGood) &&
1051 (ses->server->tcpStatus != CifsNew)));
1052
1053
1054 if ((rc == -ERESTARTSYS) &&
1055 (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
1056 ((ses->server->tcpStatus == CifsGood) ||
1057 (ses->server->tcpStatus == CifsNew))) {
1058
1059 if (in_buf->Command == SMB_COM_TRANSACTION2) {
1060
1061
1062 rc = send_cancel(ses->server, in_buf, midQ);
1063 if (rc) {
1064 cifs_delete_mid(midQ);
1065 return rc;
1066 }
1067 } else {
1068
1069
1070
1071 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1072
1073
1074
1075 if (rc && rc != -ENOLCK) {
1076 cifs_delete_mid(midQ);
1077 return rc;
1078 }
1079 }
1080
1081 rc = wait_for_response(ses->server, midQ);
1082 if (rc) {
1083 send_cancel(ses->server, in_buf, midQ);
1084 spin_lock(&GlobalMid_Lock);
1085 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1086
1087 midQ->callback = DeleteMidQEntry;
1088 spin_unlock(&GlobalMid_Lock);
1089 return rc;
1090 }
1091 spin_unlock(&GlobalMid_Lock);
1092 }
1093
1094
1095 rstart = 1;
1096 }
1097
1098 rc = cifs_sync_mid_result(midQ, ses->server);
1099 if (rc != 0)
1100 return rc;
1101
1102
1103 if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
1104 rc = -EIO;
1105 cifs_dbg(VFS, "Bad MID state?\n");
1106 goto out;
1107 }
1108
1109 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
1110 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
1111 rc = cifs_check_receive(midQ, ses->server, 0);
1112out:
1113 cifs_delete_mid(midQ);
1114 if (rstart && rc == -EACCES)
1115 return -ERESTARTSYS;
1116 return rc;
1117}
1118