[linux-cifs-client] Re: Bug in cifsfs POSIX locking client code.

Jeremy Allison jra at samba.org
Fri Jul 14 04:54:55 GMT 2006


On Thu, Jul 13, 2006 at 08:56:52PM -0700, Jeremy Allison wrote:
> On Wed, Jul 12, 2006 at 12:13:53AM -0700, Jeremy Allison wrote:
> > 
> > I'm guessing the waiting for blocking calls still isn't
> > working correctly....
> 
> Steve - here's a possible fix as we discussed earlier
> today - it keeps a "last received time" in the session
> struct. I'm going to test this with my tdbtorture overnight
> and see if it fixes the problem.
> 
> Let me know what you think of the patch (it applies to the
> linux-converged-for-old-kernels branch).

Right idea, missing break from for(;;) :-).

Doesn't work so well in a kernel :-).

Try this version instead .... I'm testing it right now with
the tdbtorture that was previously failing.

Jeremy.
-------------- next part --------------
Index: connect.c
===================================================================
--- connect.c	(revision 55)
+++ connect.c	(working copy)
@@ -609,6 +609,10 @@
 
 		task_to_wake = NULL;
 		spin_lock(&GlobalMid_Lock);
+
+		/* Note when we last received a reply - needed for timeout purposes. */
+		server->last_receive_time = jiffies;
+
 		list_for_each(tmp, &server->pending_mid_q) {
 			mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
 
Index: transport.c
===================================================================
--- transport.c	(revision 55)
+++ transport.c	(working copy)
@@ -476,12 +476,40 @@
 
 	/* No user interrupts in wait - wreaks havoc with performance */
 	if(timeout != MAX_SCHEDULE_TIMEOUT) {
-		timeout += jiffies;
-		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			time_after(jiffies, timeout) || 
-			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)));
+		unsigned long curr_timeout;
+
+		for (;;) {
+			curr_timeout = timeout + jiffies;
+			wait_event(ses->server->response_q,
+				(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
+				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->last_receive_time;
+				spin_unlock(&GlobalMid_Lock);
+
+				/* Calculate 15 seconds past last received time. */
+				lrt += (15 * HZ);
+				if (time_after(jiffies, lrt)) {
+					/* Server sent no replies for 15 seconds. */	
+					cERROR(1,("Server idle for 15 seconds. Timing out"));
+					break;
+				}
+			} else {
+				break;
+			}
+		}
 	} else {
 		wait_event(ses->server->response_q,
 			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
@@ -743,12 +771,40 @@
 
 	/* No user interrupts in wait - wreaks havoc with performance */
 	if(timeout != MAX_SCHEDULE_TIMEOUT) {
-		timeout += jiffies;
-		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			time_after(jiffies, timeout) || 
-			((ses->server->tcpStatus != CifsGood) &&
-			 (ses->server->tcpStatus != CifsNew)));
+		unsigned long curr_timeout;
+
+		for (;;) {
+			curr_timeout = timeout + jiffies;
+			wait_event(ses->server->response_q,
+				(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
+				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->last_receive_time;
+				spin_unlock(&GlobalMid_Lock);
+
+				/* Calculate 15 seconds past last received time. */
+				lrt += (15 * HZ);
+				if (time_after(jiffies, lrt)) {
+					/* Server sent no replies for 15 seconds. */	
+					cERROR(1,("Server idle for 15 seconds. Timing out"));
+					break;
+				}
+			} else {
+				break;
+			}
+		}
 	} else {
 		wait_event(ses->server->response_q,
 			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
Index: cifsglob.h
===================================================================
--- cifsglob.h	(revision 55)
+++ cifsglob.h	(working copy)
@@ -160,6 +160,7 @@
 	char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
 	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; 
+	unsigned long last_receive_time;
 };
 
 /*


More information about the linux-cifs-client mailing list