mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
MFV r323917: 8648 Fix range locking in ZIL commit codepath
illumos/illumos-gate@42b141117242b1411172
https://www.illumos.org/issues/8648 I'm opening this bug to track integration of the following ZFS on Linux commit into illumos: commitf763c3d1df
Author: LOLi <loli10K@users.noreply.github.com> Date: Mon Aug 21 17:59:48 2017 +0200 Fix range locking in ZIL commit codepath Since OpenZFS 7578 (1b7c1e5
) if we have a ZVOL with logbias=throughput we will force WR_INDIRECT itxs in zvol_log_write() setting itx->itx_lr offset and length to the offset and length of the BIO from zvol_write()->zvol_log_write(): these offset and length are later used to take a range lock in zillog->zl_get_data function: zvol_get_data(). Now suppose we have a ZVOL with blocksize=8K and push 4K writes to offset 0: we will only be range-locking 0-4096. This means the ASSERTion we make in dbuf_unoverride() is no longer valid because now dmu_sync() is called from zilog's get_data functions holding a partial lock on the dbuf. Fix this by taking a range lock on the whole block in zvol_get_data(). Reviewed-by: Chunwei Chen <tuxoko@gmail.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: loli10K <ezomori.nozomu@gmail.com> Reviewed by: Igor Kozhukhov <igor@dilos.org> Reviewed by: Matt Ahrens <mahrens@delphix.com> Reviewed by: Andriy Gapon <avg@FreeBSD.org> Reviewed by: Alexander Motin <mav@FreeBSD.org> Approved by: Robert Mustacchi <rm@joyent.com> Author: LOLi <loli10K@users.noreply.github.com> MFC after: 10 days
This commit is contained in:
commit
f94aa61c33
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=323918
@ -1343,7 +1343,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!
|
||||
*/
|
||||
|
@ -1349,7 +1349,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.
|
||||
@ -1358,12 +1357,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) {
|
||||
|
Loading…
Reference in New Issue
Block a user