[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)
This commit is contained in:
Steve French
2006-07-16 04:32:51 +00:00
parent 3a5ff61c18
commit 14a441a2b4

View File

@@ -3,7 +3,8 @@
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* * Jeremy Allison (jra@samba.org) 2006.
*
* This library is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published * it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or * 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,
/* No user interrupts in wait - wreaks havoc with performance */ /* No user interrupts in wait - wreaks havoc with performance */
if(timeout != MAX_SCHEDULE_TIMEOUT) { if(timeout != MAX_SCHEDULE_TIMEOUT) {
timeout += jiffies; unsigned long curr_timeout;
wait_event(ses->server->response_q,
(!(midQ->midState & MID_REQUEST_SUBMITTED)) || for (;;) {
(time_after(jiffies, timeout) && curr_timeout = timeout + jiffies;
time_after(jiffies, ses->server->lstrp + HZ)) || wait_event(ses->server->response_q,
((ses->server->tcpStatus != CifsGood) && (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
(ses->server->tcpStatus != CifsNew))); time_after(jiffies, curr_timeout) ||
((ses->server->tcpStatus != CifsGood) &&
(ses->server->tcpStatus != CifsNew)));
if (time_after(jiffies, curr_timeout) &&
(midQ->midState & MID_REQUEST_SUBMITTED) &&
((ses->server->tcpStatus == CifsGood) ||
(ses->server->tcpStatus == CifsNew))) {
unsigned long lrt;
/* We timed out. Is the server still
sending replies ? */
spin_lock(&GlobalMid_Lock);
lrt = ses->server->lstrp;
spin_unlock(&GlobalMid_Lock);
/* Calculate 10 seconds past last receive time.
Although we prefer not to time out if the
server is still responding - we will time
out if the server takes more than 15 (or 45
or 180) seconds to respond to this request
and has not responded to any request from
other threads on the client within 10 seconds */
lrt += (10 * HZ);
if (time_after(jiffies, lrt)) {
/* No replies for 10 seconds. */
cERROR(1,("server not responding"));
break;
}
} else {
break;
}
}
} else { } else {
wait_event(ses->server->response_q, wait_event(ses->server->response_q,
(!(midQ->midState & MID_REQUEST_SUBMITTED)) || (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
@@ -710,21 +744,40 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
/* No user interrupts in wait - wreaks havoc with performance */ /* No user interrupts in wait - wreaks havoc with performance */
if(timeout != MAX_SCHEDULE_TIMEOUT) { if(timeout != MAX_SCHEDULE_TIMEOUT) {
timeout += jiffies; unsigned long curr_timeout;
/* although we prefer not to time out if the server is still
responding - we will time out if the server takes for (;;) {
more than 15 (or 45 or 180) seconds to respond to this request curr_timeout = timeout + jiffies;
and has not responded to any request from other threads wait_event(ses->server->response_q,
on this client within a second (note that it is not worth (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
grabbing the GlobalMid_Lock and slowing things down in this time_after(jiffies, curr_timeout) ||
wait event to more accurately check the lstrsp field on some ((ses->server->tcpStatus != CifsGood) &&
arch since we are already in an error path that will retry */ (ses->server->tcpStatus != CifsNew)));
wait_event(ses->server->response_q,
(!(midQ->midState & MID_REQUEST_SUBMITTED)) || if (time_after(jiffies, curr_timeout) &&
(time_after(jiffies, timeout) && (midQ->midState & MID_REQUEST_SUBMITTED) &&
time_after(jiffies, ses->server->lstrp + HZ)) || ((ses->server->tcpStatus == CifsGood) ||
((ses->server->tcpStatus != CifsGood) && (ses->server->tcpStatus == CifsNew))) {
(ses->server->tcpStatus != CifsNew)));
unsigned long lrt;
/* We timed out. Is the server still
sending replies ? */
spin_lock(&GlobalMid_Lock);
lrt = ses->server->lstrp;
spin_unlock(&GlobalMid_Lock);
/* Calculate 10 seconds past last receive time*/
lrt += (10 * HZ);
if (time_after(jiffies, lrt)) {
/* Server sent no reply in 10 seconds */
cERROR(1,("Server not responding"));
break;
}
} else {
break;
}
}
} else { } else {
wait_event(ses->server->response_q, wait_event(ses->server->response_q,
(!(midQ->midState & MID_REQUEST_SUBMITTED)) || (!(midQ->midState & MID_REQUEST_SUBMITTED)) ||