FreeBSD: Lock vnode in zfs_ioctl()

Previously vnode was not locked there, unlike Linux.  It required
locking it in vn_flush_cached_data(), which recursed on the lock
if called from zfs_clone_range(), having the vnode locked.

Reviewed-by: Alan Somers <asomers@gmail.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Alexander Motin <mav@FreeBSD.org>
Sponsored by: iXsystems, Inc.
Closes #16789
Closes #16796
This commit is contained in:
Alexander Motin 2024-11-23 17:26:52 -05:00 committed by GitHub
parent 38c0324c0f
commit b3b0ce64d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 4 additions and 4 deletions

View File

@ -91,20 +91,16 @@ vn_is_readonly(vnode_t *vp)
((vp)->v_object != NULL && \ ((vp)->v_object != NULL && \
(vp)->v_object->resident_page_count > 0) (vp)->v_object->resident_page_count > 0)
#ifndef IN_BASE
static __inline void static __inline void
vn_flush_cached_data(vnode_t *vp, boolean_t sync) vn_flush_cached_data(vnode_t *vp, boolean_t sync)
{ {
if (vm_object_mightbedirty(vp->v_object)) { if (vm_object_mightbedirty(vp->v_object)) {
int flags = sync ? OBJPC_SYNC : 0; int flags = sync ? OBJPC_SYNC : 0;
vn_lock(vp, LK_SHARED | LK_RETRY);
zfs_vmobject_wlock(vp->v_object); zfs_vmobject_wlock(vp->v_object);
vm_object_page_clean(vp->v_object, 0, 0, flags); vm_object_page_clean(vp->v_object, 0, 0, flags);
zfs_vmobject_wunlock(vp->v_object); zfs_vmobject_wunlock(vp->v_object);
VOP_UNLOCK(vp);
} }
} }
#endif
#define vn_exists(vp) do { } while (0) #define vn_exists(vp) do { } while (0)
#define vn_invalid(vp) do { } while (0) #define vn_invalid(vp) do { } while (0)

View File

@ -291,8 +291,12 @@ zfs_ioctl(vnode_t *vp, ulong_t com, intptr_t data, int flag, cred_t *cred,
case F_SEEK_HOLE: case F_SEEK_HOLE:
{ {
off = *(offset_t *)data; off = *(offset_t *)data;
error = vn_lock(vp, LK_SHARED);
if (error)
return (error);
/* offset parameter is in/out */ /* offset parameter is in/out */
error = zfs_holey(VTOZ(vp), com, &off); error = zfs_holey(VTOZ(vp), com, &off);
VOP_UNLOCK(vp);
if (error) if (error)
return (error); return (error);
*(offset_t *)data = off; *(offset_t *)data = off;