Use AVL tree lookup in zfsctl_snapdir_vget for mounted snapshots

zfsctl_snapdir_vget resolves NFS file handles for snapshot directory
entries by calling zfsctl_snapshot_path_objset, which iterates all
snapshots via dmu_snapshot_list_next to find the matching objsetid.
With many snapshots this linear scan is expensive.

For snapshots that have been previously mounted, the path is already
cached in the in-memory AVL tree. Check the tree first with
zfsctl_snapshot_find_by_objsetid and fall back to the on-disk scan
only when the entry is not found.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Ameer Hamza <ahamza@ixsystems.com>
Closes #18429
This commit is contained in:
Ameer Hamza
2026-04-16 02:49:22 +05:00
committed by GitHub
parent 2abf469be5
commit 01e2a96839
+18 -4
View File
@@ -1394,17 +1394,31 @@ int
zfsctl_snapdir_vget(struct super_block *sb, uint64_t objsetid, int gen,
struct inode **ipp)
{
zfsvfs_t *zfsvfs = sb->s_fs_info;
int error;
struct path path;
char *mnt;
struct dentry *dentry;
zfs_snapentry_t *se;
mnt = kmem_alloc(MAXPATHLEN, KM_SLEEP);
error = zfsctl_snapshot_path_objset(sb->s_fs_info, objsetid,
MAXPATHLEN, mnt);
if (error)
goto out;
/*
* Try the in-memory AVL tree first for previously mounted
* snapshots, falling back to the on-disk scan if not found.
*/
rw_enter(&zfs_snapshot_lock, RW_READER);
se = zfsctl_snapshot_find_by_objsetid(zfsvfs->z_os->os_spa, objsetid);
rw_exit(&zfs_snapshot_lock);
if (se != NULL) {
strlcpy(mnt, se->se_path, MAXPATHLEN);
zfsctl_snapshot_rele(se);
} else {
error = zfsctl_snapshot_path_objset(zfsvfs, objsetid,
MAXPATHLEN, mnt);
if (error)
goto out;
}
/* Trigger automount */
error = -kern_path(mnt, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &path);