From: rajasimandalos@gmail.com
To: linux-cifs@vger.kernel.org
Cc: smfrench@gmail.com, pc@manguebit.org, sprasad@microsoft.com,
bharathsm@microsoft.com, enzo@kernel.org
Subject: [PATCH v2 6/8] smb: client: allow nolease option to be reconfigured on remount
Date: Thu, 7 May 2026 13:44:46 +0000 [thread overview]
Message-ID: <20260507134448.168602-7-rajasimandalos@gmail.com> (raw)
In-Reply-To: <20260507134448.168602-1-rajasimandalos@gmail.com>
From: Rajasi Mandal <rajasimandal@microsoft.com>
Changing nolease via remount is silently accepted but has no effect:
the value is not propagated to the live tcon, and stale lease-bearing
state from before the switch keeps using the old behavior.
Make nolease take effect on remount:
- Propagate ctx->no_lease to tcon->no_lease in smb3_sync_tcon_opts()
so future opens honor the new setting.
- On switch to nolease, drop deferred file handles via
cifs_close_all_deferred_files_sb() (each holds an active lease).
- On switch to nolease, evict cached directory fids via the new
invalidate_all_cached_dirs_sb() helper (each holds a directory
lease).
invalidate_all_cached_dirs_sb() mirrors cifs_close_all_deferred_files_sb():
take tc_count refs on every tcon under tlink_tree_lock, drop the lock,
then call invalidate_all_cached_dirs() per tcon (it can sleep). Two
new tcon_ref trace tags are added for the audit trail.
Existing open handles keep their leases until the server breaks them
or userspace closes the file -- nolease only governs new opens.
Signed-off-by: Rajasi Mandal <rajasimandal@microsoft.com>
---
fs/smb/client/cached_dir.c | 44 ++++++++++++++++++++++++++++++++++++++
fs/smb/client/cached_dir.h | 1 +
fs/smb/client/fs_context.c | 22 +++++++++++++++++++
fs/smb/client/trace.h | 2 ++
4 files changed, 69 insertions(+)
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index 88d5e9a32f28..58d68a8f4d41 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -637,6 +637,50 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon, bool sync)
flush_delayed_work(&cfids->laundromat_work);
}
+/*
+ * Invalidate cached directory entries across all tcons under a
+ * superblock. Collect references on each tcon under tlink_tree_lock,
+ * then call invalidate_all_cached_dirs() outside the spinlock since it
+ * can sleep. Holding a tc_count reference prevents the tcon from being
+ * freed by tlink_expire_delayed() between dropping the spinlock and
+ * the call.
+ */
+void invalidate_all_cached_dirs_sb(struct cifs_sb_info *cifs_sb)
+{
+ struct rb_root *root = &cifs_sb->tlink_tree;
+ struct rb_node *node;
+ struct cifs_tcon *tcon;
+ struct tcon_link *tlink;
+ struct tcon_list *tmp_list, *q;
+ LIST_HEAD(tcon_head);
+
+ spin_lock(&cifs_sb->tlink_tree_lock);
+ for (node = rb_first(root); node; node = rb_next(node)) {
+ tlink = rb_entry(node, struct tcon_link, tl_rbnode);
+ tcon = tlink_tcon(tlink);
+ if (IS_ERR(tcon))
+ continue;
+ tmp_list = kmalloc_obj(struct tcon_list, GFP_ATOMIC);
+ if (!tmp_list)
+ break;
+ tmp_list->tcon = tcon;
+ spin_lock(&tcon->tc_lock);
+ ++tcon->tc_count;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_cached_inval_sb);
+ spin_unlock(&tcon->tc_lock);
+ list_add_tail(&tmp_list->entry, &tcon_head);
+ }
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ list_for_each_entry_safe(tmp_list, q, &tcon_head, entry) {
+ invalidate_all_cached_dirs(tmp_list->tcon, true);
+ list_del(&tmp_list->entry);
+ cifs_put_tcon(tmp_list->tcon, netfs_trace_tcon_ref_put_cached_inval_sb);
+ kfree(tmp_list);
+ }
+}
+
static void
cached_dir_offload_close(struct work_struct *work)
{
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index fc756836da95..606ba2a0b64f 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -90,6 +90,7 @@ void close_cached_dir(struct cached_fid *cfid);
void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
const char *name, struct cifs_sb_info *cifs_sb);
void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
+void invalidate_all_cached_dirs_sb(struct cifs_sb_info *cifs_sb);
void invalidate_all_cached_dirs(struct cifs_tcon *tcon, bool sync);
bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 972d3969f7e7..01c57adb0ef1 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -35,6 +35,7 @@
#include "nterr.h"
#include "rfc1002pdu.h"
#include "fs_context.h"
+#include "cached_dir.h"
DEFINE_MUTEX(cifs_mount_mutex);
@@ -1286,6 +1287,7 @@ static void smb3_sync_tcon_opts(struct cifs_sb_info *cifs_sb,
spin_lock(&tcon->tc_lock);
tcon->retry = ctx->retry;
+ tcon->no_lease = ctx->no_lease;
/*
* Note: this updates the limit for new cached dir opens
* but does not resize or evict existing cached dirents.
@@ -1294,6 +1296,26 @@ static void smb3_sync_tcon_opts(struct cifs_sb_info *cifs_sb,
spin_unlock(&tcon->tc_lock);
}
spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ /*
+ * When switching to nolease, close deferred file handles and
+ * invalidate cached directory entries. Both hold leases from
+ * before the switch; without cleaning them up, those handles
+ * continue using lease-based caching despite nolease being set.
+ *
+ * Note: files already open with leases (e.g. RWH) by applications
+ * are not affected -- nolease only governs new opens. Existing
+ * handles retain their leases until the server sends a lease break
+ * or the application closes the handle.
+ *
+ * Both _sb() helpers iterate all tcons internally and handle
+ * their own locking. They can sleep, so they must be called
+ * outside tlink_tree_lock.
+ */
+ if (ctx->no_lease) {
+ cifs_close_all_deferred_files_sb(cifs_sb);
+ invalidate_all_cached_dirs_sb(cifs_sb);
+ }
}
/*
diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h
index b99ec5a417fa..cec34e69e191 100644
--- a/fs/smb/client/trace.h
+++ b/fs/smb/client/trace.h
@@ -173,6 +173,7 @@
EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \
EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \
EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \
+ EM(netfs_trace_tcon_ref_get_cached_inval_sb, "GET Ch-IvS") \
EM(netfs_trace_tcon_ref_get_cached_laundromat, "GET Ch-Lau") \
EM(netfs_trace_tcon_ref_get_cached_lease_break, "GET Ch-Lea") \
EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \
@@ -185,6 +186,7 @@
EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \
EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \
EM(netfs_trace_tcon_ref_put_cached_close, "PUT Ch-Cls") \
+ EM(netfs_trace_tcon_ref_put_cached_inval_sb, "PUT Ch-IvS") \
EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \
EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \
--
2.43.0
next prev parent reply other threads:[~2026-05-07 13:45 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-07 13:44 [PATCH v2 0/8] Remount patches v2 rajasimandalos
2026-05-07 13:44 ` [PATCH v2 1/8] smb: client: block non-reconfigurable option changes on remount rajasimandalos
2026-05-07 13:44 ` [PATCH v2 2/8] smb: client: sync tcon-level options " rajasimandalos
2026-05-07 13:44 ` [PATCH v2 3/8] smb: client: sync retrans " rajasimandalos
2026-05-07 13:44 ` [PATCH v2 4/8] smb: client: sync echo_interval " rajasimandalos
2026-05-07 13:44 ` [PATCH v2 5/8] smb: client: move struct tcon_list to cifsglob.h rajasimandalos
2026-05-07 13:44 ` rajasimandalos [this message]
2026-05-07 13:44 ` [PATCH v2 7/8] smb: client: block cache=ro and cache=singleclient on remount rajasimandalos
2026-05-07 13:44 ` [PATCH v2 8/8] smb: client: apply rasize " 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=20260507134448.168602-7-rajasimandalos@gmail.com \
--to=rajasimandalos@gmail.com \
--cc=bharathsm@microsoft.com \
--cc=enzo@kernel.org \
--cc=linux-cifs@vger.kernel.org \
--cc=pc@manguebit.org \
--cc=smfrench@gmail.com \
--cc=sprasad@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox