diff options
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); |