aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShirish Pargaonkar <shirishpargaonkar@gmail.com>2013-10-03 06:44:45 -0400
committerSteve French <smfrench@gmail.com>2013-10-06 21:18:42 -0400
commiteb4c7df6c20b407ecbf1a985edc33d967371c2e8 (patch)
tree09e3117fabaa3ec8f95f3e70a747f5e0f9990ada
parentc31f330719b7331b2112a5525fe5941a99ac223d (diff)
cifs: Avoid umount hangs with smb2 when server is unresponsive
Do not send SMB2 Logoff command when reconnecting, the way smb1 code base works. Also, no need to wait for a credit for an echo command when one is already in flight. Without these changes, umount command hangs if the server is unresponsive e.g. hibernating. Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@gmail.com> Acked-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <smfrench@us.ibm.com>
-rw-r--r--fs/cifs/smb2pdu.c6
-rw-r--r--fs/cifs/transport.c9
2 files changed, 13 insertions, 2 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index eba0efde66d7..edccb5252462 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -687,6 +687,10 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
687 else 687 else
688 return -EIO; 688 return -EIO;
689 689
690 /* no need to send SMB logoff if uid already closed due to reconnect */
691 if (ses->need_reconnect)
692 goto smb2_session_already_dead;
693
690 rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req); 694 rc = small_smb2_init(SMB2_LOGOFF, NULL, (void **) &req);
691 if (rc) 695 if (rc)
692 return rc; 696 return rc;
@@ -701,6 +705,8 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
701 * No tcon so can't do 705 * No tcon so can't do
702 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]); 706 * cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_fail[SMB2...]);
703 */ 707 */
708
709smb2_session_already_dead:
704 return rc; 710 return rc;
705} 711}
706 712
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 6fdcb1b4a106..800b938e4061 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -410,8 +410,13 @@ static int
410wait_for_free_request(struct TCP_Server_Info *server, const int timeout, 410wait_for_free_request(struct TCP_Server_Info *server, const int timeout,
411 const int optype) 411 const int optype)
412{ 412{
413 return wait_for_free_credits(server, timeout, 413 int *val;
414 server->ops->get_credits_field(server, optype)); 414
415 val = server->ops->get_credits_field(server, optype);
416 /* Since an echo is already inflight, no need to wait to send another */
417 if (*val <= 0 && optype == CIFS_ECHO_OP)
418 return -EAGAIN;
419 return wait_for_free_credits(server, timeout, val);
415} 420}
416 421
417static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, 422static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf,