diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c index 21296c76e..cfb2f3be2 100644 --- a/module/zfs/zfs_log.c +++ b/module/zfs/zfs_log.c @@ -232,7 +232,13 @@ zfs_xattr_owner_unlinked(znode_t *zp) int unlinked = 0; znode_t *dzp; + /* + * 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__ zhold(zp); +#endif /* * if zp is XATTR node, keep walking up via z_xattr_parent until we * get the owner @@ -247,7 +253,9 @@ zfs_xattr_owner_unlinked(znode_t *zp) zp = dzp; unlinked = zp->z_unlinked; } +#ifndef __FreeBSD__ zrele(zp); +#endif return (unlinked); } diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c index 59a219983..6372c004a 100644 --- a/module/zfs/zfs_replay.c +++ b/module/zfs/zfs_replay.c @@ -48,6 +48,16 @@ #include #include +/* + * NB: FreeBSD expects to be able to do vnode locking in lookup and + * hold the locks across all subsequent VOPs until vput is called. + * This means that its zfs vnops routines can't do any internal locking. + * In order to have the same contract as the Linux vnops there would + * needed to be duplicate locked vnops. If the vnops were used more widely + * in common code this would likely be preferable. However, currently + * this is the only file where this is the case. + */ + /* * Functions to replay ZFS intent log (ZIL) records * The functions are called through a function vector (zfs_replay_vector)