git: 4175fa107f77 - main - stand: Lookup the offsets for this SA bundle

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

URL: https://cgit.FreeBSD.org/src/commit/?id=4175fa107f77e93c7e5c7d0dbd3662b0a6ae620b

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

    stand: Lookup the offsets for this SA bundle
    
    Compute the offset for the data for this bundle and the requested data
    type.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D60265
---
 stand/libsa/zfs/zfsimpl.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c
index b9b5b227deec..e06c9b01328b 100644
--- a/stand/libsa/zfs/zfsimpl.c
+++ b/stand/libsa/zfs/zfsimpl.c
@@ -3834,6 +3834,73 @@ zfs_sa_load(struct zfsmount *mount)
 	return (0);
 }
 
+/*
+ * Walk through the system attribute bundle looking for the attribute that's
+ * requested. Return it's value and size.
+ */
+static int
+zfs_sa_lookup(struct zfsmount *mount, const void *buf, size_t buflen,
+    enum zfs_sa_attr_id attr, void *value, size_t *size)
+{
+	const sa_hdr_phys_t *hdr;
+	uint16_t layout[ZFS_SA_MAX_ATTRS];
+	char layout_name[16];
+	size_t hdrsize, length, offset;
+	unsigned int i, j, length_idx;
+	int error;
+
+	hdr = buf;
+	if (buflen < sizeof(*hdr) || hdr->sa_magic != SA_MAGIC)
+		return (EIO);
+	error = zfs_sa_load(mount);
+	if (error != 0)
+		return (error);
+
+	memset(layout, 0xff, sizeof(layout));
+	i = SA_HDR_LAYOUT_NUM(hdr);
+	if (i == 0)
+		i = 1;
+	snprintf(layout_name, sizeof(layout_name), "%u", i);
+	error = zap_lookup(mount->spa, &mount->sa_layouts, layout_name,
+	    sizeof(layout[0]), nitems(layout), layout);
+	if (error != 0)
+		return (error);
+
+	hdrsize = SA_HDR_SIZE(hdr);
+	if (hdrsize < sizeof(*hdr) || hdrsize > buflen)
+		return (EIO);
+	offset = hdrsize;
+	length_idx = 0;
+	for (i = 0; i < nitems(layout) && layout[i] != UINT16_MAX; i++) {
+		for (j = 0; j < nitems(zfs_sa_attrs); j++) {
+			if (mount->sa_attrs[j] != UINT64_MAX &&
+			    SA_ATTR_NUM(mount->sa_attrs[j]) == layout[i])
+				break;
+		}
+		if (j == nitems(zfs_sa_attrs))
+			return (EIO);
+		length = SA_ATTR_LENGTH(mount->sa_attrs[j]);
+		if (length == 0) {
+			if (offsetof(sa_hdr_phys_t, sa_lengths) +
+			    (length_idx + 1) * sizeof(hdr->sa_lengths[0]) >
+			    hdrsize)
+				return (EIO);
+			length = hdr->sa_lengths[length_idx++];
+		}
+		if (offset > buflen || length > buflen - offset)
+			return (EIO);
+		if (j == attr) {
+			if (*size < length)
+				return (EOVERFLOW);
+			memcpy(value, (const char *)buf + offset, length);
+			*size = length;
+			return (0);
+		}
+		offset = roundup2(offset + length, 8);
+	}
+	return (ENOENT);
+}
+
 static int
 zfs_dnode_stat(struct zfsmount *mount, dnode_phys_t *dn, struct stat *sb,
     uint64_t fsid_guid, uint64_t objnum)