aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorFederico Sauter <fsauter@innominate.com>2015-03-17 12:45:28 -0400
committerSteve French <smfrench@gmail.com>2015-05-20 14:25:55 -0400
commit4afe260bab50290a05e5732570329a530ed023f3 (patch)
treef5b2c9281cd3fe80c9bfcc3679baed8155bfdc76 /fs/cifs
parentb29103076bec8316e155e71309dc0fba499022c6 (diff)
CIFS: Fix race condition on RFC1002_NEGATIVE_SESSION_RESPONSE
This patch fixes a race condition that occurs when connecting to a NT 3.51 host without specifying a NetBIOS name. In that case a RFC1002_NEGATIVE_SESSION_RESPONSE is received and the SMB negotiation is reattempted, but under some conditions it leads SendReceive() to hang forever while waiting for srv_mutex. This, in turn, sets the calling process to an uninterruptible sleep state and makes it unkillable. The solution is to unlock the srv_mutex acquired in the demux thread *before* going to sleep (after the reconnect error) and before reattempting the connection.
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/connect.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index f3bfe08e177b..8383d5ea4202 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -386,6 +386,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
386 rc = generic_ip_connect(server); 386 rc = generic_ip_connect(server);
387 if (rc) { 387 if (rc) {
388 cifs_dbg(FYI, "reconnect error %d\n", rc); 388 cifs_dbg(FYI, "reconnect error %d\n", rc);
389 mutex_unlock(&server->srv_mutex);
389 msleep(3000); 390 msleep(3000);
390 } else { 391 } else {
391 atomic_inc(&tcpSesReconnectCount); 392 atomic_inc(&tcpSesReconnectCount);
@@ -393,8 +394,8 @@ cifs_reconnect(struct TCP_Server_Info *server)
393 if (server->tcpStatus != CifsExiting) 394 if (server->tcpStatus != CifsExiting)
394 server->tcpStatus = CifsNeedNegotiate; 395 server->tcpStatus = CifsNeedNegotiate;
395 spin_unlock(&GlobalMid_Lock); 396 spin_unlock(&GlobalMid_Lock);
397 mutex_unlock(&server->srv_mutex);
396 } 398 }
397 mutex_unlock(&server->srv_mutex);
398 } while (server->tcpStatus == CifsNeedReconnect); 399 } while (server->tcpStatus == CifsNeedReconnect);
399 400
400 return rc; 401 return rc;