[PATCH] cifs: Better handle errors on second socket recv message call
authorSteve French <smfrench@austin.rr.com>
Fri, 29 Apr 2005 05:41:09 +0000 (22:41 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 29 Apr 2005 05:41:09 +0000 (22:41 -0700)
Signed-off-by: Steve French (sfrench@us.ibm.com)
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/cifs/cifsglob.h
fs/cifs/connect.c

index 322a124..8fc0801 100644 (file)
@@ -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 @@ struct mid_q_entry {
        __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 {
index d5d49b5..8c5d310 100644 (file)
@@ -359,20 +359,36 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                                        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 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                        wake_up(&server->response_q);
                        continue;
                }
+dmx_loop_end:
+               cFYI(1,("Exiting cifsd loop"));
+
        }
        spin_lock(&GlobalMid_Lock);
        server->tcpStatus = CifsExiting;