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 mutex_unlock(&server->srv_mutex);
582
583 if (rc == 0)
584 return 0;
585
586 cifs_delete_mid(mid);
587 add_credits_and_wake_if(server, credits, optype);
588 return rc;
589}
590
591
592
593
594
595
596
597
598
599
600int
601SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
602 char *in_buf, int flags)
603{
604 int rc;
605 struct kvec iov[1];
606 int resp_buf_type;
607
608 iov[0].iov_base = in_buf;
609 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
610 flags |= CIFS_NO_RESP;
611 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
612 cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
613
614 return rc;
615}
616
617static int
618cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
619{
620 int rc = 0;
621
622 cifs_dbg(FYI, "%s: cmd=%d mid=%llu state=%d\n",
623 __func__, le16_to_cpu(mid->command), mid->mid, mid->mid_state);
624
625 spin_lock(&GlobalMid_Lock);
626 switch (mid->mid_state) {
627 case MID_RESPONSE_RECEIVED:
628 spin_unlock(&GlobalMid_Lock);
629 return rc;
630 case MID_RETRY_NEEDED:
631 rc = -EAGAIN;
632 break;
633 case MID_RESPONSE_MALFORMED:
634 rc = -EIO;
635 break;
636 case MID_SHUTDOWN:
637 rc = -EHOSTDOWN;
638 break;
639 default:
640 list_del_init(&mid->qhead);
641 cifs_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
642 __func__, mid->mid, mid->mid_state);
643 rc = -EIO;
644 }
645 spin_unlock(&GlobalMid_Lock);
646
647 DeleteMidQEntry(mid);
648 return rc;
649}
650
651static inline int
652send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
653{
654 return server->ops->send_cancel ?
655 server->ops->send_cancel(server, buf, mid) : 0;
656}
657
658int
659cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
660 bool log_error)
661{
662 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
663
664 dump_smb(mid->resp_buf, min_t(u32, 92, len));
665
666
667 if (server->sign) {
668 struct kvec iov;
669 int rc = 0;
670 struct smb_rqst rqst = { .rq_iov = &iov,
671 .rq_nvec = 1 };
672
673 iov.iov_base = mid->resp_buf;
674 iov.iov_len = len;
675
676 rc = cifs_verify_signature(&rqst, server,
677 mid->sequence_number);
678 if (rc)
679 cifs_dbg(VFS, "SMB signature verification returned error = %d\n",
680 rc);
681 }
682
683
684 return map_smb_to_linux_error(mid->resp_buf, log_error);
685}
686
687struct mid_q_entry *
688cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
689{
690 int rc;
691 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
692 struct mid_q_entry *mid;
693
694 rc = allocate_mid(ses, hdr, &mid);
695 if (rc)
696 return ERR_PTR(rc);
697 rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
698 if (rc) {
699 cifs_delete_mid(mid);
700 return ERR_PTR(rc);
701 }
702 return mid;
703}
704
705int
706SendReceive2(const unsigned int xid, struct cifs_ses *ses,
707 struct kvec *iov, int n_vec, int *resp_buf_type ,
708 const int flags)
709{
710 int rc = 0;
711 int timeout, optype;
712 struct mid_q_entry *midQ;
713 char *buf = iov[0].iov_base;
714 unsigned int credits = 1;
715 struct smb_rqst rqst = { .rq_iov = iov,
716 .rq_nvec = n_vec };
717
718 timeout = flags & CIFS_TIMEOUT_MASK;
719 optype = flags & CIFS_OP_MASK;
720
721 *resp_buf_type = CIFS_NO_BUFFER;
722
723 if ((ses == NULL) || (ses->server == NULL)) {
724 cifs_small_buf_release(buf);
725 cifs_dbg(VFS, "Null session\n");
726 return -EIO;
727 }
728
729 if (ses->server->tcpStatus == CifsExiting) {
730 cifs_small_buf_release(buf);
731 return -ENOENT;
732 }
733
734
735
736
737
738
739
740 rc = wait_for_free_request(ses->server, timeout, optype);
741 if (rc) {
742 cifs_small_buf_release(buf);
743 return rc;
744 }
745
746
747
748
749
750
751
752 mutex_lock(&ses->server->srv_mutex);
753
754 midQ = ses->server->ops->setup_request(ses, &rqst);
755 if (IS_ERR(midQ)) {
756 mutex_unlock(&ses->server->srv_mutex);
757 cifs_small_buf_release(buf);
758
759 add_credits(ses->server, 1, optype);
760 return PTR_ERR(midQ);
761 }
762
763 midQ->mid_state = MID_REQUEST_SUBMITTED;
764 cifs_in_send_inc(ses->server);
765 rc = smb_sendv(ses->server, iov, n_vec);
766 cifs_in_send_dec(ses->server);
767 cifs_save_when_sent(midQ);
768
769 if (rc < 0)
770 ses->server->sequence_number -= 2;
771 mutex_unlock(&ses->server->srv_mutex);
772
773 if (rc < 0) {
774 cifs_small_buf_release(buf);
775 goto out;
776 }
777
778 if (timeout == CIFS_ASYNC_OP) {
779 cifs_small_buf_release(buf);
780 goto out;
781 }
782
783 rc = wait_for_response(ses->server, midQ);
784 if (rc != 0) {
785 send_cancel(ses->server, buf, midQ);
786 spin_lock(&GlobalMid_Lock);
787 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
788 midQ->callback = DeleteMidQEntry;
789 spin_unlock(&GlobalMid_Lock);
790 cifs_small_buf_release(buf);
791 add_credits(ses->server, 1, optype);
792 return rc;
793 }
794 spin_unlock(&GlobalMid_Lock);
795 }
796
797 cifs_small_buf_release(buf);
798
799 rc = cifs_sync_mid_result(midQ, ses->server);
800 if (rc != 0) {
801 add_credits(ses->server, 1, optype);
802 return rc;
803 }
804
805 if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
806 rc = -EIO;
807 cifs_dbg(FYI, "Bad MID state?\n");
808 goto out;
809 }
810
811 buf = (char *)midQ->resp_buf;
812 iov[0].iov_base = buf;
813 iov[0].iov_len = get_rfc1002_length(buf) + 4;
814 if (midQ->large_buf)
815 *resp_buf_type = CIFS_LARGE_BUFFER;
816 else
817 *resp_buf_type = CIFS_SMALL_BUFFER;
818
819 credits = ses->server->ops->get_credits(midQ);
820
821 rc = ses->server->ops->check_receive(midQ, ses->server,
822 flags & CIFS_LOG_ERROR);
823
824
825 if ((flags & CIFS_NO_RESP) == 0)
826 midQ->resp_buf = NULL;
827out:
828 cifs_delete_mid(midQ);
829 add_credits(ses->server, credits, optype);
830
831 return rc;
832}
833
834int
835SendReceive(const unsigned int xid, struct cifs_ses *ses,
836 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
837 int *pbytes_returned, const int timeout)
838{
839 int rc = 0;
840 struct mid_q_entry *midQ;
841
842 if (ses == NULL) {
843 cifs_dbg(VFS, "Null smb session\n");
844 return -EIO;
845 }
846 if (ses->server == NULL) {
847 cifs_dbg(VFS, "Null tcp session\n");
848 return -EIO;
849 }
850
851 if (ses->server->tcpStatus == CifsExiting)
852 return -ENOENT;
853
854
855
856
857
858 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
859 MAX_CIFS_HDR_SIZE - 4) {
860 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
861 be32_to_cpu(in_buf->smb_buf_length));
862 return -EIO;
863 }
864
865 rc = wait_for_free_request(ses->server, timeout, 0);
866 if (rc)
867 return rc;
868
869
870
871
872
873 mutex_lock(&ses->server->srv_mutex);
874
875 rc = allocate_mid(ses, in_buf, &midQ);
876 if (rc) {
877 mutex_unlock(&ses->server->srv_mutex);
878
879 add_credits(ses->server, 1, 0);
880 return rc;
881 }
882
883 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
884 if (rc) {
885 mutex_unlock(&ses->server->srv_mutex);
886 goto out;
887 }
888
889 midQ->mid_state = MID_REQUEST_SUBMITTED;
890
891 cifs_in_send_inc(ses->server);
892 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
893 cifs_in_send_dec(ses->server);
894 cifs_save_when_sent(midQ);
895
896 if (rc < 0)
897 ses->server->sequence_number -= 2;
898
899 mutex_unlock(&ses->server->srv_mutex);
900
901 if (rc < 0)
902 goto out;
903
904 if (timeout == CIFS_ASYNC_OP)
905 goto out;
906
907 rc = wait_for_response(ses->server, midQ);
908 if (rc != 0) {
909 send_cancel(ses->server, in_buf, midQ);
910 spin_lock(&GlobalMid_Lock);
911 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
912
913 midQ->callback = DeleteMidQEntry;
914 spin_unlock(&GlobalMid_Lock);
915 add_credits(ses->server, 1, 0);
916 return rc;
917 }
918 spin_unlock(&GlobalMid_Lock);
919 }
920
921 rc = cifs_sync_mid_result(midQ, ses->server);
922 if (rc != 0) {
923 add_credits(ses->server, 1, 0);
924 return rc;
925 }
926
927 if (!midQ->resp_buf || !out_buf ||
928 midQ->mid_state != MID_RESPONSE_RECEIVED) {
929 rc = -EIO;
930 cifs_dbg(VFS, "Bad MID state?\n");
931 goto out;
932 }
933
934 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
935 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
936 rc = cifs_check_receive(midQ, ses->server, 0);
937out:
938 cifs_delete_mid(midQ);
939 add_credits(ses->server, 1, 0);
940
941 return rc;
942}
943
944
945
946
947static int
948send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
949 struct smb_hdr *in_buf,
950 struct smb_hdr *out_buf)
951{
952 int bytes_returned;
953 struct cifs_ses *ses = tcon->ses;
954 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
955
956
957
958
959
960
961 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
962 pSMB->Timeout = 0;
963 pSMB->hdr.Mid = get_next_mid(ses->server);
964
965 return SendReceive(xid, ses, in_buf, out_buf,
966 &bytes_returned, 0);
967}
968
969int
970SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
971 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
972 int *pbytes_returned)
973{
974 int rc = 0;
975 int rstart = 0;
976 struct mid_q_entry *midQ;
977 struct cifs_ses *ses;
978
979 if (tcon == NULL || tcon->ses == NULL) {
980 cifs_dbg(VFS, "Null smb session\n");
981 return -EIO;
982 }
983 ses = tcon->ses;
984
985 if (ses->server == NULL) {
986 cifs_dbg(VFS, "Null tcp session\n");
987 return -EIO;
988 }
989
990 if (ses->server->tcpStatus == CifsExiting)
991 return -ENOENT;
992
993
994
995
996
997 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
998 MAX_CIFS_HDR_SIZE - 4) {
999 cifs_dbg(VFS, "Illegal length, greater than maximum frame, %d\n",
1000 be32_to_cpu(in_buf->smb_buf_length));
1001 return -EIO;
1002 }
1003
1004 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
1005 if (rc)
1006 return rc;
1007
1008
1009
1010
1011
1012 mutex_lock(&ses->server->srv_mutex);
1013
1014 rc = allocate_mid(ses, in_buf, &midQ);
1015 if (rc) {
1016 mutex_unlock(&ses->server->srv_mutex);
1017 return rc;
1018 }
1019
1020 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
1021 if (rc) {
1022 cifs_delete_mid(midQ);
1023 mutex_unlock(&ses->server->srv_mutex);
1024 return rc;
1025 }
1026
1027 midQ->mid_state = MID_REQUEST_SUBMITTED;
1028 cifs_in_send_inc(ses->server);
1029 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
1030 cifs_in_send_dec(ses->server);
1031 cifs_save_when_sent(midQ);
1032
1033 if (rc < 0)
1034 ses->server->sequence_number -= 2;
1035
1036 mutex_unlock(&ses->server->srv_mutex);
1037
1038 if (rc < 0) {
1039 cifs_delete_mid(midQ);
1040 return rc;
1041 }
1042
1043
1044 rc = wait_event_interruptible(ses->server->response_q,
1045 (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
1046 ((ses->server->tcpStatus != CifsGood) &&
1047 (ses->server->tcpStatus != CifsNew)));
1048
1049
1050 if ((rc == -ERESTARTSYS) &&
1051 (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
1052 ((ses->server->tcpStatus == CifsGood) ||
1053 (ses->server->tcpStatus == CifsNew))) {
1054
1055 if (in_buf->Command == SMB_COM_TRANSACTION2) {
1056
1057
1058 rc = send_cancel(ses->server, in_buf, midQ);
1059 if (rc) {
1060 cifs_delete_mid(midQ);
1061 return rc;
1062 }
1063 } else {
1064
1065
1066
1067 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1068
1069
1070
1071 if (rc && rc != -ENOLCK) {
1072 cifs_delete_mid(midQ);
1073 return rc;
1074 }
1075 }
1076
1077 rc = wait_for_response(ses->server, midQ);
1078 if (rc) {
1079 send_cancel(ses->server, in_buf, midQ);
1080 spin_lock(&GlobalMid_Lock);
1081 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1082
1083 midQ->callback = DeleteMidQEntry;
1084 spin_unlock(&GlobalMid_Lock);
1085 return rc;
1086 }
1087 spin_unlock(&GlobalMid_Lock);
1088 }
1089
1090
1091 rstart = 1;
1092 }
1093
1094 rc = cifs_sync_mid_result(midQ, ses->server);
1095 if (rc != 0)
1096 return rc;
1097
1098
1099 if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
1100 rc = -EIO;
1101 cifs_dbg(VFS, "Bad MID state?\n");
1102 goto out;
1103 }
1104
1105 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
1106 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
1107 rc = cifs_check_receive(midQ, ses->server, 0);
1108out:
1109 cifs_delete_mid(midQ);
1110 if (rstart && rc == -EACCES)
1111 return -ERESTARTSYS;
1112 return rc;
1113}
1114