浏览代码

[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>
Steve French 20 年之前
父节点
当前提交
67010fbc6f
共有 2 个文件被更改,包括 27 次插入7 次删除
  1. 2 1
      fs/cifs/cifsglob.h
  2. 25 6
      fs/cifs/connect.c

+ 2 - 1
fs/cifs/cifsglob.h

@@ -1,7 +1,7 @@
 /*
 /*
  *   fs/cifs/cifsglob.h
  *   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)
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *
  *   This library is free software; you can redistribute it and/or modify
  *   This library is free software; you can redistribute it and/or modify
@@ -321,6 +321,7 @@ struct mid_q_entry {
 	__u8 command;	/* smb command code */
 	__u8 command;	/* smb command code */
 	unsigned multiPart:1;	/* multiple responses to one SMB request */
 	unsigned multiPart:1;	/* multiple responses to one SMB request */
 	unsigned largeBuf:1;    /* if valid response, is pointer to large buf */
 	unsigned largeBuf:1;    /* if valid response, is pointer to large buf */
+	unsigned multiResp:1    /* multiple trans2 responses for one request  */
 };
 };
 
 
 struct oplock_q_entry {
 struct oplock_q_entry {

+ 25 - 6
fs/cifs/connect.c

@@ -359,20 +359,36 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
 					length = 0;
 					length = 0;
 					iov.iov_base = 4 + (char *)smb_buffer;
 					iov.iov_base = 4 + (char *)smb_buffer;
 					iov.iov_len = pdu_length;
 					iov.iov_len = pdu_length;
-					for (total_read = 0; 
+					for (total_read = 0;
 					     total_read < pdu_length;
 					     total_read < pdu_length;
 					     total_read += length) {
 					     total_read += length) {
-						length = kernel_recvmsg(csocket, &smb_msg, 
+						length = kernel_recvmsg(csocket, &smb_msg,
 							&iov, 1,
 							&iov, 1,
 							pdu_length - total_read, 0);
 							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,
 							cERROR(1,
-							       ("Zero length receive when expecting %d ",
+							       ("Received no data, expecting %d",
 								pdu_length - total_read));
 								pdu_length - total_read));
 							cifs_reconnect(server);
 							cifs_reconnect(server);
 							csocket = server->ssocket;
 							csocket = server->ssocket;
-							wake_up(&server->response_q);
-							continue;
+							goto dmx_loop_end;
 						}
 						}
 					}
 					}
 					length += 4; /* account for rfc1002 hdr */
 					length += 4; /* account for rfc1002 hdr */
@@ -434,6 +450,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
 			wake_up(&server->response_q);
 			wake_up(&server->response_q);
 			continue;
 			continue;
 		}
 		}
+dmx_loop_end:
+		cFYI(1,("Exiting cifsd loop"));
+
 	}
 	}
 	spin_lock(&GlobalMid_Lock);
 	spin_lock(&GlobalMid_Lock);
 	server->tcpStatus = CifsExiting;
 	server->tcpStatus = CifsExiting;