From: nspmangalore@gmail.com
To: linux-cifs@vger.kernel.org, smfrench@gmail.com, pc@manguebit.org,
bharathsm@microsoft.com
Cc: Shyam Prasad N <sprasad@microsoft.com>
Subject: [PATCH] cifs: open files should not hold ref on superblock
Date: Sun, 1 Feb 2026 00:16:36 +0530 [thread overview]
Message-ID: <20260131184656.972897-1-sprasad@microsoft.com> (raw)
From: Shyam Prasad N <sprasad@microsoft.com>
Today whenever we deal with a file, in addition to holding
a reference on the dentry, we also get a reference on the
superblock. This happens in two cases:
1. when a new cinode is allocated
2. when an oplock break is being processed
This code change allows these code paths to use a ref on the
dentry (and hence the inode). That way, umount is
ensured to clean up SMB client resources when it's the last
ref on the superblock (For ex: when same objects are shared).
The code change also moves the call to close all the files in
deferred close list to the umount code path.
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
---
fs/smb/client/cifsfs.c | 4 ++--
fs/smb/client/cifsproto.h | 2 ++
fs/smb/client/connect.c | 2 ++
fs/smb/client/file.c | 11 -----------
fs/smb/client/misc.c | 36 ++++++++++++++++++++++++++++++++++++
5 files changed, 42 insertions(+), 13 deletions(-)
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index a3dc7cb1ab541..277dabd982cbd 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -331,10 +331,11 @@ static void cifs_kill_sb(struct super_block *sb)
/*
* We need to release all dentries for the cached directories
- * before we kill the sb.
+ * and close all deferred file handles before we kill the sb.
*/
if (cifs_sb->root) {
close_all_cached_dirs(cifs_sb);
+ cifs_close_all_deferred_files_sb(cifs_sb);
/* finally release root dentry */
dput(cifs_sb->root);
@@ -865,7 +866,6 @@ static void cifs_umount_begin(struct super_block *sb)
spin_unlock(&tcon->tc_lock);
spin_unlock(&cifs_tcp_ses_lock);
- cifs_close_all_deferred_files(tcon);
/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
/* cancel_notify_requests(tcon); */
if (tcon->ses && tcon->ses->server) {
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index f8c0615d4ee42..5feaeac16b0c5 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -302,6 +302,8 @@ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
+extern void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb);
+
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
struct dentry *dentry);
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index ce620503e9f70..31745ef692390 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -4149,6 +4149,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
if (cifs_sb->master_tlink) {
tcon = cifs_sb->master_tlink->tl_tcon;
if (tcon) {
+ cifs_close_all_deferred_files(tcon);
spin_lock(&tcon->sb_list_lock);
list_del_init(&cifs_sb->tcon_sb_link);
spin_unlock(&tcon->sb_list_lock);
@@ -4163,6 +4164,7 @@ cifs_umount(struct cifs_sb_info *cifs_sb)
rb_erase(node, root);
spin_unlock(&cifs_sb->tlink_tree_lock);
+ cifs_close_all_deferred_files(tlink->tl_tcon);
cifs_put_tlink(tlink);
spin_lock(&cifs_sb->tlink_tree_lock);
}
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index 7ff5cc9c5c5b7..0b80b11a9864d 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -712,8 +712,6 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
mutex_init(&cfile->fh_mutex);
spin_lock_init(&cfile->file_info_lock);
- cifs_sb_active(inode->i_sb);
-
/*
* If the server returned a read oplock and we have mandatory brlocks,
* set oplock level to None.
@@ -768,7 +766,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
struct inode *inode = d_inode(cifs_file->dentry);
struct cifsInodeInfo *cifsi = CIFS_I(inode);
struct cifsLockInfo *li, *tmp;
- struct super_block *sb = inode->i_sb;
/*
* Delete any outstanding lock records. We'll lose them when the file
@@ -786,7 +783,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
cifs_put_tlink(cifs_file->tlink);
dput(cifs_file->dentry);
- cifs_sb_deactive(sb);
kfree(cifs_file->symlink_target);
kfree(cifs_file);
}
@@ -3163,12 +3159,6 @@ void cifs_oplock_break(struct work_struct *work)
__u64 persistent_fid, volatile_fid;
__u16 net_fid;
- /*
- * Hold a reference to the superblock to prevent it and its inodes from
- * being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put()
- * may release the last reference to the sb and trigger inode eviction.
- */
- cifs_sb_active(sb);
wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
TASK_UNINTERRUPTIBLE);
@@ -3241,7 +3231,6 @@ void cifs_oplock_break(struct work_struct *work)
cifs_put_tlink(tlink);
out:
cifs_done_oplock_break(cinode);
- cifs_sb_deactive(sb);
}
static int cifs_swap_activate(struct swap_info_struct *sis,
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
index 9529fa385938e..dfeb1faff8568 100644
--- a/fs/smb/client/misc.c
+++ b/fs/smb/client/misc.c
@@ -28,6 +28,11 @@
#include "fs_context.h"
#include "cached_dir.h"
+struct tcon_list {
+ struct list_head entry;
+ struct cifs_tcon *tcon;
+};
+
/* The xid serves as a useful identifier for each incoming vfs request,
in a similar way to the mid which is useful to track each sent smb,
and CurrentXid can also provide a running counter (although it
@@ -171,6 +176,7 @@ tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
}
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace);
free_cached_dirs(tcon->cfids);
+
atomic_dec(&tconInfoAllocCount);
kfree(tcon->nativeFileSystem);
kfree_sensitive(tcon->password);
@@ -840,6 +846,36 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
}
}
+void cifs_close_all_deferred_files_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(sizeof(*tmp_list), GFP_ATOMIC);
+ if (tmp_list == NULL)
+ break;
+ tmp_list->tcon = tcon;
+ 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) {
+ cifs_close_all_deferred_files(tmp_list->tcon);
+ list_del(&tmp_list->entry);
+ kfree(tmp_list);
+ }
+}
+
void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,
struct dentry *dentry)
{
--
2.43.0
next reply other threads:[~2026-01-31 18:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-31 18:46 nspmangalore [this message]
2026-02-12 15:56 ` [PATCH] cifs: open files should not hold ref on superblock Steve French
2026-02-26 3:19 ` Shyam Prasad N
-- strict thread matches above, loose matches on Subject: below --
2026-03-04 12:45 nspmangalore
2026-03-04 20:17 ` Steve French
2026-03-12 19:58 ` Henrique Carvalho
2026-03-13 5:27 ` Shyam Prasad N
2026-03-13 20:17 ` Henrique Carvalho
2026-03-14 8:37 ` Shyam Prasad N
2026-03-14 22:03 ` Steve French
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=20260131184656.972897-1-sprasad@microsoft.com \
--to=nspmangalore@gmail.com \
--cc=bharathsm@microsoft.com \
--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