diff mbox series

[next,3/3] smb: client: Update IO sizes after reconnection

Message ID 20250331133315.117666-4-wangzhaolong1@huawei.com (mailing list archive)
State New
Headers show
Series smb: client: Improve IO parameter resilience after reconnection | expand

Commit Message

Wang Zhaolong March 31, 2025, 1:33 p.m. UTC
When a SMB connection is reset and reconnected, the negotiated IO
parameters (rsize/wsize) can become out of sync with the server's
current capabilities. This can lead to suboptimal performance or
even IO failures if the server's limits have changed.

This patch implements automatic IO size renegotiation:
1. Adds cifs_renegotiate_iosize() function to update all superblocks
   associated with a tree connection
2. Updates each mount's rsize/wsize based on current server capabilities
3. Calls this function after successful tree connection reconnection

With this change, all mount points will automatically maintain optimal
and reliable IO parameters after network disruptions, using the
bidirectional mapping added in previous patches.

This completes the series improving connection resilience by keeping
mount parameters synchronized with server capabilities.

Signed-off-by: Wang Zhaolong <wangzhaolong1@huawei.com>
---
 fs/smb/client/smb2pdu.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index f9c521b3c65e..103319cdce00 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -41,10 +41,11 @@ 
 #ifdef CONFIG_CIFS_DFS_UPCALL
 #include "dfs_cache.h"
 #endif
 #include "cached_dir.h"
 #include "compress.h"
+#include "fs_context.h"
 
 /*
  *  The following table defines the expected "StructureSize" of SMB2 requests
  *  in order by SMB2 command.  This is similar to "wct" in SMB/CIFS requests.
  *
@@ -4089,10 +4090,28 @@  smb2_echo_callback(struct mid_q_entry *mid)
 
 	release_mid(mid);
 	add_credits(server, &credits, CIFS_ECHO_OP);
 }
 
+static void cifs_renegotiate_iosize(struct TCP_Server_Info *server,
+				    struct cifs_tcon *tcon)
+{
+	struct cifs_sb_info *cifs_sb;
+
+	if (server == NULL || tcon == NULL)
+		return;
+
+	spin_lock(&tcon->sb_list_lock);
+	list_for_each_entry(cifs_sb, &tcon->cifs_sb_list, tcon_sb_link) {
+		cifs_sb->ctx->rsize =
+			server->ops->negotiate_rsize(tcon, cifs_sb->ctx);
+		cifs_sb->ctx->wsize =
+			server->ops->negotiate_wsize(tcon, cifs_sb->ctx);
+	}
+	spin_unlock(&tcon->sb_list_lock);
+}
+
 void smb2_reconnect_server(struct work_struct *work)
 {
 	struct TCP_Server_Info *server = container_of(work,
 					struct TCP_Server_Info, reconnect.work);
 	struct TCP_Server_Info *pserver;
@@ -4174,13 +4193,14 @@  void smb2_reconnect_server(struct work_struct *work)
 	}
 	spin_unlock(&cifs_tcp_ses_lock);
 
 	list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
 		rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server, true);
-		if (!rc)
+		if (!rc) {
+			cifs_renegotiate_iosize(server, tcon);
 			cifs_reopen_persistent_handles(tcon);
-		else
+		} else
 			resched = true;
 		list_del_init(&tcon->rlist);
 		if (tcon->ipc)
 			cifs_put_smb_ses(tcon->ses);
 		else