aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs/zfs_log.c
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs/zfs_log.c')
-rw-r--r--module/zfs/zfs_log.c25
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);