aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c434
1 files changed, 206 insertions, 228 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 59ca81b16919..c1ccca1a933f 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -36,7 +36,13 @@
36 36
37extern mempool_t *cifs_mid_poolp; 37extern mempool_t *cifs_mid_poolp;
38 38
39static struct mid_q_entry * 39static void
40wake_up_task(struct mid_q_entry *mid)
41{
42 wake_up_process(mid->callback_data);
43}
44
45struct mid_q_entry *
40AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) 46AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
41{ 47{
42 struct mid_q_entry *temp; 48 struct mid_q_entry *temp;
@@ -58,28 +64,28 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server)
58 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ 64 /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */
59 /* when mid allocated can be before when sent */ 65 /* when mid allocated can be before when sent */
60 temp->when_alloc = jiffies; 66 temp->when_alloc = jiffies;
61 temp->tsk = current; 67
68 /*
69 * The default is for the mid to be synchronous, so the
70 * default callback just wakes up the current task.
71 */
72 temp->callback = wake_up_task;
73 temp->callback_data = current;
62 } 74 }
63 75
64 spin_lock(&GlobalMid_Lock);
65 list_add_tail(&temp->qhead, &server->pending_mid_q);
66 atomic_inc(&midCount); 76 atomic_inc(&midCount);
67 temp->midState = MID_REQUEST_ALLOCATED; 77 temp->midState = MID_REQUEST_ALLOCATED;
68 spin_unlock(&GlobalMid_Lock);
69 return temp; 78 return temp;
70} 79}
71 80
72static void 81void
73DeleteMidQEntry(struct mid_q_entry *midEntry) 82DeleteMidQEntry(struct mid_q_entry *midEntry)
74{ 83{
75#ifdef CONFIG_CIFS_STATS2 84#ifdef CONFIG_CIFS_STATS2
76 unsigned long now; 85 unsigned long now;
77#endif 86#endif
78 spin_lock(&GlobalMid_Lock);
79 midEntry->midState = MID_FREE; 87 midEntry->midState = MID_FREE;
80 list_del(&midEntry->qhead);
81 atomic_dec(&midCount); 88 atomic_dec(&midCount);
82 spin_unlock(&GlobalMid_Lock);
83 if (midEntry->largeBuf) 89 if (midEntry->largeBuf)
84 cifs_buf_release(midEntry->resp_buf); 90 cifs_buf_release(midEntry->resp_buf);
85 else 91 else
@@ -103,6 +109,16 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
103 mempool_free(midEntry, cifs_mid_poolp); 109 mempool_free(midEntry, cifs_mid_poolp);
104} 110}
105 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
106static int 122static int
107smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) 123smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec)
108{ 124{
@@ -244,31 +260,31 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
244 return smb_sendv(server, &iov, 1); 260 return smb_sendv(server, &iov, 1);
245} 261}
246 262
247static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) 263static int wait_for_free_request(struct TCP_Server_Info *server,
264 const int long_op)
248{ 265{
249 if (long_op == CIFS_ASYNC_OP) { 266 if (long_op == CIFS_ASYNC_OP) {
250 /* oplock breaks must not be held up */ 267 /* oplock breaks must not be held up */
251 atomic_inc(&ses->server->inFlight); 268 atomic_inc(&server->inFlight);
252 return 0; 269 return 0;
253 } 270 }
254 271
255 spin_lock(&GlobalMid_Lock); 272 spin_lock(&GlobalMid_Lock);
256 while (1) { 273 while (1) {
257 if (atomic_read(&ses->server->inFlight) >= 274 if (atomic_read(&server->inFlight) >= cifs_max_pending) {
258 cifs_max_pending){
259 spin_unlock(&GlobalMid_Lock); 275 spin_unlock(&GlobalMid_Lock);
260#ifdef CONFIG_CIFS_STATS2 276#ifdef CONFIG_CIFS_STATS2
261 atomic_inc(&ses->server->num_waiters); 277 atomic_inc(&server->num_waiters);
262#endif 278#endif
263 wait_event(ses->server->request_q, 279 wait_event(server->request_q,
264 atomic_read(&ses->server->inFlight) 280 atomic_read(&server->inFlight)
265 < cifs_max_pending); 281 < cifs_max_pending);
266#ifdef CONFIG_CIFS_STATS2 282#ifdef CONFIG_CIFS_STATS2
267 atomic_dec(&ses->server->num_waiters); 283 atomic_dec(&server->num_waiters);
268#endif 284#endif
269 spin_lock(&GlobalMid_Lock); 285 spin_lock(&GlobalMid_Lock);
270 } else { 286 } else {
271 if (ses->server->tcpStatus == CifsExiting) { 287 if (server->tcpStatus == CifsExiting) {
272 spin_unlock(&GlobalMid_Lock); 288 spin_unlock(&GlobalMid_Lock);
273 return -ENOENT; 289 return -ENOENT;
274 } 290 }
@@ -278,7 +294,7 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op)
278 294
279 /* update # of requests on the wire to server */ 295 /* update # of requests on the wire to server */
280 if (long_op != CIFS_BLOCKING_OP) 296 if (long_op != CIFS_BLOCKING_OP)
281 atomic_inc(&ses->server->inFlight); 297 atomic_inc(&server->inFlight);
282 spin_unlock(&GlobalMid_Lock); 298 spin_unlock(&GlobalMid_Lock);
283 break; 299 break;
284 } 300 }
@@ -308,53 +324,81 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf,
308 *ppmidQ = AllocMidQEntry(in_buf, ses->server); 324 *ppmidQ = AllocMidQEntry(in_buf, ses->server);
309 if (*ppmidQ == NULL) 325 if (*ppmidQ == NULL)
310 return -ENOMEM; 326 return -ENOMEM;
327 spin_lock(&GlobalMid_Lock);
328 list_add_tail(&(*ppmidQ)->qhead, &ses->server->pending_mid_q);
329 spin_unlock(&GlobalMid_Lock);
311 return 0; 330 return 0;
312} 331}
313 332
314static int wait_for_response(struct cifsSesInfo *ses, 333static int
315 struct mid_q_entry *midQ, 334wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
316 unsigned long timeout,
317 unsigned long time_to_wait)
318{ 335{
319 unsigned long curr_timeout; 336 int error;
320 337
321 for (;;) { 338 error = wait_event_killable(server->response_q,
322 curr_timeout = timeout + jiffies; 339 midQ->midState != MID_REQUEST_SUBMITTED);
323 wait_event_timeout(ses->server->response_q, 340 if (error < 0)
324 midQ->midState != MID_REQUEST_SUBMITTED, timeout); 341 return -ERESTARTSYS;
325 342
326 if (time_after(jiffies, curr_timeout) && 343 return 0;
327 (midQ->midState == MID_REQUEST_SUBMITTED) && 344}
328 ((ses->server->tcpStatus == CifsGood) ||
329 (ses->server->tcpStatus == CifsNew))) {
330 345
331 unsigned long lrt;
332 346
333 /* We timed out. Is the server still 347/*
334 sending replies ? */ 348 * Send a SMB request and set the callback function in the mid to handle
335 spin_lock(&GlobalMid_Lock); 349 * the result. Caller is responsible for dealing with timeouts.
336 lrt = ses->server->lstrp; 350 */
337 spin_unlock(&GlobalMid_Lock); 351int
352cifs_call_async(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
353 mid_callback_t *callback, void *cbdata)
354{
355 int rc;
356 struct mid_q_entry *mid;
338 357
339 /* Calculate time_to_wait past last receive time. 358 rc = wait_for_free_request(server, CIFS_ASYNC_OP);
340 Although we prefer not to time out if the 359 if (rc)
341 server is still responding - we will time 360 return rc;
342 out if the server takes more than 15 (or 45 361
343 or 180) seconds to respond to this request 362 mutex_lock(&server->srv_mutex);
344 and has not responded to any request from 363 mid = AllocMidQEntry(in_buf, server);
345 other threads on the client within 10 seconds */ 364 if (mid == NULL) {
346 lrt += time_to_wait; 365 mutex_unlock(&server->srv_mutex);
347 if (time_after(jiffies, lrt)) { 366 return -ENOMEM;
348 /* No replies for time_to_wait. */
349 cERROR(1, "server not responding");
350 return -1;
351 }
352 } else {
353 return 0;
354 }
355 } 367 }
356}
357 368
369 /* put it on the pending_mid_q */
370 spin_lock(&GlobalMid_Lock);
371 list_add_tail(&mid->qhead, &server->pending_mid_q);
372 spin_unlock(&GlobalMid_Lock);
373
374 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
375 if (rc) {
376 mutex_unlock(&server->srv_mutex);
377 goto out_err;
378 }
379
380 mid->callback = callback;
381 mid->callback_data = cbdata;
382 mid->midState = MID_REQUEST_SUBMITTED;
383#ifdef CONFIG_CIFS_STATS2
384 atomic_inc(&server->inSend);
385#endif
386 rc = smb_send(server, in_buf, in_buf->smb_buf_length);
387#ifdef CONFIG_CIFS_STATS2
388 atomic_dec(&server->inSend);
389 mid->when_sent = jiffies;
390#endif
391 mutex_unlock(&server->srv_mutex);
392 if (rc)
393 goto out_err;
394
395 return rc;
396out_err:
397 delete_mid(mid);
398 atomic_dec(&server->inFlight);
399 wake_up(&server->request_q);
400 return rc;
401}
358 402
359/* 403/*
360 * 404 *
@@ -382,6 +426,81 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses,
382 return rc; 426 return rc;
383} 427}
384 428
429static int
430sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
431{
432 int rc = 0;
433
434 cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command,
435 mid->mid, mid->midState);
436
437 spin_lock(&GlobalMid_Lock);
438 /* ensure that it's no longer on the pending_mid_q */
439 list_del_init(&mid->qhead);
440
441 switch (mid->midState) {
442 case MID_RESPONSE_RECEIVED:
443 spin_unlock(&GlobalMid_Lock);
444 return rc;
445 case MID_REQUEST_SUBMITTED:
446 /* socket is going down, reject all calls */
447 if (server->tcpStatus == CifsExiting) {
448 cERROR(1, "%s: canceling mid=%d cmd=0x%x state=%d",
449 __func__, mid->mid, mid->command, mid->midState);
450 rc = -EHOSTDOWN;
451 break;
452 }
453 case MID_RETRY_NEEDED:
454 rc = -EAGAIN;
455 break;
456 default:
457 cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__,
458 mid->mid, mid->midState);
459 rc = -EIO;
460 }
461 spin_unlock(&GlobalMid_Lock);
462
463 DeleteMidQEntry(mid);
464 return rc;
465}
466
467/*
468 * An NT cancel request header looks just like the original request except:
469 *
470 * The Command is SMB_COM_NT_CANCEL
471 * The WordCount is zeroed out
472 * The ByteCount is zeroed out
473 *
474 * This function mangles an existing request buffer into a
475 * SMB_COM_NT_CANCEL request and then sends it.
476 */
477static int
478send_nt_cancel(struct TCP_Server_Info *server, struct smb_hdr *in_buf,
479 struct mid_q_entry *mid)
480{
481 int rc = 0;
482
483 /* -4 for RFC1001 length and +2 for BCC field */
484 in_buf->smb_buf_length = sizeof(struct smb_hdr) - 4 + 2;
485 in_buf->Command = SMB_COM_NT_CANCEL;
486 in_buf->WordCount = 0;
487 put_bcc_le(0, in_buf);
488
489 mutex_lock(&server->srv_mutex);
490 rc = cifs_sign_smb(in_buf, server, &mid->sequence_number);
491 if (rc) {
492 mutex_unlock(&server->srv_mutex);
493 return rc;
494 }
495 rc = smb_send(server, in_buf, in_buf->smb_buf_length);
496 mutex_unlock(&server->srv_mutex);
497
498 cFYI(1, "issued NT_CANCEL for mid %u, rc = %d",
499 in_buf->Mid, rc);
500
501 return rc;
502}
503
385int 504int
386SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, 505SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
387 struct kvec *iov, int n_vec, int *pRespBufType /* ret */, 506 struct kvec *iov, int n_vec, int *pRespBufType /* ret */,
@@ -390,7 +509,6 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
390 int rc = 0; 509 int rc = 0;
391 int long_op; 510 int long_op;
392 unsigned int receive_len; 511 unsigned int receive_len;
393 unsigned long timeout;
394 struct mid_q_entry *midQ; 512 struct mid_q_entry *midQ;
395 struct smb_hdr *in_buf = iov[0].iov_base; 513 struct smb_hdr *in_buf = iov[0].iov_base;
396 514
@@ -413,7 +531,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
413 to the same server. We may make this configurable later or 531 to the same server. We may make this configurable later or
414 use ses->maxReq */ 532 use ses->maxReq */
415 533
416 rc = wait_for_free_request(ses, long_op); 534 rc = wait_for_free_request(ses->server, long_op);
417 if (rc) { 535 if (rc) {
418 cifs_small_buf_release(in_buf); 536 cifs_small_buf_release(in_buf);
419 return rc; 537 return rc;
@@ -457,65 +575,20 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
457 if (rc < 0) 575 if (rc < 0)
458 goto out; 576 goto out;
459 577
460 if (long_op == CIFS_STD_OP) 578 if (long_op == CIFS_ASYNC_OP)
461 timeout = 15 * HZ;
462 else if (long_op == CIFS_VLONG_OP) /* e.g. slow writes past EOF */
463 timeout = 180 * HZ;
464 else if (long_op == CIFS_LONG_OP)
465 timeout = 45 * HZ; /* should be greater than
466 servers oplock break timeout (about 43 seconds) */
467 else if (long_op == CIFS_ASYNC_OP)
468 goto out; 579 goto out;
469 else if (long_op == CIFS_BLOCKING_OP)
470 timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */
471 else {
472 cERROR(1, "unknown timeout flag %d", long_op);
473 rc = -EIO;
474 goto out;
475 }
476
477 /* wait for 15 seconds or until woken up due to response arriving or
478 due to last connection to this server being unmounted */
479 if (signal_pending(current)) {
480 /* if signal pending do not hold up user for full smb timeout
481 but we still give response a chance to complete */
482 timeout = 2 * HZ;
483 }
484
485 /* No user interrupts in wait - wreaks havoc with performance */
486 wait_for_response(ses, midQ, timeout, 10 * HZ);
487
488 spin_lock(&GlobalMid_Lock);
489 580
490 if (midQ->resp_buf == NULL) { 581 rc = wait_for_response(ses->server, midQ);
491 cERROR(1, "No response to cmd %d mid %d", 582 if (rc != 0)
492 midQ->command, midQ->mid); 583 goto out;
493 if (midQ->midState == MID_REQUEST_SUBMITTED) {
494 if (ses->server->tcpStatus == CifsExiting)
495 rc = -EHOSTDOWN;
496 else {
497 ses->server->tcpStatus = CifsNeedReconnect;
498 midQ->midState = MID_RETRY_NEEDED;
499 }
500 }
501 584
502 if (rc != -EHOSTDOWN) { 585 rc = sync_mid_result(midQ, ses->server);
503 if (midQ->midState == MID_RETRY_NEEDED) { 586 if (rc != 0) {
504 rc = -EAGAIN;
505 cFYI(1, "marking request for retry");
506 } else {
507 rc = -EIO;
508 }
509 }
510 spin_unlock(&GlobalMid_Lock);
511 DeleteMidQEntry(midQ);
512 /* Update # of requests on wire to server */
513 atomic_dec(&ses->server->inFlight); 587 atomic_dec(&ses->server->inFlight);
514 wake_up(&ses->server->request_q); 588 wake_up(&ses->server->request_q);
515 return rc; 589 return rc;
516 } 590 }
517 591
518 spin_unlock(&GlobalMid_Lock);
519 receive_len = midQ->resp_buf->smb_buf_length; 592 receive_len = midQ->resp_buf->smb_buf_length;
520 593
521 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 594 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
@@ -559,19 +632,18 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
559 if (receive_len >= sizeof(struct smb_hdr) - 4 632 if (receive_len >= sizeof(struct smb_hdr) - 4
560 /* do not count RFC1001 header */ + 633 /* do not count RFC1001 header */ +
561 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ ) 634 (2 * midQ->resp_buf->WordCount) + 2 /* bcc */ )
562 BCC(midQ->resp_buf) = 635 put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf);
563 le16_to_cpu(BCC_LE(midQ->resp_buf));
564 if ((flags & CIFS_NO_RESP) == 0) 636 if ((flags & CIFS_NO_RESP) == 0)
565 midQ->resp_buf = NULL; /* mark it so buf will 637 midQ->resp_buf = NULL; /* mark it so buf will
566 not be freed by 638 not be freed by
567 DeleteMidQEntry */ 639 delete_mid */
568 } else { 640 } else {
569 rc = -EIO; 641 rc = -EIO;
570 cFYI(1, "Bad MID state?"); 642 cFYI(1, "Bad MID state?");
571 } 643 }
572 644
573out: 645out:
574 DeleteMidQEntry(midQ); 646 delete_mid(midQ);
575 atomic_dec(&ses->server->inFlight); 647 atomic_dec(&ses->server->inFlight);
576 wake_up(&ses->server->request_q); 648 wake_up(&ses->server->request_q);
577 649
@@ -585,7 +657,6 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
585{ 657{
586 int rc = 0; 658 int rc = 0;
587 unsigned int receive_len; 659 unsigned int receive_len;
588 unsigned long timeout;
589 struct mid_q_entry *midQ; 660 struct mid_q_entry *midQ;
590 661
591 if (ses == NULL) { 662 if (ses == NULL) {
@@ -610,7 +681,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
610 return -EIO; 681 return -EIO;
611 } 682 }
612 683
613 rc = wait_for_free_request(ses, long_op); 684 rc = wait_for_free_request(ses->server, long_op);
614 if (rc) 685 if (rc)
615 return rc; 686 return rc;
616 687
@@ -649,64 +720,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
649 if (rc < 0) 720 if (rc < 0)
650 goto out; 721 goto out;
651 722
652 if (long_op == CIFS_STD_OP) 723 if (long_op == CIFS_ASYNC_OP)
653 timeout = 15 * HZ;
654 /* wait for 15 seconds or until woken up due to response arriving or
655 due to last connection to this server being unmounted */
656 else if (long_op == CIFS_ASYNC_OP)
657 goto out; 724 goto out;
658 else if (long_op == CIFS_VLONG_OP) /* writes past EOF can be slow */
659 timeout = 180 * HZ;
660 else if (long_op == CIFS_LONG_OP)
661 timeout = 45 * HZ; /* should be greater than
662 servers oplock break timeout (about 43 seconds) */
663 else if (long_op == CIFS_BLOCKING_OP)
664 timeout = 0x7FFFFFFF; /* large but no so large as to wrap */
665 else {
666 cERROR(1, "unknown timeout flag %d", long_op);
667 rc = -EIO;
668 goto out;
669 }
670 725
671 if (signal_pending(current)) { 726 rc = wait_for_response(ses->server, midQ);
672 /* if signal pending do not hold up user for full smb timeout 727 if (rc != 0)
673 but we still give response a chance to complete */ 728 goto out;
674 timeout = 2 * HZ;
675 }
676
677 /* No user interrupts in wait - wreaks havoc with performance */
678 wait_for_response(ses, midQ, timeout, 10 * HZ);
679
680 spin_lock(&GlobalMid_Lock);
681 if (midQ->resp_buf == NULL) {
682 cERROR(1, "No response for cmd %d mid %d",
683 midQ->command, midQ->mid);
684 if (midQ->midState == MID_REQUEST_SUBMITTED) {
685 if (ses->server->tcpStatus == CifsExiting)
686 rc = -EHOSTDOWN;
687 else {
688 ses->server->tcpStatus = CifsNeedReconnect;
689 midQ->midState = MID_RETRY_NEEDED;
690 }
691 }
692 729
693 if (rc != -EHOSTDOWN) { 730 rc = sync_mid_result(midQ, ses->server);
694 if (midQ->midState == MID_RETRY_NEEDED) { 731 if (rc != 0) {
695 rc = -EAGAIN;
696 cFYI(1, "marking request for retry");
697 } else {
698 rc = -EIO;
699 }
700 }
701 spin_unlock(&GlobalMid_Lock);
702 DeleteMidQEntry(midQ);
703 /* Update # of requests on wire to server */
704 atomic_dec(&ses->server->inFlight); 732 atomic_dec(&ses->server->inFlight);
705 wake_up(&ses->server->request_q); 733 wake_up(&ses->server->request_q);
706 return rc; 734 return rc;
707 } 735 }
708 736
709 spin_unlock(&GlobalMid_Lock);
710 receive_len = midQ->resp_buf->smb_buf_length; 737 receive_len = midQ->resp_buf->smb_buf_length;
711 738
712 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 739 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
@@ -748,43 +775,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
748 if (receive_len >= sizeof(struct smb_hdr) - 4 775 if (receive_len >= sizeof(struct smb_hdr) - 4
749 /* do not count RFC1001 header */ + 776 /* do not count RFC1001 header */ +
750 (2 * out_buf->WordCount) + 2 /* bcc */ ) 777 (2 * out_buf->WordCount) + 2 /* bcc */ )
751 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 778 put_bcc(get_bcc_le(midQ->resp_buf), midQ->resp_buf);
752 } else { 779 } else {
753 rc = -EIO; 780 rc = -EIO;
754 cERROR(1, "Bad MID state?"); 781 cERROR(1, "Bad MID state?");
755 } 782 }
756 783
757out: 784out:
758 DeleteMidQEntry(midQ); 785 delete_mid(midQ);
759 atomic_dec(&ses->server->inFlight); 786 atomic_dec(&ses->server->inFlight);
760 wake_up(&ses->server->request_q); 787 wake_up(&ses->server->request_q);
761 788
762 return rc; 789 return rc;
763} 790}
764 791
765/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */
766
767static int
768send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf,
769 struct mid_q_entry *midQ)
770{
771 int rc = 0;
772 struct cifsSesInfo *ses = tcon->ses;
773 __u16 mid = in_buf->Mid;
774
775 header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0);
776 in_buf->Mid = mid;
777 mutex_lock(&ses->server->srv_mutex);
778 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
779 if (rc) {
780 mutex_unlock(&ses->server->srv_mutex);
781 return rc;
782 }
783 rc = smb_send(ses->server, in_buf, in_buf->smb_buf_length);
784 mutex_unlock(&ses->server->srv_mutex);
785 return rc;
786}
787
788/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows 792/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows
789 blocking lock to return. */ 793 blocking lock to return. */
790 794
@@ -807,7 +811,7 @@ send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon,
807 pSMB->hdr.Mid = GetNextMid(ses->server); 811 pSMB->hdr.Mid = GetNextMid(ses->server);
808 812
809 return SendReceive(xid, ses, in_buf, out_buf, 813 return SendReceive(xid, ses, in_buf, out_buf,
810 &bytes_returned, CIFS_STD_OP); 814 &bytes_returned, 0);
811} 815}
812 816
813int 817int
@@ -845,7 +849,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
845 return -EIO; 849 return -EIO;
846 } 850 }
847 851
848 rc = wait_for_free_request(ses, CIFS_BLOCKING_OP); 852 rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP);
849 if (rc) 853 if (rc)
850 return rc; 854 return rc;
851 855
@@ -863,7 +867,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
863 867
864 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); 868 rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number);
865 if (rc) { 869 if (rc) {
866 DeleteMidQEntry(midQ); 870 delete_mid(midQ);
867 mutex_unlock(&ses->server->srv_mutex); 871 mutex_unlock(&ses->server->srv_mutex);
868 return rc; 872 return rc;
869 } 873 }
@@ -880,7 +884,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
880 mutex_unlock(&ses->server->srv_mutex); 884 mutex_unlock(&ses->server->srv_mutex);
881 885
882 if (rc < 0) { 886 if (rc < 0) {
883 DeleteMidQEntry(midQ); 887 delete_mid(midQ);
884 return rc; 888 return rc;
885 } 889 }
886 890
@@ -899,10 +903,9 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
899 if (in_buf->Command == SMB_COM_TRANSACTION2) { 903 if (in_buf->Command == SMB_COM_TRANSACTION2) {
900 /* POSIX lock. We send a NT_CANCEL SMB to cause the 904 /* POSIX lock. We send a NT_CANCEL SMB to cause the
901 blocking lock to return. */ 905 blocking lock to return. */
902 906 rc = send_nt_cancel(ses->server, in_buf, midQ);
903 rc = send_nt_cancel(tcon, in_buf, midQ);
904 if (rc) { 907 if (rc) {
905 DeleteMidQEntry(midQ); 908 delete_mid(midQ);
906 return rc; 909 return rc;
907 } 910 }
908 } else { 911 } else {
@@ -914,47 +917,22 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
914 /* If we get -ENOLCK back the lock may have 917 /* If we get -ENOLCK back the lock may have
915 already been removed. Don't exit in this case. */ 918 already been removed. Don't exit in this case. */
916 if (rc && rc != -ENOLCK) { 919 if (rc && rc != -ENOLCK) {
917 DeleteMidQEntry(midQ); 920 delete_mid(midQ);
918 return rc; 921 return rc;
919 } 922 }
920 } 923 }
921 924
922 /* Wait 5 seconds for the response. */ 925 if (wait_for_response(ses->server, midQ) == 0) {
923 if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ) == 0) {
924 /* We got the response - restart system call. */ 926 /* We got the response - restart system call. */
925 rstart = 1; 927 rstart = 1;
926 } 928 }
927 } 929 }
928 930
929 spin_lock(&GlobalMid_Lock); 931 rc = sync_mid_result(midQ, ses->server);
930 if (midQ->resp_buf) { 932 if (rc != 0)
931 spin_unlock(&GlobalMid_Lock);
932 receive_len = midQ->resp_buf->smb_buf_length;
933 } else {
934 cERROR(1, "No response for cmd %d mid %d",
935 midQ->command, midQ->mid);
936 if (midQ->midState == MID_REQUEST_SUBMITTED) {
937 if (ses->server->tcpStatus == CifsExiting)
938 rc = -EHOSTDOWN;
939 else {
940 ses->server->tcpStatus = CifsNeedReconnect;
941 midQ->midState = MID_RETRY_NEEDED;
942 }
943 }
944
945 if (rc != -EHOSTDOWN) {
946 if (midQ->midState == MID_RETRY_NEEDED) {
947 rc = -EAGAIN;
948 cFYI(1, "marking request for retry");
949 } else {
950 rc = -EIO;
951 }
952 }
953 spin_unlock(&GlobalMid_Lock);
954 DeleteMidQEntry(midQ);
955 return rc; 933 return rc;
956 }
957 934
935 receive_len = midQ->resp_buf->smb_buf_length;
958 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { 936 if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) {
959 cERROR(1, "Frame too large received. Length: %d Xid: %d", 937 cERROR(1, "Frame too large received. Length: %d Xid: %d",
960 receive_len, xid); 938 receive_len, xid);
@@ -998,10 +976,10 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon,
998 if (receive_len >= sizeof(struct smb_hdr) - 4 976 if (receive_len >= sizeof(struct smb_hdr) - 4
999 /* do not count RFC1001 header */ + 977 /* do not count RFC1001 header */ +
1000 (2 * out_buf->WordCount) + 2 /* bcc */ ) 978 (2 * out_buf->WordCount) + 2 /* bcc */ )
1001 BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); 979 put_bcc(get_bcc_le(out_buf), out_buf);
1002 980
1003out: 981out:
1004 DeleteMidQEntry(midQ); 982 delete_mid(midQ);
1005 if (rstart && rc == -EACCES) 983 if (rstart && rc == -EACCES)
1006 return -ERESTARTSYS; 984 return -ERESTARTSYS;
1007 return rc; 985 return rc;