Skip to content

Improve block cloning transactions accounting #17431

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/sys/dmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ void dmu_tx_hold_append(dmu_tx_t *tx, uint64_t object, uint64_t off, int len);
void dmu_tx_hold_append_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
int len);
void dmu_tx_hold_clone_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
int len);
uint64_t len, uint_t blksz);
void dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off,
uint64_t len);
void dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
Expand Down
3 changes: 2 additions & 1 deletion module/zfs/dbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3912,7 +3912,8 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,

ASSERT(blkid != DMU_BONUS_BLKID);
ASSERT(RW_LOCK_HELD(&dn->dn_struct_rwlock));
ASSERT3U(dn->dn_nlevels, >, level);
if (!fail_sparse)
ASSERT3U(dn->dn_nlevels, >, level);

*dbp = NULL;

Expand Down
43 changes: 36 additions & 7 deletions module/zfs/dmu_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <sys/dsl_pool.h>
#include <sys/zap_impl.h>
#include <sys/spa.h>
#include <sys/brt_impl.h>
#include <sys/sa.h>
#include <sys/sa_impl.h>
#include <sys/zfs_context.h>
Expand Down Expand Up @@ -547,17 +548,45 @@ dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, uint64_t len)
}

static void
dmu_tx_count_clone(dmu_tx_hold_t *txh, uint64_t off, uint64_t len)
dmu_tx_count_clone(dmu_tx_hold_t *txh, uint64_t off, uint64_t len,
uint_t blksz)
{
dmu_tx_t *tx = txh->txh_tx;
dnode_t *dn = txh->txh_dnode;
int err;

/*
* Reuse dmu_tx_count_free(), it does exactly what we need for clone.
*/
dmu_tx_count_free(txh, off, len);
ASSERT0(tx->tx_txg);
ASSERT(dn->dn_indblkshift != 0);
ASSERT(blksz != 0);
ASSERT0(off % blksz);

(void) zfs_refcount_add_many(&txh->txh_memory_tohold,
len / blksz * sizeof (brt_entry_t), FTAG);

int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
uint64_t start = off / blksz >> shift;
uint64_t end = (off + len) / blksz >> shift;

(void) zfs_refcount_add_many(&txh->txh_space_towrite,
(end - start + 1) << dn->dn_indblkshift, FTAG);

zio_t *zio = zio_root(tx->tx_pool->dp_spa,
NULL, NULL, ZIO_FLAG_CANFAIL);
for (uint64_t i = start; i <= end; i++) {
err = dmu_tx_check_ioerr(zio, dn, 1, i);
if (err != 0) {
tx->tx_err = err;
break;
}
}
err = zio_wait(zio);
if (err != 0)
tx->tx_err = err;
}

void
dmu_tx_hold_clone_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
dmu_tx_hold_clone_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
uint64_t len, uint_t blksz)
{
dmu_tx_hold_t *txh;

Expand All @@ -567,7 +596,7 @@ dmu_tx_hold_clone_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
txh = dmu_tx_hold_dnode_impl(tx, dn, THT_CLONE, off, len);
if (txh != NULL) {
dmu_tx_count_dnode(txh);
dmu_tx_count_clone(txh, off, len);
dmu_tx_count_clone(txh, off, len, blksz);
}
}

Expand Down
5 changes: 3 additions & 2 deletions module/zfs/zfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1828,7 +1828,8 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
dmu_tx_hold_sa(tx, outzp->z_sa_hdl, B_FALSE);
db = (dmu_buf_impl_t *)sa_get_db(outzp->z_sa_hdl);
DB_DNODE_ENTER(db);
dmu_tx_hold_clone_by_dnode(tx, DB_DNODE(db), outoff, size);
dmu_tx_hold_clone_by_dnode(tx, DB_DNODE(db), outoff, size,
inblksz);
DB_DNODE_EXIT(db);
zfs_sa_upgrade_txholds(tx, outzp);
error = dmu_tx_assign(tx, DMU_TX_WAIT);
Expand Down Expand Up @@ -1995,7 +1996,7 @@ zfs_clone_range_replay(znode_t *zp, uint64_t off, uint64_t len, uint64_t blksz,
dmu_tx_hold_sa(tx, zp->z_sa_hdl, B_FALSE);
db = (dmu_buf_impl_t *)sa_get_db(zp->z_sa_hdl);
DB_DNODE_ENTER(db);
dmu_tx_hold_clone_by_dnode(tx, DB_DNODE(db), off, len);
dmu_tx_hold_clone_by_dnode(tx, DB_DNODE(db), off, len, blksz);
DB_DNODE_EXIT(db);
zfs_sa_upgrade_txholds(tx, zp);
error = dmu_tx_assign(tx, DMU_TX_WAIT);
Expand Down
5 changes: 3 additions & 2 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ zvol_replay_clone_range(void *arg1, void *arg2, boolean_t byteswap)
if (error != 0 || !zv->zv_dn)
return (error);
tx = dmu_tx_create(os);
dmu_tx_hold_clone_by_dnode(tx, zv->zv_dn, off, len);
dmu_tx_hold_clone_by_dnode(tx, zv->zv_dn, off, len, blksz);
error = dmu_tx_assign(tx, DMU_TX_WAIT);
if (error != 0) {
dmu_tx_abort(tx);
Expand Down Expand Up @@ -742,7 +742,8 @@ zvol_clone_range(zvol_state_t *zv_src, uint64_t inoff, zvol_state_t *zv_dst,
}

tx = dmu_tx_create(zv_dst->zv_objset);
dmu_tx_hold_clone_by_dnode(tx, zv_dst->zv_dn, outoff, size);
dmu_tx_hold_clone_by_dnode(tx, zv_dst->zv_dn, outoff, size,
zv_src->zv_volblocksize);
error = dmu_tx_assign(tx, DMU_TX_WAIT);
if (error != 0) {
dmu_tx_abort(tx);
Expand Down
Loading