summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2011-04-12 01:01:14 +0000
committerSteve French <sfrench@us.ibm.com>2011-04-12 01:01:14 +0000
commitfd88ce9313e9f9d3b56eada7fc76a301828baefd (patch)
treeda6f5ec8cbb639b68ed68d22ab3d879b51550f42
parent157c249114508aa71daa308a426e15d81a4eed00 (diff)
downloadkernel-common-fd88ce9313e9f9d3b56eada7fc76a301828baefd.tar.gz
kernel-common-fd88ce9313e9f9d3b56eada7fc76a301828baefd.tar.bz2
kernel-common-fd88ce9313e9f9d3b56eada7fc76a301828baefd.zip
[CIFS] cifs: clarify the meaning of tcpStatus == CifsGood
When the TCP_Server_Info is first allocated and connected, tcpStatus == CifsGood means that the NEGOTIATE_PROTOCOL request has completed and the socket is ready for other calls. cifs_reconnect however sets tcpStatus to CifsGood as soon as the socket is reconnected and the optional RFC1001 session setup is done. We have no clear way to tell the difference between these two states, and we need to know this in order to know whether we can send an echo or not. Resolve this by adding a new statusEnum value -- CifsNeedNegotiate. When the socket has been connected but has not yet had a NEGOTIATE_PROTOCOL request done, set it to this value. Once the NEGOTIATE is done, cifs_negotiate_protocol will set tcpStatus to CifsGood. This also fixes and cleans the logic in cifs_reconnect and cifs_reconnect_tcon. The old code checked for specific states when what it really wants to know is whether the state has actually changed from CifsNeedReconnect. Reported-and-Tested-by: JG <jg@cms.ac> Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/connect.c8
3 files changed, 8 insertions, 7 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 1cff9aa9020c..ddb359906708 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -91,7 +91,8 @@ enum statusEnum {
CifsNew = 0,
CifsGood,
CifsExiting,
- CifsNeedReconnect
+ CifsNeedReconnect,
+ CifsNeedNegotiate
};
enum securityEnum {
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 3919ec8f956e..df959bae6728 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -142,9 +142,9 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
*/
while (server->tcpStatus == CifsNeedReconnect) {
wait_event_interruptible_timeout(server->response_q,
- (server->tcpStatus == CifsGood), 10 * HZ);
+ (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
- /* is TCP session is reestablished now ?*/
+ /* are we still trying to reconnect? */
if (server->tcpStatus != CifsNeedReconnect)
break;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 709fd9d9b78f..8cf4a63a36d5 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -199,8 +199,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
}
spin_unlock(&GlobalMid_Lock);
- while ((server->tcpStatus != CifsExiting) &&
- (server->tcpStatus != CifsGood)) {
+ while (server->tcpStatus == CifsNeedReconnect) {
try_to_freeze();
/* we should try only the port we connected to before */
@@ -212,7 +211,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
atomic_inc(&tcpSesReconnectCount);
spin_lock(&GlobalMid_Lock);
if (server->tcpStatus != CifsExiting)
- server->tcpStatus = CifsGood;
+ server->tcpStatus = CifsNeedNegotiate;
spin_unlock(&GlobalMid_Lock);
}
}
@@ -421,7 +420,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
pdu_length = 4; /* enough to get RFC1001 header */
incomplete_rcv:
- if (echo_retries > 0 &&
+ if (echo_retries > 0 && server->tcpStatus == CifsGood &&
time_after(jiffies, server->lstrp +
(echo_retries * SMB_ECHO_INTERVAL))) {
cERROR(1, "Server %s has not responded in %d seconds. "
@@ -1766,6 +1765,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
module_put(THIS_MODULE);
goto out_err_crypto_release;
}
+ tcp_ses->tcpStatus = CifsNeedNegotiate;
/* thread spawned, put it on the list */
spin_lock(&cifs_tcp_ses_lock);