Fix a logic bug in the FreeBSD getpages VOP

In commit cd32b4f5b7 ("Fix a deadlock in the FreeBSD getpages VOP") I
introduced a bug while porting the patch originally committed to
FreeBSD: the rangelock pointer may be NULL if the try operation failed,
so we must avoid calling zfs_rangelock_unlock() in that case.

Reviewed-by: Allan Jude <allan@klarasystems.com>
Reviewed-by: Ryan Moeller <ryan@ixsystems.com>
Reviewed-by: Matt Macy <mmacy@FreeBSD.org>
Reported-by: Steve Wills <swills@FreeBSD.org>
Signed-off-by: Mark Johnston <markj@FreeBSD.org>
Closes #10519 
Closes #10960
This commit is contained in:
Mark Johnston 2020-09-22 19:05:52 -04:00 committed by GitHub
parent 5f8a9e6a02
commit 0daa0320e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4859,6 +4859,7 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
obj_size = object->un_pager.vnp.vnp_size; obj_size = object->un_pager.vnp.vnp_size;
zfs_vmobject_wunlock(object); zfs_vmobject_wunlock(object);
if (IDX_TO_OFF(ma[count - 1]->pindex) >= obj_size) { if (IDX_TO_OFF(ma[count - 1]->pindex) >= obj_size) {
if (lr != NULL)
zfs_rangelock_exit(lr); zfs_rangelock_exit(lr);
ZFS_EXIT(zfsvfs); ZFS_EXIT(zfsvfs);
return (zfs_vm_pagerret_bad); return (zfs_vm_pagerret_bad);
@ -4887,6 +4888,7 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
error = dmu_read_pages(os, zp->z_id, ma, count, &pgsin_b, &pgsin_a, error = dmu_read_pages(os, zp->z_id, ma, count, &pgsin_b, &pgsin_a,
MIN(end, obj_size) - (end - PAGE_SIZE)); MIN(end, obj_size) - (end - PAGE_SIZE));
if (lr != NULL)
zfs_rangelock_exit(lr); zfs_rangelock_exit(lr);
ZFS_ACCESSTIME_STAMP(zfsvfs, zp); ZFS_ACCESSTIME_STAMP(zfsvfs, zp);
ZFS_EXIT(zfsvfs); ZFS_EXIT(zfsvfs);