From 262fa4695d90207b9080f2cc5cb01eccf07fe243 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Sat, 3 Oct 2026 08:42:58 -0600 Subject: [PATCH] stand: Implement zfs_dnode_readlink in terms of zfs_dnode_sa_lookup Get the link offset using the zfs_dnode_sa_lookup helper now. Recently, the symbolic links we rely on in the boot loader have stopped working. Prior to OpenZFS commit e90badec11d3 ("Inherit the project ID for every object type", Matt Turner, 2026-08-14), symbolic link information was written at a fixed offset in the SA data. Since that commit, the inherited PROJIDs mean that all pools with quota enabled have started writing symbolic links with a new, non-fixed offset. Old symbolic links remained unchanged, but new ones were written with a different offset. At work, we have all these things: rewritten BEs, quotas, and a dependence on symbolic links in our boot path. This came in on 2026-08-24 OpenZFS merge (22649d4dba73). This was 12 hours after stab week for August, so we didn't hit this until the September stab week. Since the new kernel has to write links at the new offset, the initial tests worked, but the second ones didn't. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D60268 --- stand/libsa/zfs/zfsimpl.c | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c index a13f8d805049..5447fd825c24 100644 --- a/stand/libsa/zfs/zfsimpl.c +++ b/stand/libsa/zfs/zfsimpl.c @@ -3995,38 +3995,11 @@ zfs_dnode_readlink(struct zfsmount *mount, dnode_phys_t *dn, char *path, int rc = 0; if (dn->dn_bonustype == DMU_OT_SA) { - sa_hdr_phys_t *sahdrp = NULL; - size_t size = 0; - void *buf = NULL; - int hdrsize; - char *p; + size_t size = psize; - if (dn->dn_bonuslen != 0) { - sahdrp = (sa_hdr_phys_t *)DN_BONUS(dn); - } else { - blkptr_t *bp; - - if ((dn->dn_flags & DNODE_FLAG_SPILL_BLKPTR) == 0) - return (EIO); - bp = DN_SPILL_BLKPTR(dn); - - size = BP_GET_LSIZE(bp); - buf = malloc(size); - if (buf == NULL) - rc = ENOMEM; - else - rc = zio_read(mount->spa, bp, buf); - if (rc != 0) { - free(buf); - return (rc); - } - sahdrp = buf; - } - hdrsize = SA_HDR_SIZE(sahdrp); - p = (char *)((uintptr_t)sahdrp + hdrsize + SA_SYMLINK_OFFSET); - memcpy(path, p, psize); - free(buf); - return (0); + rc = zfs_dnode_sa_lookup(mount, dn, ZFS_SA_SYMLINK, path, + &size); + return (rc != 0 ? rc : (size == psize ? 0 : EIO)); } /* * Second test is purely to silence bogus compiler