Skip to content

Commit

Permalink
Add module parameter to disable prefetch in zfs_readdir
Browse files Browse the repository at this point in the history
Add paramter zfs_readdir_dnode_prefetch_enabled, defaulting to 1, to control
whether zfs_readdir prefetched metadata for all objects it look at when
reading a directory.

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

Signed-off-by: Charles Hedrick <[email protected]>
Co-authored-by: Chris Siebenmann<[email protected]>
  • Loading branch information
clhedrick-student authored and root committed Jul 12, 2024
1 parent fd51786 commit ff52ddb
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 0 deletions.
12 changes: 12 additions & 0 deletions man/man4/zfs.4
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,18 @@ intact.
Unlike predictive prefetch, prescient prefetch never issues I/O
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.
(Normally off)
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 more entries 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.
A reasonable value would be 20000.
.
.It Sy zfs_qat_checksum_disable Ns = Ns Sy 0 Ns | Ns 1 Pq int
Disable QAT hardware acceleration for SHA256 checksums.
May be unset after the ZFS modules have been loaded to initialize the QAT
Expand Down
8 changes: 8 additions & 0 deletions module/os/linux/zfs/zfs_vnops_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,7 @@ zfs_rmdir(znode_t *dzp, char *name, znode_t *cwd, cred_t *cr,
* We use 0 for '.', and 1 for '..'. If this is the root of the filesystem,
* we use the offset 2 for the '.zfs' directory.
*/
static ulong_t zfs_readdir_dnode_prefetch_limit = 0UL;
int
zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
{
Expand Down Expand Up @@ -1537,6 +1538,9 @@ zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
os = zfsvfs->z_os;
offset = ctx->pos;
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.
Expand Down Expand Up @@ -4252,4 +4256,8 @@ EXPORT_SYMBOL(zfs_map);
/* CSTYLED */
module_param(zfs_delete_blocks, ulong, 0644);
MODULE_PARM_DESC(zfs_delete_blocks, "Delete files larger than N blocks async");

module_param(zfs_readdir_dnode_prefetch_limit, ulong, 0644);

Check failure on line 4260 in module/os/linux/zfs/zfs_vnops_os.c

View workflow job for this annotation

GitHub Actions / checkstyle

non-POSIX typedef ulong used: use ulong_t instead
MODULE_PARM_DESC(zfs_readdir_dnode_prefetch_limit,
"No zfs_readdir prefetch if non-zero and size > this");
#endif

0 comments on commit ff52ddb

Please sign in to comment.