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 e90badec11 ("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 (22649d4dba). 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
This commit is contained in:
Warner Losh committed 2026-10-03 11:32:08 -06:00
1 parent f382ef1dc8
commit 262fa4695d
1 file changed
+4 -31
+4 -31
View File
@@ -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