diff options
-rw-r--r-- | fs/cifs/cifssmb.c | 12 | ||||
-rw-r--r-- | fs/cifs/connect.c | 3 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 12 |
3 files changed, 26 insertions, 1 deletions
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 48455afefec8..7cbe28315971 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -178,6 +178,18 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) | |||
178 | * reconnect the same SMB session | 178 | * reconnect the same SMB session |
179 | */ | 179 | */ |
180 | mutex_lock(&ses->session_mutex); | 180 | mutex_lock(&ses->session_mutex); |
181 | |||
182 | /* | ||
183 | * Recheck after acquire mutex. If another thread is negotiating | ||
184 | * and the server never sends an answer the socket will be closed | ||
185 | * and tcpStatus set to reconnect. | ||
186 | */ | ||
187 | if (server->tcpStatus == CifsNeedReconnect) { | ||
188 | rc = -EHOSTDOWN; | ||
189 | mutex_unlock(&ses->session_mutex); | ||
190 | goto out; | ||
191 | } | ||
192 | |||
181 | rc = cifs_negotiate_protocol(0, ses); | 193 | rc = cifs_negotiate_protocol(0, ses); |
182 | if (rc == 0 && ses->need_reconnect) | 194 | if (rc == 0 && ses->need_reconnect) |
183 | rc = cifs_setup_session(0, ses, nls_codepage); | 195 | rc = cifs_setup_session(0, ses, nls_codepage); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 83a8f52cd879..5aa2d278ca84 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -509,7 +509,8 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
509 | * 65s kernel_recvmsg times out, and we see that we haven't gotten | 509 | * 65s kernel_recvmsg times out, and we see that we haven't gotten |
510 | * a response in >60s. | 510 | * a response in >60s. |
511 | */ | 511 | */ |
512 | if (server->tcpStatus == CifsGood && | 512 | if ((server->tcpStatus == CifsGood || |
513 | server->tcpStatus == CifsNeedNegotiate) && | ||
513 | time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { | 514 | time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { |
514 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", | 515 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", |
515 | server->hostname, (2 * server->echo_interval) / HZ); | 516 | server->hostname, (2 * server->echo_interval) / HZ); |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index d7595e735304..5531e7ee1210 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -238,6 +238,18 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) | |||
238 | * the same SMB session | 238 | * the same SMB session |
239 | */ | 239 | */ |
240 | mutex_lock(&tcon->ses->session_mutex); | 240 | mutex_lock(&tcon->ses->session_mutex); |
241 | |||
242 | /* | ||
243 | * Recheck after acquire mutex. If another thread is negotiating | ||
244 | * and the server never sends an answer the socket will be closed | ||
245 | * and tcpStatus set to reconnect. | ||
246 | */ | ||
247 | if (server->tcpStatus == CifsNeedReconnect) { | ||
248 | rc = -EHOSTDOWN; | ||
249 | mutex_unlock(&tcon->ses->session_mutex); | ||
250 | goto out; | ||
251 | } | ||
252 | |||
241 | rc = cifs_negotiate_protocol(0, tcon->ses); | 253 | rc = cifs_negotiate_protocol(0, tcon->ses); |
242 | if (!rc && tcon->ses->need_reconnect) | 254 | if (!rc && tcon->ses->need_reconnect) |
243 | rc = cifs_setup_session(0, tcon->ses, nls_codepage); | 255 | rc = cifs_setup_session(0, tcon->ses, nls_codepage); |