Skip to content

Commit 48ce292

Browse files
authored
Clarify and restrict dmu_tx_assign() errors
There are three possible cases where dmu_tx_assign() may encounter a fatal error. When there is a true lack of free space (ENOSPC), when there is a lack of quota space (EDQUOT), or when data required to perform the transaction cannot be read from disk (EIO). See the dmu_tx_check_ioerr() function for additional details of on the motivation for check for I/O error early. Prior to this change dmu_tx_assign() would return the contents of tx->tx_err which covered a wide range of possible error codes (EIO, ECKSUM, ESRCH, etc). In practice, none of the callers could do anything useful with this level of detail and simply returned the error. Therefore, this change converts all tx->tx_err errors to EIO, adds ASSERTs to dmu_tx_assign() to cover the only possible errors, and clarifies the function comment to include EIO as a possible fatal error. Reviewed-by: Alexander Motin <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Brian D Behlendorf <[email protected]> Closes #17463
1 parent 8170eb6 commit 48ce292

File tree

3 files changed

+13
-6
lines changed

3 files changed

+13
-6
lines changed

cmd/ztest.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,7 @@ ztest_zd_fini(ztest_ds_t *zd)
18161816
(ztest_random(10) == 0 ? DMU_TX_NOWAIT : DMU_TX_WAIT)
18171817

18181818
static uint64_t
1819-
ztest_tx_assign(dmu_tx_t *tx, uint64_t txg_how, const char *tag)
1819+
ztest_tx_assign(dmu_tx_t *tx, dmu_tx_flag_t txg_how, const char *tag)
18201820
{
18211821
uint64_t txg;
18221822
int error;
@@ -1829,9 +1829,10 @@ ztest_tx_assign(dmu_tx_t *tx, uint64_t txg_how, const char *tag)
18291829
if (error == ERESTART) {
18301830
ASSERT3U(txg_how, ==, DMU_TX_NOWAIT);
18311831
dmu_tx_wait(tx);
1832-
} else {
1833-
ASSERT3U(error, ==, ENOSPC);
1832+
} else if (error == ENOSPC) {
18341833
ztest_record_enospc(tag);
1834+
} else {
1835+
ASSERT(error == EDQUOT || error == EIO);
18351836
}
18361837
dmu_tx_abort(tx);
18371838
return (0);

module/zfs/dmu_tx.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ dmu_tx_try_assign(dmu_tx_t *tx)
10541054

10551055
if (tx->tx_err) {
10561056
DMU_TX_STAT_BUMP(dmu_tx_error);
1057-
return (tx->tx_err);
1057+
return (SET_ERROR(EIO));
10581058
}
10591059

10601060
if (spa_suspended(spa)) {
@@ -1190,7 +1190,8 @@ dmu_tx_unassign(dmu_tx_t *tx)
11901190
* If DMU_TX_WAIT is set and the currently open txg is full, this function
11911191
* will wait until there's a new txg. This should be used when no locks
11921192
* are being held. With this bit set, this function will only fail if
1193-
* we're truly out of space (or over quota).
1193+
* we're truly out of space (ENOSPC), over quota (EDQUOT), or required
1194+
* data for the transaction could not be read from disk (EIO).
11941195
*
11951196
* If DMU_TX_WAIT is *not* set and we can't assign into the currently open
11961197
* txg without blocking, this function will return immediately with
@@ -1279,8 +1280,11 @@ dmu_tx_assign(dmu_tx_t *tx, dmu_tx_flag_t flags)
12791280
* Return unless we decided to retry, or the caller does not
12801281
* want to block.
12811282
*/
1282-
if (err != ERESTART || !(flags & DMU_TX_WAIT))
1283+
if (err != ERESTART || !(flags & DMU_TX_WAIT)) {
1284+
ASSERT(err == EDQUOT || err == ENOSPC ||
1285+
err == ERESTART || err == EIO);
12831286
return (err);
1287+
}
12841288

12851289
/*
12861290
* Wait until there's room in this txg, or until it's been

module/zfs/dsl_dir.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,8 @@ dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t lsize, uint64_t asize,
14501450
MSEC2NSEC(10), MSEC2NSEC(10));
14511451
err = SET_ERROR(ERESTART);
14521452
}
1453+
1454+
ASSERT3U(err, ==, ERESTART);
14531455
}
14541456

14551457
if (err == 0) {

0 commit comments

Comments
 (0)