From 9d76950d67849cc1911c949fb0f80f63c9293664 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Fri, 23 May 2025 21:48:46 -0400 Subject: [PATCH] ZIL: Improve write log size accounting Before this change write log size TXG throttling mechanism was accounting only user payload bytes. But the actual ZIL both on disk and especially in memory include headers of hundred(s) of bytes. Not accouting those may allow applications like bonnie++, in their wisdom writing one byte at a time, to consume excessive amount of memory and ZIL/SLOG in one TXG. Reviewed-by: Brian Behlendorf Reviewed-by: Rob Norris Signed-off-by: Alexander Motin Sponsored by: iXsystems, Inc. Closes #17373 --- module/zfs/zfs_log.c | 11 ++++++----- module/zfs/zvol.c | 10 ++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c index f90d88f1e..8655ff594 100644 --- a/module/zfs/zfs_log.c +++ b/module/zfs/zfs_log.c @@ -617,8 +617,7 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, dmu_buf_impl_t *db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl); uint32_t blocksize = zp->z_blksz; itx_wr_state_t write_state; - uint64_t gen = 0; - ssize_t size = resid; + uint64_t gen = 0, log_size = 0; if (zil_replaying(zilog, tx) || zp->z_unlinked || zfs_xattr_owner_unlinked(zp)) { @@ -680,6 +679,10 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, } } + log_size += itx->itx_size; + if (wr_state == WR_NEED_COPY) + log_size += len; + itx->itx_wr_state = wr_state; lr->lr_foid = zp->z_id; lr->lr_offset = off; @@ -699,9 +702,7 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, resid -= len; } - if (write_state == WR_COPIED || write_state == WR_NEED_COPY) { - dsl_pool_wrlog_count(zilog->zl_dmu_pool, size, tx->tx_txg); - } + dsl_pool_wrlog_count(zilog->zl_dmu_pool, log_size, tx->tx_txg); } /* diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index 05a56f8e6..148bf16ce 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -871,7 +871,7 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset, uint32_t blocksize = zv->zv_volblocksize; zilog_t *zilog = zv->zv_zilog; itx_wr_state_t write_state; - uint64_t sz = size; + uint64_t log_size = 0; if (zil_replaying(zilog, tx)) return; @@ -909,6 +909,10 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset, wr_state = WR_NEED_COPY; } + log_size += itx->itx_size; + if (wr_state == WR_NEED_COPY) + log_size += len; + itx->itx_wr_state = wr_state; lr->lr_foid = ZVOL_OBJ; lr->lr_offset = offset; @@ -924,9 +928,7 @@ zvol_log_write(zvol_state_t *zv, dmu_tx_t *tx, uint64_t offset, size -= len; } - if (write_state == WR_COPIED || write_state == WR_NEED_COPY) { - dsl_pool_wrlog_count(zilog->zl_dmu_pool, sz, tx->tx_txg); - } + dsl_pool_wrlog_count(zilog->zl_dmu_pool, log_size, tx->tx_txg); } /*