Prevent panic during concurrent snapshot rollback and zvol read

Protect zvol_cdev_read with zv_suspend_lock to prevent concurrent
release of the dnode, avoiding panic when a snapshot is rolled back
in parallel during ongoing zvol read operation.

Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Ameer Hamza <ahamza@ixsystems.com>
Closes #14839
This commit is contained in:
Ameer Hamza 2023-05-10 05:56:35 +05:00 committed by GitHub
parent d3db900a4e
commit 14ba8ab97d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -832,6 +832,7 @@ zvol_cdev_read(struct cdev *dev, struct uio *uio_s, int ioflag)
(zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize)) (zfs_uio_offset(&uio) < 0 || zfs_uio_offset(&uio) > volsize))
return (SET_ERROR(EIO)); return (SET_ERROR(EIO));
rw_enter(&zv->zv_suspend_lock, ZVOL_RW_READER);
ssize_t start_resid = zfs_uio_resid(&uio); ssize_t start_resid = zfs_uio_resid(&uio);
lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio), lr = zfs_rangelock_enter(&zv->zv_rangelock, zfs_uio_offset(&uio),
zfs_uio_resid(&uio), RL_READER); zfs_uio_resid(&uio), RL_READER);
@ -853,6 +854,7 @@ zvol_cdev_read(struct cdev *dev, struct uio *uio_s, int ioflag)
zfs_rangelock_exit(lr); zfs_rangelock_exit(lr);
int64_t nread = start_resid - zfs_uio_resid(&uio); int64_t nread = start_resid - zfs_uio_resid(&uio);
dataset_kstats_update_read_kstats(&zv->zv_kstat, nread); dataset_kstats_update_read_kstats(&zv->zv_kstat, nread);
rw_exit(&zv->zv_suspend_lock);
return (error); return (error);
} }