mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-01-15 17:52:05 +03:00
linux/super: add tunable to request immediate reclaim of unused dentries
Traditionally, unused dentries would be cached in the dentry cache until the associated entry is no longer on disk. The cached dentry continues to hold an inode reference, causing the inode to be pinned (see previous commit). Here we implement the dentry op d_delete, which is roughly analogous to the drop_inode superblock op, and add a zfs_delete_dentry tunable to control its behaviour. By default it continues the traditional behaviour, but when the tunable is enabled, we signal that an unused dentry should be freed immediately, releasing its inode reference, and so allowing that inode to be deleted if no longer in use. Sponsored-by: Klara, Inc. Sponsored-by: Fastmail Pty Ltd Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <alexander.motin@TrueNAS.com> Signed-off-by: Rob Norris <rob.norris@klarasystems.com> Closes #17746
This commit is contained in:
parent
42b9995f88
commit
15a6b982c5
@ -46,12 +46,37 @@ AC_DEFUN([ZFS_AC_KERNEL_D_SET_D_OP], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.17 API change
|
||||
dnl # sb->s_d_op removed; set_default_d_op(sb, dop) added
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_SET_DEFAULT_D_OP], [
|
||||
ZFS_LINUX_TEST_SRC([set_default_d_op], [
|
||||
#include <linux/dcache.h>
|
||||
], [
|
||||
set_default_d_op(NULL, NULL);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SET_DEFAULT_D_OP], [
|
||||
AC_MSG_CHECKING([whether set_default_d_op() is available])
|
||||
ZFS_LINUX_TEST_RESULT([set_default_d_op], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_SET_DEFAULT_D_OP, 1,
|
||||
[Define if set_default_d_op() is available])
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_DENTRY], [
|
||||
ZFS_AC_KERNEL_SRC_D_OBTAIN_ALIAS
|
||||
ZFS_AC_KERNEL_SRC_D_SET_D_OP
|
||||
ZFS_AC_KERNEL_SRC_SET_DEFAULT_D_OP
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_DENTRY], [
|
||||
ZFS_AC_KERNEL_D_OBTAIN_ALIAS
|
||||
ZFS_AC_KERNEL_D_SET_D_OP
|
||||
ZFS_AC_KERNEL_SET_DEFAULT_D_OP
|
||||
])
|
||||
|
||||
@ -55,6 +55,7 @@ extern const struct file_operations zpl_dir_file_operations;
|
||||
extern void zpl_prune_sb(uint64_t nr_to_scan, void *arg);
|
||||
|
||||
extern const struct super_operations zpl_super_operations;
|
||||
extern const struct dentry_operations zpl_dentry_operations;
|
||||
extern const struct export_operations zpl_export_operations;
|
||||
extern struct file_system_type zpl_fs_type;
|
||||
|
||||
|
||||
@ -2604,6 +2604,28 @@ frequently evicted and reloaded.
|
||||
.Pp
|
||||
This parameter is only available on Linux.
|
||||
.
|
||||
.It Sy zfs_delete_dentry Ns = Ns Sy 0 Ns | Ns 1 Pq int
|
||||
Sets whether the kernel should free a dentry structure when it is no longer
|
||||
required, or hold it in the dentry cache.
|
||||
Intended for testing/debugging.
|
||||
.
|
||||
Since a dentry structure holds an inode reference, a cached dentry can "pin"
|
||||
an inode in memory indefinitely, along with associated OpenZFS structures (See
|
||||
.Sy zfs_delete_inode ) .
|
||||
.Pp
|
||||
The default value of
|
||||
.Sy 0
|
||||
instructs the kernel to cache entries and their associated inodes when they
|
||||
are no longer directly referenced.
|
||||
They will be reclaimed as part of the kernel's normal cache management
|
||||
processes.
|
||||
Setting it to
|
||||
.Sy 1
|
||||
will instruct the kernel to release directory entries and their inodes as soon
|
||||
as they are no longer referenced by the filesystem.
|
||||
.Pp
|
||||
This parameter is only available on Linux.
|
||||
.
|
||||
.It Sy zio_taskq_batch_pct Ns = Ns Sy 80 Ns % Pq uint
|
||||
Percentage of online CPUs which will run a worker thread for I/O.
|
||||
These workers are responsible for I/O work such as compression, encryption,
|
||||
|
||||
@ -1556,6 +1556,12 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
|
||||
sb->s_xattr = zpl_xattr_handlers;
|
||||
sb->s_export_op = &zpl_export_operations;
|
||||
|
||||
#ifdef HAVE_SET_DEFAULT_D_OP
|
||||
set_default_d_op(sb, &zpl_dentry_operations);
|
||||
#else
|
||||
sb->s_d_op = &zpl_dentry_operations;
|
||||
#endif
|
||||
|
||||
/* Set features for file system. */
|
||||
zfs_set_fuid_feature(zfsvfs);
|
||||
|
||||
|
||||
@ -41,6 +41,14 @@
|
||||
*/
|
||||
int zfs_delete_inode = 0;
|
||||
|
||||
/*
|
||||
* What to do when the last reference to a dentry is released. If 0, the kernel
|
||||
* will cache it until the entry (file) is destroyed. If 1, the dentry will be
|
||||
* marked for cleanup, at which time its inode reference will be released. See
|
||||
* zpl_dentry_delete().
|
||||
*/
|
||||
int zfs_delete_dentry = 0;
|
||||
|
||||
static struct inode *
|
||||
zpl_inode_alloc(struct super_block *sb)
|
||||
{
|
||||
@ -513,6 +521,35 @@ const struct super_operations zpl_super_operations = {
|
||||
.show_stats = NULL,
|
||||
};
|
||||
|
||||
/*
|
||||
* ->d_delete() is called when the last reference to a dentry is released. Its
|
||||
* return value indicates if the dentry should be destroyed immediately, or
|
||||
* retained in the dentry cache.
|
||||
*
|
||||
* By default (zfs_delete_dentry=0) the kernel will always cache unused
|
||||
* entries. Each dentry holds an inode reference, so cached dentries can hold
|
||||
* the final inode reference indefinitely, leading to the inode and its related
|
||||
* data being pinned (see zpl_drop_inode()).
|
||||
*
|
||||
* When set to 1, we signal that the dentry should be destroyed immediately and
|
||||
* never cached. This reduces memory usage, at the cost of higher overheads to
|
||||
* lookup a file, as the inode and its underlying data (dnode/dbuf) need to be
|
||||
* reloaded and reinflated.
|
||||
*
|
||||
* Note that userspace does not have direct control over dentry references and
|
||||
* reclaim; rather, this is part of the kernel's caching and reclaim subsystems
|
||||
* (eg vm.vfs_cache_pressure).
|
||||
*/
|
||||
static int
|
||||
zpl_dentry_delete(const struct dentry *dentry)
|
||||
{
|
||||
return (zfs_delete_dentry ? 1 : 0);
|
||||
}
|
||||
|
||||
const struct dentry_operations zpl_dentry_operations = {
|
||||
.d_delete = zpl_dentry_delete,
|
||||
};
|
||||
|
||||
struct file_system_type zpl_fs_type = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = ZFS_DRIVER,
|
||||
@ -527,3 +564,7 @@ struct file_system_type zpl_fs_type = {
|
||||
|
||||
ZFS_MODULE_PARAM(zfs, zfs_, delete_inode, INT, ZMOD_RW,
|
||||
"Delete inodes as soon as the last reference is released.");
|
||||
|
||||
ZFS_MODULE_PARAM(zfs, zfs_, delete_dentry, INT, ZMOD_RW,
|
||||
"Delete dentries from dentry cache as soon as the last reference is "
|
||||
"released.");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user