From: Enzo Matsumiya <ematsumiya@suse.de>
To: linux-cifs@vger.kernel.org
Cc: pc@manguebit.org, linkinjeon@kernel.org,
ronniesahlberg@gmail.com, sprasad@microsoft.com, tom@talpey.com,
bharathsm@microsoft.com, henrique.carvalho@suse.com,
Enzo Matsumiya <ematsumiya@suse.de>
Subject: [PATCH v2 1/2] smb: client: fast fail sends if need to reconnect
Date: Mon, 28 Sep 2026 12:03:54 -0300 [thread overview]
Message-ID: <20260928150355.850472-2-ematsumiya@suse.de> (raw)
In-Reply-To: <20260928150355.850472-1-ematsumiya@suse.de>
smb_send_kvec() keeps retrying when server needs to reconnect, which
makes no sense as cifs_reconnect() will never run in parallel (because
both need server mutex).
IOW, retrying will never succeed, but only delay reconnects further.
Bail out early from smb_send_kvec() when need to reconnect.
Also shutdown socket queues when CifsNeedReconnect is first set, so any
sends/receives fails immediately (don't wait for socket to timeout).
Consequential change:
To shutdown the socket, we need to hold server mutex. Since not all
callers hold it when calling cifs_signal_cifsd_for_reconnect(), we
need to keep track of the owner task, so we can lock it as needed.
Add TCP_Server_Info::mutex_owner for that.
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
---
v1 -> v2 (fix issues detected by sashiko):
- move kernel_sock_shutdown() call out of cifs_tcp_ses_lock
- use server mutex to check/shutdown socket
fs/smb/client/cifsglob.h | 3 +++
fs/smb/client/connect.c | 54 +++++++++++++++++++++++++++++++--------
fs/smb/client/transport.c | 8 ++++++
3 files changed, 55 insertions(+), 10 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 79e4e84f8985..d279b5c92a08 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -711,6 +711,7 @@ struct TCP_Server_Info {
spinlock_t req_lock; /* protect the two values above */
struct mutex _srv_mutex;
unsigned int nofs_flag;
+ struct task_struct *mutex_owner;
struct task_struct *tsk;
char server_GUID[16];
__u16 sec_mode;
@@ -847,12 +848,14 @@ static inline void cifs_server_lock(struct TCP_Server_Info *server)
mutex_lock(&server->_srv_mutex);
server->nofs_flag = nofs_flag;
+ server->mutex_owner = current;
}
static inline void cifs_server_unlock(struct TCP_Server_Info *server)
{
unsigned int nofs_flag = server->nofs_flag;
+ server->mutex_owner = NULL;
mutex_unlock(&server->_srv_mutex);
memalloc_nofs_restore(nofs_flag);
}
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 28e1ddeb6182..4cc433308c96 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -127,13 +127,42 @@ void smb2_query_server_interfaces(struct work_struct *work)
(SMB_INTERFACE_POLL_INTERVAL * HZ));
}
-#define set_need_reco(server) \
-do { \
- spin_lock(&server->srv_lock); \
- if (server->tcpStatus != CifsExiting) \
- server->tcpStatus = CifsNeedReconnect; \
- spin_unlock(&server->srv_lock); \
-} while (0)
+static inline bool __set_need_reco(struct TCP_Server_Info *server)
+{
+ bool need_reco = false;
+
+ spin_lock(&server->srv_lock);
+ if (server->tcpStatus != CifsExiting) {
+ need_reco = (server->tcpStatus != CifsNeedReconnect);
+ server->tcpStatus = CifsNeedReconnect;
+ }
+ spin_unlock(&server->srv_lock);
+
+ return need_reco;
+}
+
+static inline void kill_socket_queues(struct TCP_Server_Info *server)
+{
+ bool locked = false;
+
+ if (server->mutex_owner != current) {
+ cifs_server_lock(server);
+ locked = true;
+ }
+
+ if (server->ssocket)
+ /* Don't release it yet! */
+ kernel_sock_shutdown(server->ssocket, SHUT_RDWR);
+
+ if (locked)
+ cifs_server_unlock(server);
+}
+
+static inline void set_need_reco(struct TCP_Server_Info *server)
+{
+ if (__set_need_reco(server))
+ kill_socket_queues(server);
+}
/*
* Update the tcpStatus for the server.
@@ -151,6 +180,7 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
struct TCP_Server_Info *nserver;
struct cifs_ses *ses;
LIST_HEAD(reco);
+ bool shutdown;
int i;
/* if we need to signal just this channel */
@@ -162,7 +192,7 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
if (SERVER_IS_CHAN(server))
server = server->primary_server;
scoped_guard(spinlock, &cifs_tcp_ses_lock) {
- set_need_reco(server);
+ shutdown = __set_need_reco(server);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
spin_lock(&ses->ses_lock);
if (ses->ses_status == SES_EXITING) {
@@ -184,6 +214,9 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
}
}
+ if (shutdown)
+ kill_socket_queues(server);
+
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry_safe(server, nserver, &reco, rlist) {
list_del_init(&server->rlist);
@@ -365,9 +398,10 @@ static bool cifs_tcp_ses_needs_reconnect(struct TCP_Server_Info *server, int num
cifs_dbg(FYI, "Mark tcp session as need reconnect\n");
trace_smb3_reconnect(server->current_mid, server->conn_id,
server->hostname);
- server->tcpStatus = CifsNeedReconnect;
-
spin_unlock(&server->srv_lock);
+
+ set_need_reco(server);
+
return true;
}
diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
index 6e21b5f8754a..c6e0ee6d0ef4 100644
--- a/fs/smb/client/transport.c
+++ b/fs/smb/client/transport.c
@@ -180,6 +180,10 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
*/
rc = sock_sendmsg(ssocket, smb_msg);
if (rc == -EAGAIN || unlikely(rc == -EINTR && task_work_pending(current))) {
+ /* Don't retry if need to reconnect */
+ if (unlikely(server->tcpStatus == CifsNeedReconnect))
+ return -ECONNRESET;
+
retries++;
if (retries >= 14 ||
(!server->noblocksnd && (retries > 2))) {
@@ -191,6 +195,10 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
continue;
}
+ /* Blame the need to reconnect for any non-interrupt error */
+ if (unlikely(server->tcpStatus == CifsNeedReconnect && !is_interrupt_error(rc)))
+ rc = -ECONNRESET;
+
if (rc < 0)
return rc;
--
2.55.0
next prev parent reply other threads:[~2026-09-28 15:04 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 15:03 [PATCH v2 0/2] reconnect fixes and improvements Enzo Matsumiya
2026-09-28 15:03 ` Enzo Matsumiya [this message]
2026-09-29 4:14 ` [PATCH v2 1/2] smb: client: fast fail sends if need to reconnect Namjae Jeon
2026-09-29 12:25 ` Enzo Matsumiya
2026-09-28 15:03 ` [PATCH v2 2/2] smb: client: prevent premature discard of requests if reconnecting Enzo Matsumiya
2026-10-06 13:49 ` [PATCH v2 0/2] reconnect fixes and improvements Enzo Matsumiya
2026-10-06 15:51 ` Paulo Alcantara
2026-10-06 15:57 ` Enzo Matsumiya
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260928150355.850472-2-ematsumiya@suse.de \
--to=ematsumiya@suse.de \
--cc=bharathsm@microsoft.com \
--cc=henrique.carvalho@suse.com \
--cc=linkinjeon@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=pc@manguebit.org \
--cc=ronniesahlberg@gmail.com \
--cc=sprasad@microsoft.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox