diff options
author | Matthew Macy <[email protected]> | 2020-02-28 14:53:18 -0800 |
---|---|---|
committer | GitHub <[email protected]> | 2020-02-28 14:53:18 -0800 |
commit | cf118ae8dc149c5c9fd9b70e89790c38824b85de (patch) | |
tree | 9e3b2b13d18d45f827a7de17e28619a02ee6f0db /module/zfs/zfs_log.c | |
parent | ae9f92f6f31c81f4d1aa4602f812f912b4392e7c (diff) |
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 <[email protected]>
Signed-off-by: Matt Macy <[email protected]>
Closes #10075
Diffstat (limited to 'module/zfs/zfs_log.c')
-rw-r--r-- | module/zfs/zfs_log.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c index cfb2f3be2..6951ef90b 100644 --- a/module/zfs/zfs_log.c +++ b/module/zfs/zfs_log.c @@ -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); |