From: rajasimandalos@gmail.com
To: linux-cifs@vger.kernel.org
Cc: bharathsm@microsoft.com, msetiya@microsoft.com,
smfrench@gmail.com, sfrench@samba.org, stfrench@microsoft.com,
Rajasi Mandal <rajasimandal@microsoft.com>
Subject: [PATCH 1/9] smb: client: sync runtime state into ctx on reconfigure
Date: Thu, 2 Jul 2026 11:35:27 +0000 [thread overview]
Message-ID: <20260702113535.4044308-2-rajasimandalos@gmail.com> (raw)
In-Reply-To: <20260702113535.4044308-1-rajasimandalos@gmail.com>
From: Rajasi Mandal <rajasimandal@microsoft.com>
smb3_init_fs_context() builds a fresh context with init defaults on
every call, including reconfigure (remount). Many fields displayed
by cifs_show_options() are sourced from tcon/server/ses rather than
from ctx, so the init defaults do not reflect the live mount and
cannot be used as a baseline for comparing new vs old options on
remount.
Detect FS_CONTEXT_FOR_RECONFIGURE in smb3_init_fs_context() and
duplicate the existing cifs_sb->ctx instead. Before duplicating,
sync ctx with runtime state via a new helper
smb3_sync_ctx_from_runtime() so the baseline matches what
cifs_show_options() displays. Add srv_lock / tc_lock around the
relevant runtime writers (SMB2_negotiate, SMB2_tcon,
reset_cifs_unix_caps, cifs_swn_set_server_dstaddr) so the helper
can read them without torn-read races.
Also preserve inherited multichannel/max_channels values in
smb3_handle_conflicting_options() during reconfigure when neither
option is explicitly specified, since the dup'd context already
carries them.
This is preparatory plumbing for a subsequent commit that compares
new_ctx against old_ctx in smb3_verify_reconfigure_ctx() to reject
non-reconfigurable option changes.
Signed-off-by: Rajasi Mandal <rajasimandal@microsoft.com>
Reviewed-by: Meetakshi Setiya <msetiya@microsoft.com>
---
fs/smb/client/cifs_swn.h | 14 ++++-
fs/smb/client/fs_context.c | 111 +++++++++++++++++++++++++++++++++++++
fs/smb/client/smb1ops.c | 7 ++-
fs/smb/client/smb2pdu.c | 11 +++-
4 files changed, 139 insertions(+), 4 deletions(-)
diff --git a/fs/smb/client/cifs_swn.h b/fs/smb/client/cifs_swn.h
index 955d07b69450..caf0779d4d07 100644
--- a/fs/smb/client/cifs_swn.h
+++ b/fs/smb/client/cifs_swn.h
@@ -26,11 +26,21 @@ void cifs_swn_check(void);
static inline bool cifs_swn_set_server_dstaddr(struct TCP_Server_Info *server)
{
+ bool ret = false;
+
+ /*
+ * srv_lock serializes the 128-byte sockaddr_storage write against
+ * concurrent readers (e.g. cifs_show_address(), reconn_set_ipaddr_
+ * from_hostname() snapshot, smb3_sync_ctx_from_runtime()) and other
+ * writers like cifs_chan_update_iface() which already use srv_lock.
+ */
+ spin_lock(&server->srv_lock);
if (server->use_swn_dstaddr) {
server->dstaddr = server->swn_dstaddr;
- return true;
+ ret = true;
}
- return false;
+ spin_unlock(&server->srv_lock);
+ return ret;
}
static inline void cifs_swn_reset_server_dstaddr(struct TCP_Server_Info *server)
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 9addc74ce57e..576a78b6d0cb 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -926,6 +926,81 @@ static void smb3_fs_context_free(struct fs_context *fc)
smb3_cleanup_fs_context(ctx);
}
+/*
+ * Sync cifs_sb->ctx with runtime state from tcon/server/ses so the
+ * baseline matches what cifs_show_options() displays. Wide fields
+ * (dstaddr, ops/vals) are protected by the matching server/tcon lock;
+ * the remaining word-sized scalars rely on the same unsynchronized-read
+ * pattern already used by cifs_show_options().
+ */
+static int smb3_sync_ctx_from_runtime(struct cifs_sb_info *cifs_sb)
+{
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_ses *ses = tcon->ses;
+ struct smb3_fs_context *ctx = cifs_sb->ctx;
+ const char *domain;
+ int unicode;
+
+ /*
+ * Server fields that can drift from ctx after mount:
+ * - ops/vals: dialect renegotiation during reconnect (paired,
+ * so read under srv_lock to match the writer in SMB2_negotiate)
+ * - dstaddr: SWN witness failover updates server->dstaddr; the
+ * 128-byte sockaddr_storage is not atomic, so srv_lock is
+ * required against torn reads
+ * - nosharesock: can be flipped to true post-mount by SMB2_tcon
+ * on STATUS_BAD_NETWORK_NAME with ISOLATED_TRANSPORT, so read
+ * under srv_lock to pair with that writer
+ */
+ spin_lock(&server->srv_lock);
+ ctx->ops = server->ops;
+ ctx->vals = server->vals;
+ ctx->dstaddr = server->dstaddr;
+ ctx->nosharesock = server->nosharesock;
+ spin_unlock(&server->srv_lock);
+
+ /*
+ * tcon->unix_ext can be flipped post-mount by reset_cifs_unix_caps()
+ * on SMB1 reconnect (smb1_reconnect path). Read under tc_lock to pair
+ * with that writer. tcon->posix_extensions is only ever set at
+ * mount-time pre-publish, but read it under the same lock so the
+ * derived linux_ext/no_linux_ext pair is consistent.
+ */
+ spin_lock(&tcon->tc_lock);
+ if (tcon->posix_extensions || tcon->unix_ext) {
+ ctx->linux_ext = 1;
+ ctx->no_linux_ext = 0;
+ } else {
+ ctx->linux_ext = 0;
+ ctx->no_linux_ext = 1;
+ }
+ spin_unlock(&tcon->tc_lock);
+ ctx->seal = tcon->seal;
+ ctx->persistent = tcon->use_persistent;
+ ctx->nopersistent = !tcon->use_persistent;
+ ctx->resilient = tcon->use_resilient;
+ ctx->witness = tcon->use_witness;
+
+ /*
+ * Session fields: domainName and unicode are effectively
+ * write-once (set during session setup, never freed/replaced
+ * while the session exists), so plain reads are safe.
+ */
+ domain = ses->domainName;
+ unicode = ses->unicode;
+
+ if (domain && !ctx->domainname) {
+ ctx->domainname = kstrdup(domain, GFP_KERNEL);
+ if (!ctx->domainname)
+ return -ENOMEM;
+ }
+ if (unicode >= 0)
+ ctx->unicode = unicode;
+
+ return 0;
+}
+
/*
* Compare the old and new proposed context during reconfigure
* and check if the changes are compatible.
@@ -1961,6 +2036,42 @@ int smb3_init_fs_context(struct fs_context *fc)
char *nodename = utsname()->nodename;
int i;
+ /*
+ * For reconfigure (remount), duplicate the existing mount context
+ * instead of building one from scratch with init defaults.
+ *
+ * VFS sets fc->root before calling init_fs_context for reconfigure,
+ * so we can access the existing superblock's context. We first sync
+ * cifs_sb->ctx with runtime state (tcon/server/ses) so that ctx
+ * matches what cifs_show_options() displays. Then we dup old_ctx
+ * into new_ctx. The parser will overwrite only the options
+ * explicitly passed on remount, so any difference between new_ctx
+ * and old_ctx in smb3_verify_reconfigure_ctx() represents a real,
+ * intentional change by the user.
+ */
+ if (fc->purpose == FS_CONTEXT_FOR_RECONFIGURE) {
+ struct cifs_sb_info *cifs_sb = CIFS_SB(fc->root->d_sb);
+ int rc;
+
+ rc = smb3_sync_ctx_from_runtime(cifs_sb);
+ if (rc)
+ return rc;
+
+ ctx = kzalloc_obj(struct smb3_fs_context);
+ if (!ctx)
+ return -ENOMEM;
+
+ rc = smb3_fs_context_dup(ctx, cifs_sb->ctx);
+ if (rc) {
+ kfree(ctx);
+ return rc;
+ }
+
+ fc->fs_private = ctx;
+ fc->ops = &smb3_fs_context_ops;
+ return 0;
+ }
+
ctx = kzalloc_obj(struct smb3_fs_context);
if (unlikely(!ctx))
return -ENOMEM;
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index d34b3d99f6ed..33c890e14988 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -36,11 +36,16 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,
if (ctx && ctx->no_linux_ext) {
tcon->fsUnixInfo.Capability = 0;
+ spin_lock(&tcon->tc_lock);
tcon->unix_ext = 0; /* Unix Extensions disabled */
+ spin_unlock(&tcon->tc_lock);
cifs_dbg(FYI, "Linux protocol extensions disabled\n");
return;
- } else if (ctx)
+ } else if (ctx) {
+ spin_lock(&tcon->tc_lock);
tcon->unix_ext = 1; /* Unix Extensions supported */
+ spin_unlock(&tcon->tc_lock);
+ }
if (!tcon->unix_ext) {
cifs_dbg(FYI, "Unix extensions disabled so not set on reconnect\n");
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 4972cfe249f6..958ca0753774 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -1189,8 +1189,10 @@ SMB2_negotiate(const unsigned int xid,
goto neg_exit;
case SMB311_PROT_ID:
/* ops set to 3.0 by default for default so update */
+ spin_lock(&server->srv_lock);
server->ops = &smb311_operations;
server->vals = &smb311_values;
+ spin_unlock(&server->srv_lock);
break;
default:
break;
@@ -1205,12 +1207,16 @@ SMB2_negotiate(const unsigned int xid,
goto neg_exit;
case SMB21_PROT_ID:
/* ops set to 3.0 by default for default so update */
+ spin_lock(&server->srv_lock);
server->ops = &smb21_operations;
server->vals = &smb21_values;
+ spin_unlock(&server->srv_lock);
break;
case SMB311_PROT_ID:
+ spin_lock(&server->srv_lock);
server->ops = &smb311_operations;
server->vals = &smb311_values;
+ spin_unlock(&server->srv_lock);
break;
default:
break;
@@ -2226,8 +2232,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
if (server->ops->validate_negotiate)
rc = server->ops->validate_negotiate(xid, tcon);
if (rc == 0) /* See MS-SMB2 2.2.10 and 3.2.5.5 */
- if (tcon->share_flags & SMB2_SHAREFLAG_ISOLATED_TRANSPORT)
+ if (tcon->share_flags & SMB2_SHAREFLAG_ISOLATED_TRANSPORT) {
+ spin_lock(&server->srv_lock);
server->nosharesock = true;
+ spin_unlock(&server->srv_lock);
+ }
tcon_exit:
free_rsp_buf(resp_buftype, rsp);
--
2.43.0
next prev parent reply other threads:[~2026-07-02 11:35 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 11:35 [PATCH RESEND 0/9] smb: client: remount reconfigure option fixes rajasimandalos
2026-07-02 11:35 ` rajasimandalos [this message]
2026-07-02 11:35 ` [PATCH 2/9] smb: client: block non-reconfigurable option changes on remount rajasimandalos
2026-07-02 11:35 ` [PATCH 3/9] smb: client: sync retrans " rajasimandalos
2026-07-02 11:35 ` [PATCH 4/9] smb: client: block cache=ro and cache=singleclient " rajasimandalos
2026-07-02 11:35 ` [PATCH 5/9] smb: client: apply rasize " rajasimandalos
2026-07-02 11:35 ` [PATCH 6/9] smb: client: move struct tcon_list to cifsglob.h rajasimandalos
2026-07-02 11:35 ` [PATCH 7/9] smb: client: allow nolease option to be reconfigured on remount rajasimandalos
2026-07-02 11:35 ` [PATCH 8/9] smb: client: review fixes for remount ctx/retrans sync (patches 1-4) rajasimandalos
2026-07-02 11:35 ` [PATCH 9/9] smb: client: review fixes for nolease remount (patch 7) rajasimandalos
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=20260702113535.4044308-2-rajasimandalos@gmail.com \
--to=rajasimandalos@gmail.com \
--cc=bharathsm@microsoft.com \
--cc=linux-cifs@vger.kernel.org \
--cc=msetiya@microsoft.com \
--cc=rajasimandal@microsoft.com \
--cc=sfrench@samba.org \
--cc=smfrench@gmail.com \
--cc=stfrench@microsoft.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.