From 3897e86bd1e70f6eb5a48b89e6489bb8026cecf4 Mon Sep 17 00:00:00 2001 From: Alexander Motin Date: Tue, 10 Jun 2025 12:30:06 -0400 Subject: [PATCH] Make TX abort after assign safer It is not right, but there are few examples when TX is aborted after being assigned in case of error. To handle it better on production systems add extra cleanup steps. While here, replace couple dmu_tx_abort() in simple cases. Reviewed-by: Rob Norris Reviewed-by: Brian Behlendorf Reviewed-by: Igor Kozhukhov Signed-off-by: Alexander Motin Sponsored by: iXsystems, Inc. Closes #17438 --- module/zfs/dmu_tx.c | 11 ++++++++++- module/zfs/zfs_vnops.c | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/module/zfs/dmu_tx.c b/module/zfs/dmu_tx.c index 5457ca2a8..7954cdbe2 100644 --- a/module/zfs/dmu_tx.c +++ b/module/zfs/dmu_tx.c @@ -1323,6 +1323,7 @@ dmu_tx_destroy(dmu_tx_t *tx) void dmu_tx_commit(dmu_tx_t *tx) { + /* This function should only be used on assigned transactions. */ ASSERT(tx->tx_txg != 0); /* @@ -1361,7 +1362,12 @@ dmu_tx_commit(dmu_tx_t *tx) void dmu_tx_abort(dmu_tx_t *tx) { - ASSERT(tx->tx_txg == 0); + /* This function should not be used on assigned transactions. */ + ASSERT0(tx->tx_txg); + + /* Should not be needed, but better be safe than sorry. */ + if (tx->tx_tempreserve_cookie) + dsl_dir_tempreserve_clear(tx->tx_tempreserve_cookie, tx); /* * Call any registered callbacks with an error code. @@ -1369,6 +1375,9 @@ dmu_tx_abort(dmu_tx_t *tx) if (!list_is_empty(&tx->tx_callbacks)) dmu_tx_do_callbacks(&tx->tx_callbacks, SET_ERROR(ECANCELED)); + /* Should not be needed, but better be safe than sorry. */ + dmu_tx_unassign(tx); + dmu_tx_destroy(tx); } diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index afd9e6131..cacf74dcb 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -1681,7 +1681,7 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp, */ if (inblksz != outzp->z_blksz) { error = SET_ERROR(EINVAL); - dmu_tx_abort(tx); + dmu_tx_commit(tx); break; }