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