From nobody Sat Feb 7 19:41:02 2026 Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0AAE33A714 for ; Tue, 23 Dec 2025 12:43:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766493828; cv=none; b=hKsBAWMleL5ax0xVtxfkvlcAn1h+jQsIYkttEut4E6fJW5FWMv0pSYU4fgU9k5yZw0En4yEyJWN32Qt9jULftjBu1EUUiaUgbtmD7L9Knw+N+zM7VFwQSFgq9vG9WAY26bT2nZf+GR7QcP5pazbc/sDS2QY8FYOcJcQ61omFGyg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766493828; c=relaxed/simple; bh=kPNVdp0GBSCF292ESsYylSmdqGIcAxgtfQAGeVTeIXg=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=US9FZ/b0fgBYz8mXIKQmsrxl6ZybVPII5eM4N3OqJpcBaYn0+Pr6fIWAvXFm0eoXowDrXtxqqKhgwyn5Yjo1sxAcStIEvena6+ig4Vfe0/X03s9Kmzk6UKmGDHWa9QLLJzTbE/BrtSWoXXGxuPXCnGCZ/Es47jNWE1J4NyHCrpY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=D5CFwY3V; arc=none smtp.client-ip=209.85.216.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="D5CFwY3V" Received: by mail-pj1-f47.google.com with SMTP id 98e67ed59e1d1-34c3259da34so4914015a91.2 for ; Tue, 23 Dec 2025 04:43:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1766493826; x=1767098626; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=n9xfB6bM1Z+7QU2e/goT4Iic+k1CppgxDaL2ZCQcvYg=; b=D5CFwY3VAXi05ei1ReFcgxojiZnokBvWuEwJqzSnrTUIT4XGqkMv6RfRtzWkldwQKV J2bXonFBAU75QUsogplhcL6eeDFxjWQq30Hji9zEICrU52AwWPTxqsY81vmOgUkwXfuk RL4vw+QZ5Ys5FbwjlhB+/toMFhWJzsLmwkiJh0edfXsBpZJH1mEBia/v/7d7KSqmXyrG hVTvqLhSd6lab0U1mHZ/Gsim2+F+kNfRyw4V0YqqVFQOu4+vJUIcuK6HjkroPsvt8vmZ yYFWR+cPtjbax6q8QuLljELlThTwOYV6qIndSrTFxdmpreoLn1hdUe64MV0S9PSnTGAl 7Vqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1766493826; x=1767098626; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=n9xfB6bM1Z+7QU2e/goT4Iic+k1CppgxDaL2ZCQcvYg=; b=k1yHopo4z7vEGPt7hbW52GiAB3owPJwTMVGz7ji3OYZ5YiwYHrp3BkG7ScNjrSAMIx Dls487OM5fGJ4nsxTPwswU7Q8MJQeQ2kJHHHaw++HGmGjlqzEnmGhaS9jHCWzujrnX+8 PoIBpkcSjmSCeNAnUMxjClR1r/5DbfVFIH/fV2066NMINY8W9PIF6n/NmVvjmrpn72Xy JFVWDFk//yYtAgeappCuy5qdWzBIS9TDRfnNoynPqOKNpBIlWUVlRnsy9jc6i639j7Od pRKiiYMAaYqEfLP2NeQrh3Y8NQzmOCSwE25vArs5IpF9+P0QT0OQRzFoCOJXQbX2l4i1 XiqA== X-Forwarded-Encrypted: i=1; AJvYcCWji7ABC0M4vNt9EINFiY459k5pkKohS3XvvDRjKvMeF+aK1Wf7IPcUUmDmOlHg1pWbkTF2nw5swjUZ4wQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwnXlFEnFTbZmevXg15djHKA+71UB9FSrnRhAvrpFWGwAFJ8jyi xn5qgXD1f+zvlyKX9KlaFbPJZ5ZAA+XbyfCxyp/Ak6h0+pEICL4qiESC X-Gm-Gg: AY/fxX6nWgykOIKXuKtD3/X+5fSpEsBznOIVUEHD0EjrivCzN6x/RVCFbXnchJYh3l1 Zg6NW7WaB0cqyy1TgEXxY2WtU0Ny32ERVcs2nA/DJ2iU6jTk3+1VsNCuUWnxD+YMN6MH5mJw5dp QtLJ70pDlA9HfkiCptScQ2G+LVQ9pTbRcgaHEx/Y7EXxOdFhOHmuwIToM8rMVJI+T01XGgBZEB3 Y5bo4PTMBnfIUC7UlkHDvW0jY7zq1ReANi8jTV5D49iU3ujZ4tI2QGoVm20hqzVxW5IBQI/AJmc SzIGGD9fILMQum8rXQUZA3P64OCcnkFYkPrtn7ymC3NuhuhPGW/xCUepuOOi+LG7PmGkclNuLbC ypOIx9Yn8y01sEeEud+sRbk3teCjC+V7+2kVhnLi51aZlNmBqrrdd+wuz8C2qRgC/i7jaZDrCRV YUruxriMnVm5YQ/7kIIGxuhJ2sPOQgHTWl X-Google-Smtp-Source: AGHT+IEaFjA9v+EGIAoGfDWVvHiWVW2eowhdPUVTkzF3db83+cxFxSZ1FxpHKpAkokMdTpM9NMDAbQ== X-Received: by 2002:a17:90b:590b:b0:32d:dc3e:5575 with SMTP id 98e67ed59e1d1-34e9212a396mr11211228a91.5.1766493825919; Tue, 23 Dec 2025 04:43:45 -0800 (PST) Received: from archlinuxms.domain.name ([2401:4900:1cc4:6259:9219:dc3e:6361:833a]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c1e7961b4d0sm11815288a12.5.2025.12.23.04.43.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 23 Dec 2025 04:43:45 -0800 (PST) From: Piyush Sachdeva To: sfrench@samba.org, linux-cifs@vger.kernel.org, linux-kernel@vger.kernel.org Cc: sprasad@microsoft.com, bharathsm@microsoft.com, msetiya@microsoft.com, rajasimandal@microsoft.com, psachdeva@microsoft.com, Piyush Sachdeva Subject: [PATCH] smb: client: close all files marked for deferred close immediately Date: Tue, 23 Dec 2025 18:11:19 +0530 Message-ID: <20251223124119.1383159-1-s.piyush1024@gmail.com> X-Mailer: git-send-email 2.52.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Piyush Sachdeva SMB client has a feature to delay the close of a file on the server, expecting if an open call comes for the same file, the file doesn't need to be re-opened. The time duration of the deferred close is set by the mount option `closetimeo`. This patch lets a user list all handles marked for deferred close, by cat /proc/fs/cifs/close_deferred_closes. It also allow for force close of all files marked for deferred close, across all session by writing a non-zero value to the same procfs file. Signed-off-by: Piyush Sachdeva Signed-off-by: Piyush Sachdeva --- fs/smb/client/cifs_debug.c | 137 +++++++++++++++++++++++++++++++++++++ fs/smb/client/cifsglob.h | 5 ++ 2 files changed, 142 insertions(+) diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c index 7fdcaf9feb16..e149a403b16e 100644 --- a/fs/smb/client/cifs_debug.c +++ b/fs/smb/client/cifs_debug.c @@ -952,6 +952,7 @@ static const struct proc_ops traceSMB_proc_ops; static const struct proc_ops cifs_security_flags_proc_ops; static const struct proc_ops cifs_linux_ext_proc_ops; static const struct proc_ops cifs_mount_params_proc_ops; +static const struct proc_ops close_all_deferred_close_ops; =20 void cifs_proc_init(void) @@ -981,6 +982,8 @@ cifs_proc_init(void) =20 proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_o= ps); =20 + proc_create("close_deferred_closes", 0644, proc_fs_cifs, &close_all_defer= red_close_ops); + #ifdef CONFIG_CIFS_DFS_UPCALL proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops); #endif @@ -1021,6 +1024,7 @@ cifs_proc_clean(void) remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); remove_proc_entry("mount_params", proc_fs_cifs); + remove_proc_entry("close_deferred_closes", proc_fs_cifs); =20 #ifdef CONFIG_CIFS_DFS_UPCALL remove_proc_entry("dfscache", proc_fs_cifs); @@ -1317,6 +1321,139 @@ static const struct proc_ops cifs_mount_params_proc= _ops =3D { /* .proc_write =3D cifs_mount_params_proc_write, */ }; =20 +static struct list_head *get_all_tcons(void) +{ + struct TCP_Server_Info *server; + struct cifs_ses *ses; + struct cifs_tcon *tcon; + struct global_tcon_list *tree_con_list, *tmp_tree_con_list; + struct list_head *tcon_head; + + tcon_head =3D kmalloc(sizeof(struct list_head), GFP_KERNEL); + if (tcon_head =3D=3D NULL) + return NULL; + + INIT_LIST_HEAD(tcon_head); + spin_lock(&cifs_tcp_ses_lock); + list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { + if (cifs_ses_exiting(ses)) + continue; + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { + tree_con_list =3D + kmalloc(sizeof(struct global_tcon_list), + GFP_ATOMIC); + if (tree_con_list =3D=3D NULL) + goto tcon_alloc_fail; + tree_con_list->tcon =3D tcon; + list_add_tail(&tree_con_list->list, tcon_head); + } + } + } + spin_unlock(&cifs_tcp_ses_lock); + return tcon_head; + +tcon_alloc_fail: + spin_unlock(&cifs_tcp_ses_lock); + list_for_each_entry_safe(tree_con_list, tmp_tree_con_list, tcon_head, + list) { + list_del(&tree_con_list->list); + kfree(tree_con_list); + } + kfree(tcon_head); + return NULL; +} + +static ssize_t close_all_deferred_close_files(struct file *file, + const char __user *buffer, + size_t count, loff_t *ppos) +{ + char c; + int rc; + struct global_tcon_list *tmp_list, *tmp_next_list; + struct list_head *tcon_head; + + rc =3D get_user(c, buffer); + if (rc) + return rc; + if (c =3D=3D '0') + return -EINVAL; + + tcon_head =3D get_all_tcons(); + if (tcon_head =3D=3D NULL) + return count; + + list_for_each_entry_safe(tmp_list, tmp_next_list, tcon_head, list) { + cifs_close_all_deferred_files(tmp_list->tcon); + list_del(&tmp_list->list); + kfree(tmp_list); + } + + kfree(tcon_head); + return count; +} + +static int show_all_deferred_close_files(struct seq_file *m, void *v) +{ + struct global_tcon_list *tmp_list, *tmp_next_list; + struct list_head *tcon_head; + struct cifs_tcon *tcon; + struct cifsFileInfo *cfile; + + seq_puts(m, "# Version:1\n"); + seq_puts(m, "# Format:\n"); + seq_puts(m, "# = "); +#ifdef CONFIG_CIFS_DEBUG2 + seq_puts(m, " \n"); +#else + seq_puts(m, " \n"); +#endif /* CIFS_DEBUG2 */ + + tcon_head =3D get_all_tcons(); + if (tcon_head =3D=3D NULL) + return 0; + + list_for_each_entry_safe(tmp_list, tmp_next_list, tcon_head, list) { + tcon =3D tmp_list->tcon; + spin_lock(&tcon->open_file_lock); + list_for_each_entry(cfile, &tcon->openFileList, tlist) { + if (delayed_work_pending(&cfile->deferred)) { + seq_printf( + m, + "0x%x 0x%llx 0x%llx 0x%x %d %d %d %pd", + tcon->tid, tcon->ses->Suid, + cfile->fid.persistent_fid, + cfile->f_flags, cfile->count, + cfile->pid, + from_kuid(&init_user_ns, cfile->uid), + cfile->dentry); + } + } + spin_unlock(&tcon->open_file_lock); + list_del(&tmp_list->list); + kfree(tmp_list); + } + + kfree(tcon_head); + seq_putc(m, '\n'); + + return 0; +} + +static int show_all_deferred_close_proc_open(struct inode *inode, + struct file *file) +{ + return single_open(file, show_all_deferred_close_files, NULL); +} + +static const struct proc_ops close_all_deferred_close_ops =3D { + .proc_open =3D show_all_deferred_close_proc_open, + .proc_read =3D seq_read, + .proc_lseek =3D seq_lseek, + .proc_release =3D single_release, + .proc_write =3D close_all_deferred_close_files, +}; + #else inline void cifs_proc_init(void) { diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index 203e2aaa3c25..56c987258c4b 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1806,6 +1806,11 @@ struct dfs_info3_param { int ttl; }; =20 +struct global_tcon_list { + struct list_head list; + struct cifs_tcon *tcon; +}; + struct file_list { struct list_head list; struct cifsFileInfo *cfile; --=20 2.52.0