Commit 1a6a41d4 authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French
Browse files

cifs: do not use tcpStatus after negotiate completes



Recent changes to multichannel to allow channel reconnects to
work in parallel and independent of each other did so by
making use of tcpStatus for the connection, and status for the
session. However, this did not take into account the multiuser
scenario, where same connection is used by multiple connections.

However, tcpStatus should be tracked only till the end of
negotiate exchange, and not used for session setup. This change
fixes this.

Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 52832252
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -3973,7 +3973,7 @@ cifs_negotiate_protocol(const unsigned int xid, struct cifs_ses *ses,
	if (rc == 0) {
		spin_lock(&cifs_tcp_ses_lock);
		if (server->tcpStatus == CifsInNegotiate)
			server->tcpStatus = CifsNeedSessSetup;
			server->tcpStatus = CifsGood;
		else
			rc = -EHOSTDOWN;
		spin_unlock(&cifs_tcp_ses_lock);
@@ -3996,19 +3996,18 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
	bool is_binding = false;

	/* only send once per connect */
	spin_lock(&ses->chan_lock);
	is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
	spin_unlock(&ses->chan_lock);

	spin_lock(&cifs_tcp_ses_lock);
	if ((server->tcpStatus != CifsNeedSessSetup) &&
	    (ses->status == CifsGood)) {
	if (ses->status == CifsExiting) {
		spin_unlock(&cifs_tcp_ses_lock);
		return 0;
	}
	server->tcpStatus = CifsInSessSetup;
	ses->status = CifsInSessSetup;
	spin_unlock(&cifs_tcp_ses_lock);

	spin_lock(&ses->chan_lock);
	is_binding = !CIFS_ALL_CHANS_NEED_RECONNECT(ses);
	spin_unlock(&ses->chan_lock);

	if (!is_binding) {
		ses->capabilities = server->capabilities;
		if (!linuxExtEnabled)
@@ -4032,13 +4031,13 @@ cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
	if (rc) {
		cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc);
		spin_lock(&cifs_tcp_ses_lock);
		if (server->tcpStatus == CifsInSessSetup)
			server->tcpStatus = CifsNeedSessSetup;
		if (ses->status == CifsInSessSetup)
			ses->status = CifsNeedSessSetup;
		spin_unlock(&cifs_tcp_ses_lock);
	} else {
		spin_lock(&cifs_tcp_ses_lock);
		if (server->tcpStatus == CifsInSessSetup)
			server->tcpStatus = CifsGood;
		if (ses->status == CifsInSessSetup)
			ses->status = CifsGood;
		/* Even if one channel is active, session is in good state */
		ses->status = CifsGood;
		spin_unlock(&cifs_tcp_ses_lock);
+2 −1
Original line number Diff line number Diff line
@@ -3899,7 +3899,8 @@ SMB2_echo(struct TCP_Server_Info *server)
	cifs_dbg(FYI, "In echo request for conn_id %lld\n", server->conn_id);

	spin_lock(&cifs_tcp_ses_lock);
	if (server->tcpStatus == CifsNeedNegotiate) {
	if (server->ops->need_neg &&
	    server->ops->need_neg(server)) {
		spin_unlock(&cifs_tcp_ses_lock);
		/* No need to send echo on newly established connections */
		mod_delayed_work(cifsiod_wq, &server->reconnect, 0);
+2 −1
Original line number Diff line number Diff line
@@ -641,7 +641,8 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
	if (!is_signed)
		return 0;
	spin_lock(&cifs_tcp_ses_lock);
	if (server->tcpStatus == CifsNeedNegotiate) {
	if (server->ops->need_neg &&
	    server->ops->need_neg(server)) {
		spin_unlock(&cifs_tcp_ses_lock);
		return 0;
	}