Skip to content

Commit

Permalink
Merge tag 'v6.14-rc7-smb3-client-fix' of git://git.samba.org/sfrench/…
Browse files Browse the repository at this point in the history
…cifs-2.6

Pull smb client fix from Steve French:
 "smb3 client reconnect fix"

* tag 'v6.14-rc7-smb3-client-fix' of git://git.samba.org/sfrench/cifs-2.6:
  smb: client: don't retry IO on failed negprotos with soft mounts
  • Loading branch information
Linus Torvalds committed Mar 21, 2025
2 parents a1cffe8 + 7643dbd commit a7ea35b
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 73 deletions.
46 changes: 27 additions & 19 deletions fs/smb/client/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,23 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)

mutex_lock(&ses->session_mutex);
/*
* Recheck after acquire mutex. If another thread is negotiating
* and the server never sends an answer the socket will be closed
* and tcpStatus set to reconnect.
* Handle the case where a concurrent thread failed to negotiate or
* killed a channel.
*/
spin_lock(&server->srv_lock);
if (server->tcpStatus == CifsNeedReconnect) {
switch (server->tcpStatus) {
case CifsExiting:
spin_unlock(&server->srv_lock);
mutex_unlock(&ses->session_mutex);

if (tcon->retry)
goto again;
rc = -EHOSTDOWN;
goto out;
return -EHOSTDOWN;
case CifsNeedReconnect:
spin_unlock(&server->srv_lock);
mutex_unlock(&ses->session_mutex);
if (!tcon->retry)
return -EHOSTDOWN;
goto again;
default:
break;
}
spin_unlock(&server->srv_lock);

Expand All @@ -152,16 +156,20 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
spin_unlock(&ses->ses_lock);

rc = cifs_negotiate_protocol(0, ses, server);
if (!rc) {
rc = cifs_setup_session(0, ses, server, ses->local_nls);
if ((rc == -EACCES) || (rc == -EHOSTDOWN) || (rc == -EKEYREVOKED)) {
/*
* Try alternate password for next reconnect if an alternate
* password is available.
*/
if (ses->password2)
swap(ses->password2, ses->password);
}
if (rc) {
mutex_unlock(&ses->session_mutex);
if (!tcon->retry)
return -EHOSTDOWN;
goto again;
}
rc = cifs_setup_session(0, ses, server, ses->local_nls);
if ((rc == -EACCES) || (rc == -EHOSTDOWN) || (rc == -EKEYREVOKED)) {
/*
* Try alternate password for next reconnect if an alternate
* password is available.
*/
if (ses->password2)
swap(ses->password2, ses->password);
}

/* do we need to reconnect tcon? */
Expand Down
96 changes: 42 additions & 54 deletions fs/smb/client/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,32 +300,23 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,

mutex_lock(&ses->session_mutex);
/*
* if this is called by delayed work, and the channel has been disabled
* in parallel, the delayed work can continue to execute in parallel
* there's a chance that this channel may not exist anymore
* Handle the case where a concurrent thread failed to negotiate or
* killed a channel.
*/
spin_lock(&server->srv_lock);
if (server->tcpStatus == CifsExiting) {
switch (server->tcpStatus) {
case CifsExiting:
spin_unlock(&server->srv_lock);
mutex_unlock(&ses->session_mutex);
rc = -EHOSTDOWN;
goto out;
}

/*
* Recheck after acquire mutex. If another thread is negotiating
* and the server never sends an answer the socket will be closed
* and tcpStatus set to reconnect.
*/
if (server->tcpStatus == CifsNeedReconnect) {
return -EHOSTDOWN;
case CifsNeedReconnect:
spin_unlock(&server->srv_lock);
mutex_unlock(&ses->session_mutex);

if (tcon->retry)
goto again;

rc = -EHOSTDOWN;
goto out;
if (!tcon->retry)
return -EHOSTDOWN;
goto again;
default:
break;
}
spin_unlock(&server->srv_lock);

Expand All @@ -350,43 +341,41 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
spin_unlock(&ses->ses_lock);

rc = cifs_negotiate_protocol(0, ses, server);
if (!rc) {
/*
* if server stopped supporting multichannel
* and the first channel reconnected, disable all the others.
*/
if (ses->chan_count > 1 &&
!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
rc = cifs_chan_skip_or_disable(ses, server,
from_reconnect);
if (rc) {
mutex_unlock(&ses->session_mutex);
goto out;
}
}

rc = cifs_setup_session(0, ses, server, ses->local_nls);
if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
/*
* Try alternate password for next reconnect (key rotation
* could be enabled on the server e.g.) if an alternate
* password is available and the current password is expired,
* but do not swap on non pwd related errors like host down
*/
if (ses->password2)
swap(ses->password2, ses->password);
}

if ((rc == -EACCES) && !tcon->retry) {
mutex_unlock(&ses->session_mutex);
rc = -EHOSTDOWN;
goto failed;
} else if (rc) {
if (rc) {
mutex_unlock(&ses->session_mutex);
if (!tcon->retry)
return -EHOSTDOWN;
goto again;
}
/*
* if server stopped supporting multichannel
* and the first channel reconnected, disable all the others.
*/
if (ses->chan_count > 1 &&
!(server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
rc = cifs_chan_skip_or_disable(ses, server,
from_reconnect);
if (rc) {
mutex_unlock(&ses->session_mutex);
goto out;
}
} else {
}

rc = cifs_setup_session(0, ses, server, ses->local_nls);
if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
/*
* Try alternate password for next reconnect (key rotation
* could be enabled on the server e.g.) if an alternate
* password is available and the current password is expired,
* but do not swap on non pwd related errors like host down
*/
if (ses->password2)
swap(ses->password2, ses->password);
}
if (rc) {
mutex_unlock(&ses->session_mutex);
if (rc == -EACCES && !tcon->retry)
return -EHOSTDOWN;
goto out;
}

Expand Down Expand Up @@ -490,7 +479,6 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
case SMB2_IOCTL:
rc = -EAGAIN;
}
failed:
return rc;
}

Expand Down

0 comments on commit a7ea35b

Please sign in to comment.