Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14a441a2 authored by Steve French's avatar Steve French
Browse files

[CIFS] spinlock protect read of last srv response time in timeout path



Signed-off-by: default avatarJeremy Allison <jra@samba.org>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
(cherry picked from b33a3f55e54fd210fc043eafcf83728b03bc9e02 commit)
parent 3a5ff61c
Loading
Loading
Loading
Loading
+76 −23
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 *
 *   Copyright (C) International Business Machines  Corp., 2002,2005
 *   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
 *   it under the terms of the GNU Lesser General Public License as published
@@ -442,13 +443,46 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,

	/* No user interrupts in wait - wreaks havoc with performance */
	if(timeout != MAX_SCHEDULE_TIMEOUT) {
		timeout += jiffies;
		unsigned long curr_timeout;

		for (;;) {
			curr_timeout = timeout + jiffies;
			wait_event(ses->server->response_q,
				(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
			(time_after(jiffies, timeout) &&
				time_after(jiffies, ses->server->lstrp + HZ)) ||
				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 {
		wait_event(ses->server->response_q,
			(!(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 */
	if(timeout != MAX_SCHEDULE_TIMEOUT) {
		timeout += jiffies;
		/* 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 this client within a second (note that it is not worth
		grabbing the GlobalMid_Lock and slowing things down in this
		wait event to more accurately check the lstrsp field on some 
		arch since we are already in an error path that will retry */
		unsigned long curr_timeout;

		for (;;) {
			curr_timeout = timeout + jiffies;
			wait_event(ses->server->response_q,
				(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
			(time_after(jiffies, timeout) &&
				time_after(jiffies, ses->server->lstrp + HZ)) ||
				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*/
				lrt += (10 * HZ);
				if (time_after(jiffies, lrt)) {
					/* Server sent no reply in 10 seconds */
					cERROR(1,("Server not responding"));
					break;
				}
			} else {
				break;
			}
		}
	} else {
		wait_event(ses->server->response_q,
			(!(midQ->midState & MID_REQUEST_SUBMITTED)) ||