Don't call zrele on passed zp in zfs_xattr_owner_unlinked on FreeBSD

FreeBSD has a somewhat more cumbersome locking and refcounting
protocol for the platform counterpart to znode. We need to not call
zrele on the passed zp, but do need to do so on any intermediate zp.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
Closes #10075
This commit is contained in:
Matthew Macy 2020-02-28 14:53:18 -08:00 committed by GitHub
parent ae9f92f6f3
commit cf118ae8dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -231,14 +231,33 @@ zfs_xattr_owner_unlinked(znode_t *zp)
{
int unlinked = 0;
znode_t *dzp;
#ifdef __FreeBSD__
znode_t *tzp = zp;
/*
* zrele drops the vnode lock which violates the VOP locking contract
* on FreeBSD. See comment at the top of zfs_replay.c for more detail.
*/
#ifndef __FreeBSD__
/*
* if zp is XATTR node, keep walking up via z_xattr_parent until we
* get the owner
*/
while (tzp->z_pflags & ZFS_XATTR) {
ASSERT3U(zp->z_xattr_parent, !=, 0);
if (zfs_zget(ZTOZSB(tzp), tzp->z_xattr_parent, &dzp) != 0) {
unlinked = 1;
break;
}
if (tzp != zp)
zrele(tzp);
tzp = dzp;
unlinked = tzp->z_unlinked;
}
if (tzp != zp)
zrele(tzp);
#else
zhold(zp);
#endif
/*
* if zp is XATTR node, keep walking up via z_xattr_parent until we
* get the owner
@ -249,11 +268,11 @@ zfs_xattr_owner_unlinked(znode_t *zp)
unlinked = 1;
break;
}
zrele(zp);
zp = dzp;
unlinked = zp->z_unlinked;
}
#ifndef __FreeBSD__
zrele(zp);
#endif
return (unlinked);