Add module parameter to disable prefetch in zfs_readdir

Add paramter zfs_readdir_dnode_prefetch_limit, defaulting to 0, to
control whether zfs_readdir prefetched metadata for objects it look at
when reading a directory. If zero, metadata is prefetched for all
directory entries. If non-zero, metadata is prefetched only if
directory has fewer entries than this.

Setting it to non-0 can be important for NFS servers with directories
containing many subdirectories.

Signed-off-by: Charles Hedrick <hedrick@rutgers.edu>
Co-authored-by: Chris Siebenmann<cks@cs.toronto.edu>
This commit is contained in:
Charles L. Hedrick 2024-07-01 15:33:24 -04:00
parent fd51786f86
commit 5d8bda9f24
2 changed files with 27 additions and 0 deletions

View File

@ -1774,6 +1774,24 @@ intact.
Unlike predictive prefetch, prescient prefetch never issues I/O Unlike predictive prefetch, prescient prefetch never issues I/O
that ends up not being needed, so it can't hurt performance. that ends up not being needed, so it can't hurt performance.
. .
.It Sy zfs_readdir_dnode_prefetch_limit Ns = Ns Sy 0 Pq u64
Disable prefetches in readdir for large directories.
When readdir searches a directory, it normally prefetches metadata for
all objects in the directory it checks, even if it's just
looking for a single object.
Setting this to a non-zero value disables that prefetching for directories
with a greater size than that value.
Disabling it for large directories can greatly lower CPU usage on NFS servers
where directories have a very large number of subdirectories.
Directory size in this case is the size returned from calling
.Sy stat
on the directory (stat.st_size).
On ZFS, this directory size value is approximately the number of files
and subdirectories in the directory.
A reasonable value would be 20000.
A zero value (the default) means no limit on directory metadata prefetching.
This parameter only applies on Linux.
.
.It Sy zfs_qat_checksum_disable Ns = Ns Sy 0 Ns | Ns 1 Pq int .It Sy zfs_qat_checksum_disable Ns = Ns Sy 0 Ns | Ns 1 Pq int
Disable QAT hardware acceleration for SHA256 checksums. Disable QAT hardware acceleration for SHA256 checksums.
May be unset after the ZFS modules have been loaded to initialize the QAT May be unset after the ZFS modules have been loaded to initialize the QAT

View File

@ -1504,6 +1504,7 @@ out:
* We use 0 for '.', and 1 for '..'. If this is the root of the filesystem, * We use 0 for '.', and 1 for '..'. If this is the root of the filesystem,
* we use the offset 2 for the '.zfs' directory. * we use the offset 2 for the '.zfs' directory.
*/ */
static ulong_t zfs_readdir_dnode_prefetch_limit = 0UL;
int int
zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr) zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
{ {
@ -1537,6 +1538,9 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
os = zfsvfs->z_os; os = zfsvfs->z_os;
offset = ctx->pos; offset = ctx->pos;
prefetch = zp->z_zn_prefetch; prefetch = zp->z_zn_prefetch;
if (zfs_readdir_dnode_prefetch_limit &&
zp->z_size > zfs_readdir_dnode_prefetch_limit)
prefetch = B_FALSE;
/* /*
* Initialize the iterator cursor. * Initialize the iterator cursor.
@ -4252,4 +4256,9 @@ EXPORT_SYMBOL(zfs_map);
/* CSTYLED */ /* CSTYLED */
module_param(zfs_delete_blocks, ulong, 0644); module_param(zfs_delete_blocks, ulong, 0644);
MODULE_PARM_DESC(zfs_delete_blocks, "Delete files larger than N blocks async"); MODULE_PARM_DESC(zfs_delete_blocks, "Delete files larger than N blocks async");
/* CSTYLED */
module_param(zfs_readdir_dnode_prefetch_limit, ulong, 0644);
MODULE_PARM_DESC(zfs_readdir_dnode_prefetch_limit,
"No zfs_readdir prefetch if non-zero and size > this");
#endif #endif