[PATCH] cifs: Better handle errors on second socket recv message call

Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 322a124..8fc0801 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/cifsglob.h
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2003
+ *   Copyright (C) International Business Machines  Corp., 2002,2005
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -321,6 +321,7 @@
 	__u8 command;	/* smb command code */
 	unsigned multiPart:1;	/* multiple responses to one SMB request */
 	unsigned largeBuf:1;    /* if valid response, is pointer to large buf */
+	unsigned multiResp:1    /* multiple trans2 responses for one request  */
 };
 
 struct oplock_q_entry {
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d5d49b5..8c5d310 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -359,20 +359,36 @@
 					length = 0;
 					iov.iov_base = 4 + (char *)smb_buffer;
 					iov.iov_len = pdu_length;
-					for (total_read = 0; 
+					for (total_read = 0;
 					     total_read < pdu_length;
 					     total_read += length) {
-						length = kernel_recvmsg(csocket, &smb_msg, 
+						length = kernel_recvmsg(csocket, &smb_msg,
 							&iov, 1,
 							pdu_length - total_read, 0);
-						if (length == 0) {
+						if((server->tcpStatus == CifsExiting) ||
+						    (length == -EINTR)) {
+							/* then will exit */
+							goto dmx_loop_end;
+						} else if (server->tcpStatus ==
+							    CifsNeedReconnect) {
+							cifs_reconnect(server);
+							csocket = server->ssocket;
+						/* Reconnect wakes up rspns q */
+						/* Now we will reread sock */
+							goto dmx_loop_end;
+						} else if ((length == -ERESTARTSYS) || 
+							   (length == -EAGAIN)) {
+							msleep(1); /* minimum sleep to prevent looping
+                                                                allowing socket to clear and app threads to set
+                                                                tcpStatus CifsNeedReconnect if server hung */
+							continue;
+						} else if (length <= 0) {
 							cERROR(1,
-							       ("Zero length receive when expecting %d ",
+							       ("Received no data, expecting %d",
 								pdu_length - total_read));
 							cifs_reconnect(server);
 							csocket = server->ssocket;
-							wake_up(&server->response_q);
-							continue;
+							goto dmx_loop_end;
 						}
 					}
 					length += 4; /* account for rfc1002 hdr */
@@ -434,6 +450,9 @@
 			wake_up(&server->response_q);
 			continue;
 		}
+dmx_loop_end:
+		cFYI(1,("Exiting cifsd loop"));
+
 	}
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;