FAILED: patch "[PATCH] cifs: open files should not hold ref on superblock" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 340cea84f691c5206561bb2e0147158fe02070be
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026031715-transform-unroasted-b999@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 340cea84f691c5206561bb2e0147158fe02070be Mon Sep 17 00:00:00 2001
From: Shyam Prasad N <[email protected]>
Date: Wed, 4 Mar 2026 18:15:53 +0530
Subject: [PATCH] cifs: open files should not hold ref on superblock
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
The reasoning for holding the superblock ref was to make sure that when umount happens, if there are users of inodes and dentries, it does not try to clean them up and wait for the last ref to superblock to be dropped by last of such users.
But the side effect of doing that is that umount silently drops a ref on the superblock and we could have deferred closes and lease breaks still holding these refs.
Ideally, we should ensure that all of these users of inodes and dentries are cleaned up at the time of umount, which is what this code is doing.
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. It also waits for oplock_break workers to be flushed before calling kill_anon_super (which eventually frees up those objects).
fs/smb/client/cifsfs.c +5 -2
@@ -332,10 +332,14 @@ 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); + +/* Wait for all pending oplock breaks to complete */ +flush_workqueue (cifsoplockd_wq);/* finally release root dentry */ dput (cifs_sb->root);
@@ -868,7 +872,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) {
fs/smb/client/cifsproto.h +1 -0
@@ -261,6 +261,7 @@ void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);void cifs_close_all_deferred_files (struct cifs_tcon *tcon); +void cifs_close_all_deferred_files_sb (struct cifs_sb_info *cifs_sb);void cifs_close_deferred_file_under_dentry (struct cifs_tcon *tcon,struct dentry *dentry);
fs/smb/client/file.c +0 -11
@@ -711,8 +711,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.
@@ -767,7 +765,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
@@ -785,7 +782,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 );
@@ -3253,7 +3243,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,
fs/smb/client/misc.c +42 -0
54 lines not on this page · raw message
fs/smb/client/trace.h +2 -0
@@ -176,6 +176,7 @@ 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") \ + EM(netfs_trace_tcon_ref_get_close_defer_files, "GET Cl-Def") \ EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \ EM(netfs_trace_tcon_ref_get_find, "GET Find ") \EM (netfs_trace_tcon_ref_get_find_sess_tcon,"GET FndSes" ) \
@@ -187,6 +188,7 @@ 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") \ + EM(netfs_trace_tcon_ref_put_close_defer_files, "PUT Cl-Def") \ EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \ EM(netfs_trace_tcon_ref_put_dfs_refer, "PUT DfsRfr") \EM (netfs_trace_tcon_ref_put_reconnect_server,"PUT Reconn" ) \
Sasha Levin
maintainerPATCH 1/1 cifs: open files should not hold ref on superblock
From: Shyam Prasad N <[email protected]>
[ Upstream commit 340cea84f691c5206561bb2e0147158fe02070be ]
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
The reasoning for holding the superblock ref was to make sure that when umount happens, if there are users of inodes and dentries, it does not try to clean them up and wait for the last ref to superblock to be dropped by last of such users.
But the side effect of doing that is that umount silently drops a ref on the superblock and we could have deferred closes and lease breaks still holding these refs.
Ideally, we should ensure that all of these users of inodes and dentries are cleaned up at the time of umount, which is what this code is doing.
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. It also waits for oplock_break workers to be flushed before calling kill_anon_super (which eventually frees up those objects).
--- fs/cifs/cifsfs.c | 9 ++++++--- fs/cifs/cifsproto.h | 1 + fs/cifs/file.c | 11 ----------- fs/cifs/misc.c | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 14 deletions(-)
fs/cifs/cifsfs.c +6 -3
@@ -262,8 +262,8 @@ static void cifs_kill_sb(struct super_block *sb)struct tcon_link *tlink;/* -* We ned to release all dentries for the cached directories -* before we kill the sb. +* We need to release all dentries for the cached directories +* and close all deferred file handles before we kill the sb. */ if (cifs_sb->root) {for (node =rb_first (root); node; node =rb_next (node)) {
@@ -279,6 +279,10 @@ static void cifs_kill_sb(struct super_block *sb) }mutex_unlock (&cfid->fid_mutex); } +cifs_close_all_deferred_files_sb (cifs_sb); + +/* Wait for all pending oplock breaks to complete */ +flush_workqueue (cifsoplockd_wq);/* finally release root dentry */ dput (cifs_sb->root);
@@ -716,7 +720,6 @@ static void cifs_umount_begin(struct super_block *sb) tcon->tidStatus = CifsExiting;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) {
fs/cifs/cifsproto.h +1 -0
@@ -267,6 +267,7 @@ 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);extern void cifs_close_deferred_file_under_dentry (struct cifs_tcon *cifs_tcon,const char *path);
fs/cifs/file.c +0 -11
@@ -318,8 +318,6 @@ 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.
@@ -374,7 +372,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;cifs_fscache_release_inode_cookie (inode);
@@ -394,7 +391,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); }
@@ -4876,12 +4872,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 );
@@ -4954,7 +4944,6 @@ void cifs_oplock_break(struct work_struct *work)cifs_put_tlink (tlink); out:cifs_done_oplock_break (cinode); -cifs_sb_deactive (sb); }/*
fs/cifs/misc.c +41 -0
53 lines not on this page · raw message
Signature · 1 line
2.51.0