From d655bf206e3fb435e1a9e4ed64a79240f8b3a329 Mon Sep 17 00:00:00 2001 From: avg Date: Mon, 2 Oct 2017 12:47:35 +0000 Subject: MFC r323918: MFV r323917: 8648 Fix range locking in ZIL commit codepath This fixes a problem introduced in r320496, MFC of r308782. --- .../contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c | 2 +- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index 6763de7..a2b8315 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -1344,7 +1344,7 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) } else { /* indirect write */ /* * Have to lock the whole block to ensure when it's - * written out and it's checksum is being calculated + * written out and its checksum is being calculated * that no one can change the data. We need to re-check * blocksize after we get the lock in case it's changed! */ diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c index c341feb..87b2f14 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c @@ -1305,7 +1305,6 @@ zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) zgd = kmem_zalloc(sizeof (zgd_t), KM_SLEEP); zgd->zgd_zilog = zv->zv_zilog; - zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, RL_READER); /* * Write records come in two flavors: immediate and indirect. @@ -1314,12 +1313,22 @@ zvol_get_data(void *arg, lr_write_t *lr, char *buf, zio_t *zio) * sync the data and get a pointer to it (indirect) so that * we don't have to write the data twice. */ - if (buf != NULL) { /* immediate write */ + if (buf != NULL) { /* immediate write */ + zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, + RL_READER); error = dmu_read(os, object, offset, size, buf, DMU_READ_NO_PREFETCH); - } else { + } else { /* indirect write */ + /* + * Have to lock the whole block to ensure when it's written out + * and its checksum is being calculated that no one can change + * the data. Contrarily to zfs_get_data we need not re-check + * blocksize after we get the lock because it cannot be changed. + */ size = zv->zv_volblocksize; offset = P2ALIGN(offset, size); + zgd->zgd_rl = zfs_range_lock(&zv->zv_znode, offset, size, + RL_READER); error = dmu_buf_hold(os, object, offset, zgd, &db, DMU_READ_NO_PREFETCH); if (error == 0) { -- cgit v1.1