git: 8bc06ba211b9 - main - stand: Lookup specific SA value in a dnode

From: Warner Losh <imp_at_FreeBSD.org>
Date: Sat, 03 Oct 2026 17:34:56 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=8bc06ba211b962c4742fe2acb17c22b86256d592

commit 8bc06ba211b962c4742fe2acb17c22b86256d592
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-10-03 14:42:48 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-10-03 17:32:08 +0000

    stand: Lookup specific SA value in a dnode
    
    zfs_dnode_sa_lookup will look in the bonus part of the dnode for the
    requested SA values, and fall back to the spill as if it's not there.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D60266
---
 stand/libsa/zfs/zfsimpl.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c
index e06c9b01328b..1eb1923fac49 100644
--- a/stand/libsa/zfs/zfsimpl.c
+++ b/stand/libsa/zfs/zfsimpl.c
@@ -3901,6 +3901,43 @@ zfs_sa_lookup(struct zfsmount *mount, const void *buf, size_t buflen,
 	return (ENOENT);
 }
 
+/*
+ * Try to find the requested attribute by looking in both the bonus area and the
+ * spill areas. The bonus area is already in memory, but we need to read the
+ * spill area.
+ */
+static int
+zfs_dnode_sa_lookup(struct zfsmount *mount, dnode_phys_t *dn,
+    enum zfs_sa_attr_id attr, void *value, size_t *size)
+{
+	void *buf;
+	size_t buflen, valuesize;
+	int error;
+
+	if (dn->dn_bonuslen != 0) {
+		valuesize = *size;
+		error = zfs_sa_lookup(mount, DN_BONUS(dn), dn->dn_bonuslen,
+		    attr, value, &valuesize);
+		if (error == 0) {
+			*size = valuesize;
+			return (0);
+		}
+		if (error != ENOENT)
+			return (error);
+	}
+	if ((dn->dn_flags & DNODE_FLAG_SPILL_BLKPTR) == 0)
+		return (ENOENT);
+	buflen = BP_GET_LSIZE(DN_SPILL_BLKPTR(dn));
+	buf = malloc(buflen);
+	if (buf == NULL)
+		return (ENOMEM);
+	error = zio_read(mount->spa, DN_SPILL_BLKPTR(dn), buf);
+	if (error == 0)
+		error = zfs_sa_lookup(mount, buf, buflen, attr, value, size);
+	free(buf);
+	return (error);
+}
+
 static int
 zfs_dnode_stat(struct zfsmount *mount, dnode_phys_t *dn, struct stat *sb,
     uint64_t fsid_guid, uint64_t objnum)