aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/transport.c
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2006-07-16 00:32:51 -0400
committerSteve French <sfrench@us.ibm.com>2006-08-11 17:27:41 -0400
commit14a441a2b4ee1dfc00ec822d91d9fb20f401c62f (patch)
tree122a33e5e056bdd433e78b4f6a1c9f8e2d3385d2 /fs/cifs/transport.c
parent3a5ff61c18659443f76bad6cf06f60103046de5d (diff)
[CIFS] spinlock protect read of last srv response time in timeout path
Signed-off-by: Jeremy Allison <jra@samba.org> Signed-off-by: Steve French <sfrench@us.ibm.com> (cherry picked from b33a3f55e54fd210fc043eafcf83728b03bc9e02 commit)
Diffstat (limited to 'fs/cifs/transport.c')
-rw-r--r--fs/cifs/transport.c99
1 files changed, 76 insertions, 23 deletions
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 95e23ca670a8..d16e6032d4cf 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -3,7 +3,8 @@
3 * 3 *
4 * Copyright (C) International Business Machines Corp., 2002,2005 4 * Copyright (C) International Business Machines Corp., 2002,2005
5 * Author(s): Steve French (sfrench@us.ibm.com) 5 * Author(s): Steve French (sfrench@us.ibm.com)
6 * 6 * Jeremy Allison (jra@samba.org) 2006.
7 *
7 * This library is free software; you can redistribute it and/or modify 8 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published 9 * it under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation; either version 2.1 of the License, or 10 * by the Free Software Foundation; either version 2.1 of the License, or
@@ -442,13 +443,46 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
442 443
443 /* No user interrupts in wait - wreaks havoc with performance */ 444 /* No user interrupts in wait - wreaks havoc with performance */
444 if(timeout != MAX_SCHEDULE_TIMEOUT) { 445 if(timeout != MAX_SCHEDULE_TIMEOUT) {
445 timeout += jiffies; 446 unsigned long curr_timeout;
446 wait_event(ses->server->response_q, 447
447 (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 448 for (;;) {
448 (time_after(jiffies, timeout) && 449 curr_timeout = timeout + jiffies;
449 time_after(jiffies, ses->server->lstrp + HZ)) || 450 wait_event(ses->server->response_q,
450 ((ses->server->tcpStatus != CifsGood) && 451 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
451 (ses->server->tcpStatus != CifsNew))); 452 time_after(jiffies, curr_timeout) ||
453 ((ses->server->tcpStatus != CifsGood) &&
454 (ses->server->tcpStatus != CifsNew)));
455
456 if (time_after(jiffies, curr_timeout) &&
457 (midQ->midState & MID_REQUEST_SUBMITTED) &&
458 ((ses->server->tcpStatus == CifsGood) ||
459 (ses->server->tcpStatus == CifsNew))) {
460
461 unsigned long lrt;
462
463 /* We timed out. Is the server still
464 sending replies ? */
465 spin_lock(&GlobalMid_Lock);
466 lrt = ses->server->lstrp;
467 spin_unlock(&GlobalMid_Lock);
468
469 /* Calculate 10 seconds past last receive time.
470 Although we prefer not to time out if the
471 server is still responding - we will time
472 out if the server takes more than 15 (or 45
473 or 180) seconds to respond to this request
474 and has not responded to any request from
475 other threads on the client within 10 seconds */
476 lrt += (10 * HZ);
477 if (time_after(jiffies, lrt)) {
478 /* No replies for 10 seconds. */
479 cERROR(1,("server not responding"));
480 break;
481 }
482 } else {
483 break;
484 }
485 }
452 } else { 486 } else {
453 wait_event(ses->server->response_q, 487 wait_event(ses->server->response_q,
454 (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 488 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
@@ -710,21 +744,40 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
710 744
711 /* No user interrupts in wait - wreaks havoc with performance */ 745 /* No user interrupts in wait - wreaks havoc with performance */
712 if(timeout != MAX_SCHEDULE_TIMEOUT) { 746 if(timeout != MAX_SCHEDULE_TIMEOUT) {
713 timeout += jiffies; 747 unsigned long curr_timeout;
714 /* although we prefer not to time out if the server is still 748
715 responding - we will time out if the server takes 749 for (;;) {
716 more than 15 (or 45 or 180) seconds to respond to this request 750 curr_timeout = timeout + jiffies;
717 and has not responded to any request from other threads 751 wait_event(ses->server->response_q,
718 on this client within a second (note that it is not worth 752 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
719 grabbing the GlobalMid_Lock and slowing things down in this 753 time_after(jiffies, curr_timeout) ||
720 wait event to more accurately check the lstrsp field on some 754 ((ses->server->tcpStatus != CifsGood) &&
721 arch since we are already in an error path that will retry */ 755 (ses->server->tcpStatus != CifsNew)));
722 wait_event(ses->server->response_q, 756
723 (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 757 if (time_after(jiffies, curr_timeout) &&
724 (time_after(jiffies, timeout) && 758 (midQ->midState & MID_REQUEST_SUBMITTED) &&
725 time_after(jiffies, ses->server->lstrp + HZ)) || 759 ((ses->server->tcpStatus == CifsGood) ||
726 ((ses->server->tcpStatus != CifsGood) && 760 (ses->server->tcpStatus == CifsNew))) {
727 (ses->server->tcpStatus != CifsNew))); 761
762 unsigned long lrt;
763
764 /* We timed out. Is the server still
765 sending replies ? */
766 spin_lock(&GlobalMid_Lock);
767 lrt = ses->server->lstrp;
768 spin_unlock(&GlobalMid_Lock);
769
770 /* Calculate 10 seconds past last receive time*/
771 lrt += (10 * HZ);
772 if (time_after(jiffies, lrt)) {
773 /* Server sent no reply in 10 seconds */
774 cERROR(1,("Server not responding"));
775 break;
776 }
777 } else {
778 break;
779 }
780 }
728 } else { 781 } else {
729 wait_event(ses->server->response_q, 782 wait_event(ses->server->response_q,
730 (!(midQ->midState & MID_REQUEST_SUBMITTED)) || 783 (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||