]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
cifs: Fix busy dentry used after unmounting
authorZhihao Cheng <chengzhihao1@huawei.com>
Tue, 19 May 2026 09:18:05 +0000 (17:18 +0800)
committerSteve French <stfrench@microsoft.com>
Thu, 21 May 2026 14:29:37 +0000 (09:29 -0500)
Since commit 340cea84f691c ("cifs: open files should not hold ref on
superblock"), cifs file only holds the dentry ref_cnt, the cifs file
close work(cfile->deferred) could be executed after unmounting, which
will trigger a warning in generic_shutdown_super:
 BUG: Dentry 00000000a14a6845{i=c,n=file}  still in use (1) [unmount of
 cifs cifs]

The detailed processs is:
   process A           process B           kworker
 fd = open(PATH)
  vfs_open
   file->__f_path = *path // dentry->d_lockref.count = 1
   cifs_open
    cifs_new_fileinfo
     cfile->dentry = dget(dentry) // dentry->d_lockref.count = 2
 close(fd)
  __fput
  cifs_close
   queue_delayed_work(deferredclose_wq, cfile->deferred)
  dput(dentry) // dentry->d_lockref.count = 1
                 smb2_deferred_work_close
  _cifsFileInfo_put
   list_del(&cifs_file->flist)
                    umount
     cleanup_mnt
      deactivate_super
       cifs_kill_sb
        cifs_close_all_deferred_files_sb
 cifs_close_all_deferred_files
  // cannot find cfile, skip _cifsFileInfo_put
kill_anon_super
 generic_shutdown_super
  shrink_dcache_for_umount
   umount_check
    WARN ! // dentry->d_lockref.count = 1
   cifsFileInfo_put_final
    dput(cifs_file->dentry)
                            // dentry->d_lockref.count = 0

Fix it by flushing 'deferredclose_wq' before calling kill_anon_super.

Fetch a reproducer in https://bugzilla.kernel.org/show_bug.cgi?id=221548.

Fixes: 340cea84f691c ("cifs: open files should not hold ref on superblock")
Cc: stable@vger.kernel.org
Reviewed-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/cifsfs.c

index 9f76b0347fa9d71df496eb2584b92f0759931069..06ebad58be0ee6bd88c3353b3cd324a8967b79f3 100644 (file)
@@ -306,6 +306,8 @@ static void cifs_kill_sb(struct super_block *sb)
 
                /* Wait for all pending oplock breaks to complete */
                flush_workqueue(cifsoplockd_wq);
+               /* Wait for all opened files to release */
+               flush_workqueue(deferredclose_wq);
 
                /* finally release root dentry */
                dput(cifs_sb->root);