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 cERROR(1, "Null TCP session in AllocMidQEntry");
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 = smb_buffer->Mid;
62 temp->pid = current->pid;
63 temp->command = cpu_to_le16(smb_buffer->Command);
64 cFYI(1, "For smb_command %d", 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 printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu",
103 midEntry->command, midEntry->mid);
104 printk(" 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 == -ENOSPC || rc == -EAGAIN) {
183
184
185
186
187
188 WARN_ON_ONCE(rc == -ENOSPC);
189 i++;
190 if (i >= 14 || (!server->noblocksnd && (i > 2))) {
191 cERROR(1, "sends on sock %p stuck for 15 "
192 "seconds", ssocket);
193 rc = -EAGAIN;
194 break;
195 }
196 msleep(1 << i);
197 continue;
198 }
199
200 if (rc < 0)
201 break;
202
203
204 *sent += rc;
205
206 if (rc == remaining) {
207 remaining = 0;
208 break;
209 }
210
211 if (rc > remaining) {
212 cERROR(1, "sent %d requested %d", rc, remaining);
213 break;
214 }
215
216 if (rc == 0) {
217
218
219 cERROR(1, "tcp sent no data");
220 msleep(500);
221 continue;
222 }
223
224 remaining -= rc;
225
226
227 for (i = first_vec; i < n_vec; i++) {
228 if (iov[i].iov_len) {
229 if (rc > iov[i].iov_len) {
230 rc -= iov[i].iov_len;
231 iov[i].iov_len = 0;
232 } else {
233 iov[i].iov_base += rc;
234 iov[i].iov_len -= rc;
235 first_vec = i;
236 break;
237 }
238 }
239 }
240
241 i = 0;
242 rc = 0;
243 }
244 return rc;
245}
246
247
248
249
250
251
252
253
254
255
256
257void
258cifs_rqst_page_to_kvec(struct smb_rqst *rqst, unsigned int idx,
259 struct kvec *iov)
260{
261
262
263
264
265
266
267
268
269
270 iov->iov_base = kmap(rqst->rq_pages[idx]);
271
272
273 if (idx == (rqst->rq_npages - 1))
274 iov->iov_len = rqst->rq_tailsz;
275 else
276 iov->iov_len = rqst->rq_pagesz;
277}
278
279static int
280smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
281{
282 int rc;
283 struct kvec *iov = rqst->rq_iov;
284 int n_vec = rqst->rq_nvec;
285 unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
286 unsigned int i;
287 size_t total_len = 0, sent;
288 struct socket *ssocket = server->ssocket;
289 int val = 1;
290
291 if (ssocket == NULL)
292 return -ENOTSOCK;
293
294 cFYI(1, "Sending smb: smb_len=%u", smb_buf_length);
295 dump_smb(iov[0].iov_base, iov[0].iov_len);
296
297
298 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
299 (char *)&val, sizeof(val));
300
301 rc = smb_send_kvec(server, iov, n_vec, &sent);
302 if (rc < 0)
303 goto uncork;
304
305 total_len += sent;
306
307
308 for (i = 0; i < rqst->rq_npages; i++) {
309 struct kvec p_iov;
310
311 cifs_rqst_page_to_kvec(rqst, i, &p_iov);
312 rc = smb_send_kvec(server, &p_iov, 1, &sent);
313 kunmap(rqst->rq_pages[i]);
314 if (rc < 0)
315 break;
316
317 total_len += sent;
318 }
319
320uncork:
321
322 val = 0;
323 kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
324 (char *)&val, sizeof(val));
325
326 if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
327 cFYI(1, "partial send (wanted=%u sent=%zu): terminating "
328 "session", smb_buf_length + 4, total_len);
329
330
331
332
333
334 server->tcpStatus = CifsNeedReconnect;
335 }
336
337 if (rc < 0 && rc != -EINTR)
338 cERROR(1, "Error %d sending data on socket to server", rc);
339 else
340 rc = 0;
341
342 return rc;
343}
344
345static int
346smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
347{
348 struct smb_rqst rqst = { .rq_iov = iov,
349 .rq_nvec = n_vec };
350
351 return smb_send_rqst(server, &rqst);
352}
353
354int
355smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
356 unsigned int smb_buf_length)
357{
358 struct kvec iov;
359
360 iov.iov_base = smb_buffer;
361 iov.iov_len = smb_buf_length + 4;
362
363 return smb_sendv(server, &iov, 1);
364}
365
366static int
367wait_for_free_credits(struct TCP_Server_Info *server, const int timeout,
368 int *credits)
369{
370 int rc;
371
372 spin_lock(&server->req_lock);
373 if (timeout == CIFS_ASYNC_OP) {
374
375 server->in_flight++;
376 *credits -= 1;
377 spin_unlock(&server->req_lock);
378 return 0;
379 }
380
381 while (1) {
382 if (*credits <= 0) {
383 spin_unlock(&server->req_lock);
384 cifs_num_waiters_inc(server);
385 rc = wait_event_killable(server->request_q,
386 has_credits(server, credits));
387 cifs_num_waiters_dec(server);
388 if (rc)
389 return rc;
390 spin_lock(&server->req_lock);
391 } else {
392 if (server->tcpStatus == CifsExiting) {
393 spin_unlock(&server->req_lock);
394 return -ENOENT;
395 }
396
397
398
399
400
401
402
403 if (timeout != CIFS_BLOCKING_OP) {
404 *credits -= 1;
405 server->in_flight++;
406 }
407 spin_unlock(&server->req_lock);
408 break;
409 }
410 }
411 return 0;
412}
413
414static int
415wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
416 const int optype)
417{
418 return wait_for_free_credits(server, timeout,
419 server->ops->get_credits_field(server, optype));
420}
421
422static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,
423 struct mid_q_entry **ppmidQ)
424{
425 if (ses->server->tcpStatus == CifsExiting) {
426 return -ENOENT;
427 }
428
429 if (ses->server->tcpStatus == CifsNeedReconnect) {
430 cFYI(1, "tcp session dead - return to caller to retry");
431 return -EAGAIN;
432 }
433
434 if (ses->status != CifsGood) {
435
436 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) &&
437 (in_buf->Command != SMB_COM_NEGOTIATE))
438 return -EAGAIN;
439
440 }
441 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
442 if (*ppmidQ == NULL)
443 return -ENOMEM;
444 spin_lock(&GlobalMid_Lock);
445 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
446 spin_unlock(&GlobalMid_Lock);
447 return 0;
448}
449
450static int
451wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
452{
453 int error;
454
455 error = wait_event_freezekillable(server->response_q,
456 midQ->mid_state != MID_REQUEST_SUBMITTED);
457 if (error < 0)
458 return -ERESTARTSYS;
459
460 return 0;
461}
462
463struct mid_q_entry *
464cifs_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
465{
466 int rc;
467 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
468 struct mid_q_entry *mid;
469
470
471 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
472 hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
473
474 mid = AllocMidQEntry(hdr, server);
475 if (mid == NULL)
476 return ERR_PTR(-ENOMEM);
477
478 rc = cifs_sign_rqst(rqst, server, &mid->sequence_number);
479 if (rc) {
480 DeleteMidQEntry(mid);
481 return ERR_PTR(rc);
482 }
483
484 return mid;
485}
486
487
488
489
490
491int
492cifs_call_async(struct TCP_Server_Info *server, struct smb_rqst *rqst,
493 mid_receive_t *receive, mid_callback_t *callback,
494 void *cbdata, const int flags)
495{
496 int rc, timeout, optype;
497 struct mid_q_entry *mid;
498
499 timeout = flags & CIFS_TIMEOUT_MASK;
500 optype = flags & CIFS_OP_MASK;
501
502 rc = wait_for_free_request(server, timeout, optype);
503 if (rc)
504 return rc;
505
506 mutex_lock(&server->srv_mutex);
507 mid = server->ops->setup_async_request(server, rqst);
508 if (IS_ERR(mid)) {
509 mutex_unlock(&server->srv_mutex);
510 add_credits(server, 1, optype);
511 wake_up(&server->request_q);
512 return PTR_ERR(mid);
513 }
514
515 mid->receive = receive;
516 mid->callback = callback;
517 mid->callback_data = cbdata;
518 mid->mid_state = MID_REQUEST_SUBMITTED;
519
520
521 spin_lock(&GlobalMid_Lock);
522 list_add_tail(&mid->qhead, &server->pending_mid_q);
523 spin_unlock(&GlobalMid_Lock);
524
525
526 cifs_in_send_inc(server);
527 rc = smb_send_rqst(server, rqst);
528 cifs_in_send_dec(server);
529 cifs_save_when_sent(mid);
530 mutex_unlock(&server->srv_mutex);
531
532 if (rc == 0)
533 return 0;
534
535 cifs_delete_mid(mid);
536 add_credits(server, 1, optype);
537 wake_up(&server->request_q);
538 return rc;
539}
540
541
542
543
544
545
546
547
548
549
550int
551SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
552 char *in_buf, int flags)
553{
554 int rc;
555 struct kvec iov[1];
556 int resp_buf_type;
557
558 iov[0].iov_base = in_buf;
559 iov[0].iov_len = get_rfc1002_length(in_buf) + 4;
560 flags |= CIFS_NO_RESP;
561 rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags);
562 cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc);
563
564 return rc;
565}
566
567static int
568cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
569{
570 int rc = 0;
571
572 cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__,
573 le16_to_cpu(mid->command), mid->mid, mid->mid_state);
574
575 spin_lock(&GlobalMid_Lock);
576 switch (mid->mid_state) {
577 case MID_RESPONSE_RECEIVED:
578 spin_unlock(&GlobalMid_Lock);
579 return rc;
580 case MID_RETRY_NEEDED:
581 rc = -EAGAIN;
582 break;
583 case MID_RESPONSE_MALFORMED:
584 rc = -EIO;
585 break;
586 case MID_SHUTDOWN:
587 rc = -EHOSTDOWN;
588 break;
589 default:
590 list_del_init(&mid->qhead);
591 cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__,
592 mid->mid, mid->mid_state);
593 rc = -EIO;
594 }
595 spin_unlock(&GlobalMid_Lock);
596
597 DeleteMidQEntry(mid);
598 return rc;
599}
600
601static inline int
602send_cancel(struct TCP_Server_Info *server, void *buf, struct mid_q_entry *mid)
603{
604 return server->ops->send_cancel ?
605 server->ops->send_cancel(server, buf, mid) : 0;
606}
607
608int
609cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
610 bool log_error)
611{
612 unsigned int len = get_rfc1002_length(mid->resp_buf) + 4;
613
614 dump_smb(mid->resp_buf, min_t(u32, 92, len));
615
616
617 if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
618 struct kvec iov;
619 int rc = 0;
620 struct smb_rqst rqst = { .rq_iov = &iov,
621 .rq_nvec = 1 };
622
623 iov.iov_base = mid->resp_buf;
624 iov.iov_len = len;
625
626 rc = cifs_verify_signature(&rqst, server,
627 mid->sequence_number + 1);
628 if (rc)
629 cERROR(1, "SMB signature verification returned error = "
630 "%d", rc);
631 }
632
633
634 return map_smb_to_linux_error(mid->resp_buf, log_error);
635}
636
637struct mid_q_entry *
638cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
639{
640 int rc;
641 struct smb_hdr *hdr = (struct smb_hdr *)rqst->rq_iov[0].iov_base;
642 struct mid_q_entry *mid;
643
644 rc = allocate_mid(ses, hdr, &mid);
645 if (rc)
646 return ERR_PTR(rc);
647 rc = cifs_sign_rqst(rqst, ses->server, &mid->sequence_number);
648 if (rc) {
649 cifs_delete_mid(mid);
650 return ERR_PTR(rc);
651 }
652 return mid;
653}
654
655int
656SendReceive2(const unsigned int xid, struct cifs_ses *ses,
657 struct kvec *iov, int n_vec, int *resp_buf_type ,
658 const int flags)
659{
660 int rc = 0;
661 int timeout, optype;
662 struct mid_q_entry *midQ;
663 char *buf = iov[0].iov_base;
664 unsigned int credits = 1;
665 struct smb_rqst rqst = { .rq_iov = iov,
666 .rq_nvec = n_vec };
667
668 timeout = flags & CIFS_TIMEOUT_MASK;
669 optype = flags & CIFS_OP_MASK;
670
671 *resp_buf_type = CIFS_NO_BUFFER;
672
673 if ((ses == NULL) || (ses->server == NULL)) {
674 cifs_small_buf_release(buf);
675 cERROR(1, "Null session");
676 return -EIO;
677 }
678
679 if (ses->server->tcpStatus == CifsExiting) {
680 cifs_small_buf_release(buf);
681 return -ENOENT;
682 }
683
684
685
686
687
688
689
690 rc = wait_for_free_request(ses->server, timeout, optype);
691 if (rc) {
692 cifs_small_buf_release(buf);
693 return rc;
694 }
695
696
697
698
699
700
701
702 mutex_lock(&ses->server->srv_mutex);
703
704 midQ = ses->server->ops->setup_request(ses, &rqst);
705 if (IS_ERR(midQ)) {
706 mutex_unlock(&ses->server->srv_mutex);
707 cifs_small_buf_release(buf);
708
709 add_credits(ses->server, 1, optype);
710 return PTR_ERR(midQ);
711 }
712
713 midQ->mid_state = MID_REQUEST_SUBMITTED;
714 cifs_in_send_inc(ses->server);
715 rc = smb_sendv(ses->server, iov, n_vec);
716 cifs_in_send_dec(ses->server);
717 cifs_save_when_sent(midQ);
718
719 mutex_unlock(&ses->server->srv_mutex);
720
721 if (rc < 0) {
722 cifs_small_buf_release(buf);
723 goto out;
724 }
725
726 if (timeout == CIFS_ASYNC_OP) {
727 cifs_small_buf_release(buf);
728 goto out;
729 }
730
731 rc = wait_for_response(ses->server, midQ);
732 if (rc != 0) {
733 send_cancel(ses->server, buf, midQ);
734 spin_lock(&GlobalMid_Lock);
735 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
736 midQ->callback = DeleteMidQEntry;
737 spin_unlock(&GlobalMid_Lock);
738 cifs_small_buf_release(buf);
739 add_credits(ses->server, 1, optype);
740 return rc;
741 }
742 spin_unlock(&GlobalMid_Lock);
743 }
744
745 cifs_small_buf_release(buf);
746
747 rc = cifs_sync_mid_result(midQ, ses->server);
748 if (rc != 0) {
749 add_credits(ses->server, 1, optype);
750 return rc;
751 }
752
753 if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) {
754 rc = -EIO;
755 cFYI(1, "Bad MID state?");
756 goto out;
757 }
758
759 buf = (char *)midQ->resp_buf;
760 iov[0].iov_base = buf;
761 iov[0].iov_len = get_rfc1002_length(buf) + 4;
762 if (midQ->large_buf)
763 *resp_buf_type = CIFS_LARGE_BUFFER;
764 else
765 *resp_buf_type = CIFS_SMALL_BUFFER;
766
767 credits = ses->server->ops->get_credits(midQ);
768
769 rc = ses->server->ops->check_receive(midQ, ses->server,
770 flags & CIFS_LOG_ERROR);
771
772
773 if ((flags & CIFS_NO_RESP) == 0)
774 midQ->resp_buf = NULL;
775out:
776 cifs_delete_mid(midQ);
777 add_credits(ses->server, credits, optype);
778
779 return rc;
780}
781
782int
783SendReceive(const unsigned int xid, struct cifs_ses *ses,
784 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
785 int *pbytes_returned, const int timeout)
786{
787 int rc = 0;
788 struct mid_q_entry *midQ;
789
790 if (ses == NULL) {
791 cERROR(1, "Null smb session");
792 return -EIO;
793 }
794 if (ses->server == NULL) {
795 cERROR(1, "Null tcp session");
796 return -EIO;
797 }
798
799 if (ses->server->tcpStatus == CifsExiting)
800 return -ENOENT;
801
802
803
804
805
806 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
807 MAX_CIFS_HDR_SIZE - 4) {
808 cERROR(1, "Illegal length, greater than maximum frame, %d",
809 be32_to_cpu(in_buf->smb_buf_length));
810 return -EIO;
811 }
812
813 rc = wait_for_free_request(ses->server, timeout, 0);
814 if (rc)
815 return rc;
816
817
818
819
820
821 mutex_lock(&ses->server->srv_mutex);
822
823 rc = allocate_mid(ses, in_buf, &midQ);
824 if (rc) {
825 mutex_unlock(&ses->server->srv_mutex);
826
827 add_credits(ses->server, 1, 0);
828 return rc;
829 }
830
831 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
832 if (rc) {
833 mutex_unlock(&ses->server->srv_mutex);
834 goto out;
835 }
836
837 midQ->mid_state = MID_REQUEST_SUBMITTED;
838
839 cifs_in_send_inc(ses->server);
840 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
841 cifs_in_send_dec(ses->server);
842 cifs_save_when_sent(midQ);
843 mutex_unlock(&ses->server->srv_mutex);
844
845 if (rc < 0)
846 goto out;
847
848 if (timeout == CIFS_ASYNC_OP)
849 goto out;
850
851 rc = wait_for_response(ses->server, midQ);
852 if (rc != 0) {
853 send_cancel(ses->server, in_buf, midQ);
854 spin_lock(&GlobalMid_Lock);
855 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
856
857 midQ->callback = DeleteMidQEntry;
858 spin_unlock(&GlobalMid_Lock);
859 add_credits(ses->server, 1, 0);
860 return rc;
861 }
862 spin_unlock(&GlobalMid_Lock);
863 }
864
865 rc = cifs_sync_mid_result(midQ, ses->server);
866 if (rc != 0) {
867 add_credits(ses->server, 1, 0);
868 return rc;
869 }
870
871 if (!midQ->resp_buf || !out_buf ||
872 midQ->mid_state != MID_RESPONSE_RECEIVED) {
873 rc = -EIO;
874 cERROR(1, "Bad MID state?");
875 goto out;
876 }
877
878 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
879 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
880 rc = cifs_check_receive(midQ, ses->server, 0);
881out:
882 cifs_delete_mid(midQ);
883 add_credits(ses->server, 1, 0);
884
885 return rc;
886}
887
888
889
890
891static int
892send_lock_cancel(const unsigned int xid, struct cifs_tcon *tcon,
893 struct smb_hdr *in_buf,
894 struct smb_hdr *out_buf)
895{
896 int bytes_returned;
897 struct cifs_ses *ses = tcon->ses;
898 LOCK_REQ *pSMB = (LOCK_REQ *)in_buf;
899
900
901
902
903
904
905 pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES;
906 pSMB->Timeout = 0;
907 pSMB->hdr.Mid = get_next_mid(ses->server);
908
909 return SendReceive(xid, ses, in_buf, out_buf,
910 &bytes_returned, 0);
911}
912
913int
914SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
915 struct smb_hdr *in_buf, struct smb_hdr *out_buf,
916 int *pbytes_returned)
917{
918 int rc = 0;
919 int rstart = 0;
920 struct mid_q_entry *midQ;
921 struct cifs_ses *ses;
922
923 if (tcon == NULL || tcon->ses == NULL) {
924 cERROR(1, "Null smb session");
925 return -EIO;
926 }
927 ses = tcon->ses;
928
929 if (ses->server == NULL) {
930 cERROR(1, "Null tcp session");
931 return -EIO;
932 }
933
934 if (ses->server->tcpStatus == CifsExiting)
935 return -ENOENT;
936
937
938
939
940
941 if (be32_to_cpu(in_buf->smb_buf_length) > CIFSMaxBufSize +
942 MAX_CIFS_HDR_SIZE - 4) {
943 cERROR(1, "Illegal length, greater than maximum frame, %d",
944 be32_to_cpu(in_buf->smb_buf_length));
945 return -EIO;
946 }
947
948 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0);
949 if (rc)
950 return rc;
951
952
953
954
955
956 mutex_lock(&ses->server->srv_mutex);
957
958 rc = allocate_mid(ses, in_buf, &midQ);
959 if (rc) {
960 mutex_unlock(&ses->server->srv_mutex);
961 return rc;
962 }
963
964 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
965 if (rc) {
966 cifs_delete_mid(midQ);
967 mutex_unlock(&ses->server->srv_mutex);
968 return rc;
969 }
970
971 midQ->mid_state = MID_REQUEST_SUBMITTED;
972 cifs_in_send_inc(ses->server);
973 rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length));
974 cifs_in_send_dec(ses->server);
975 cifs_save_when_sent(midQ);
976 mutex_unlock(&ses->server->srv_mutex);
977
978 if (rc < 0) {
979 cifs_delete_mid(midQ);
980 return rc;
981 }
982
983
984 rc = wait_event_interruptible(ses->server->response_q,
985 (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) ||
986 ((ses->server->tcpStatus != CifsGood) &&
987 (ses->server->tcpStatus != CifsNew)));
988
989
990 if ((rc == -ERESTARTSYS) &&
991 (midQ->mid_state == MID_REQUEST_SUBMITTED) &&
992 ((ses->server->tcpStatus == CifsGood) ||
993 (ses->server->tcpStatus == CifsNew))) {
994
995 if (in_buf->Command == SMB_COM_TRANSACTION2) {
996
997
998 rc = send_cancel(ses->server, in_buf, midQ);
999 if (rc) {
1000 cifs_delete_mid(midQ);
1001 return rc;
1002 }
1003 } else {
1004
1005
1006
1007 rc = send_lock_cancel(xid, tcon, in_buf, out_buf);
1008
1009
1010
1011 if (rc && rc != -ENOLCK) {
1012 cifs_delete_mid(midQ);
1013 return rc;
1014 }
1015 }
1016
1017 rc = wait_for_response(ses->server, midQ);
1018 if (rc) {
1019 send_cancel(ses->server, in_buf, midQ);
1020 spin_lock(&GlobalMid_Lock);
1021 if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
1022
1023 midQ->callback = DeleteMidQEntry;
1024 spin_unlock(&GlobalMid_Lock);
1025 return rc;
1026 }
1027 spin_unlock(&GlobalMid_Lock);
1028 }
1029
1030
1031 rstart = 1;
1032 }
1033
1034 rc = cifs_sync_mid_result(midQ, ses->server);
1035 if (rc != 0)
1036 return rc;
1037
1038
1039 if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) {
1040 rc = -EIO;
1041 cERROR(1, "Bad MID state?");
1042 goto out;
1043 }
1044
1045 *pbytes_returned = get_rfc1002_length(midQ->resp_buf);
1046 memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
1047 rc = cifs_check_receive(midQ, ses->server, 0);
1048out:
1049 cifs_delete_mid(midQ);
1050 if (rstart && rc == -EACCES)
1051 return -ERESTARTSYS;
1052 return rc;
1053}
1054