mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2025-01-27 02:14:28 +03:00
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:
parent
ae9f92f6f3
commit
cf118ae8dc
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user